Set-Location: A positional parameter cannot be found that accepts argument _fullpath_ - powershell

I've read several similar posts but they focus on calling a PS script from within another PS script. I can do that and make the other script run, my issue is most likely linked to $MyInvocation when calling a script from another script.
Background
I have a script that half-way through needs to call another script. This other script cannot be a psm1 module because it is used as a standalone script in other processes. I begin the script with
$ScriptDir = (split-path -parent -path $MyInvocation.MyCommand.Path)
Problem
I then run
& "$ScriptDir\Another Script.ps1"
This throws the following error
Set-Location : A positional parameter cannot be found that accepts argument 'C:\Users\MyUser\Desktop\Scripts'.
At C:\Users\MyUser\Desktop\Scripts\Another Script.ps1:30 char:1
+ Set-Location = $ScriptDir
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Location], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
Here's the full section of the Another Script.ps1 that is failing
#Requires -RunAsAdministrator
$ErrorActionPreference = "Stop"
$ScriptDir = (split-path -parent -path $MyInvocation.MyCommand.Path)
Set-Location = $ScriptDir
My guess is that the Set-Location does not work because it is currently running a script inside another script. The problem I have is that this part needs to be there in order for Another Script.ps1 to run as a standalone script as well. Are there any workarounds for this, such as ignoring this step if it's run from another script?
References
https://paulcunningham.dev/powershell-invoke-expressions-spaces-in-path/
Invoke-Expression: Positional parameter cannot be found that accepts argument /s
Call PowerShell script PS1 from another PS1 script inside Powershell ISE
Powershell: A positional parameter cannot be found that accepts argument "xxx"

I can't believe I missed it: Set-Location should not have an equal sign.
It currently says
Set-Location = $ScriptDir
When it should say
Set-Location $ScriptDir

Related

Powershell - How to pass arguments with apostrophes in them?

I'm using a third party tool to do some AD manipulation. I run a powershell script and pass arguments to it.
Everything works except if that argument contains an apostrophe in it like Jerry O'Connor. I've tried lots of different escape combinations without any luck.
Here is my command: script.ps1 -name "'%name%'" and name contain is Jerry O'Connor.
The error is
Result:The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
I've tried:
script.ps1 -name "'%name%'"
script.ps1 -name \"%name%\"
script.ps1 -name ''name''
all with same error.
If you run this at the PS CMD level you'll see the error
powershell echo -name "'Jerry O'Connor'"
Anyone know how to pass an argument to script.ps1 -name "name" where that argument contains an apostrophe?
Cheers
You need to escape any ' chars. inside the value of %name% as '' to make them work inside a single-quoted PowerShell string, which from cmd.exe you can do with %name:'=''%:
From cmd.exe / a batch file:
powershell.exe -Command ./script.ps1 -name "'%name:'=''%'"
If %name% contains verbatim Jerry O'Connor, the above expands to the following, which should work as intended:
powershell.exe -Command ./script.ps1 -name "'Jerry O''Connor'"
However, you can simplify quoting if you use the -File CLI parameter instead of -Command:
powershell.exe -File ./script.ps1 -name "%name%"
See also:
For guidance on when to use -Command vs. -File, see this answer
For a comprehensive overview of the PowerShell CLI, see this answer
Try the escape character as shown here:
$Test = "`'test`'"
$Test

How to use ".\" in -file in a command file

I need to execute a command file (B.cmd) on Machine B from a Powershell script (A.ps1) on Machine A. I don't want to statically specify the path
B.cmd is supposed to execute C.ps1 which is in the same folder as B.cmd
MACHINE A: A.ps1
MACHINE B: B.cmd, C.ps1 (all in same folder)
so my command file looks like this B.cmd
#echo off
powershell.exe -file ".\C.ps1" -Iterations 10
echo
echo
pause
There's an error thrown in a A.ps1 file from which I'm calling the B.cmd file
A.ps1
Invoke-Command -ComputerName $systemName -credential $credentials -ScriptBlock {Invoke-Expression -Command: "cmd.exe /c C:\Temp\Batch\Test\B.cmd"}
A.ps1 throws error:
**The argument '.\C.ps1' to the -File parameter does not exist. Provide the path to an existing '.ps1' file as an argument to the -File parameter.**
+ CategoryInfo : NotSpecified: (The argument '....File parameter.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : XXX
How do I make the .\ work or is there an alternative or is it wrong to use the .\ for a remote execution ?
Please forgive my ignorance anywhere as I'm very very new to PS, Thank You !
If you're able to change the ABC.cmd you could use the following
powershell.exe -file "%~dp0\XYZ.ps1"
This will get the folder the ABC.cmd script is running from. Note that %~dp0 won't work in cmd for testing you'll need to test it from within a script.
So don't wrap a batch file around it. A waste of time and confuses the issue.
invoke-command -comp $computername -filepath C:\Temp\Batch\Test\XYZ.ps1
If you need to run something 10 times, do it in a loop inside your PS script.

How do I run a *.exe file from PowerShell

I have a folder at C:\Folder that has files input.xml, output.xml and licensegenerator.exe. Licensegenerator.exe takes variables that we put into input.xml and creates a temporary license for one of our programs using the output.xml file. We typically do this via command line by navigating to the C:\Folder directory, then running the command:
LicenseGenerator.exe "C:\Folder\input.xml" "C:\Folder\output.xml"
I'm attempting to write a script to do the exact same thing in PowerShell, but I'm struggling... Here's what I have:
$inputtest = "C:\Folder\Input.xml"
$outputtest = "C:\Folder\Output.xml"
$licensegen = "C:\Folder\LicenseGenerator.exe"
Invoke-Command $licensegen "$inputtest" "$outputtest"
When I run this, I get the error:
Invoke-Command : A positional parameter cannot be found that accepts argument
'C:\Folder\Output.xml'.
At line:5 char:1
+ Invoke-Command $licengegen "$inputtest" "$outputtest"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand
I have also tried running with Invoke-Expression but get the exact same error (except it says "Invoke-Expression" at the beginning). Anybody have any idea what I'm doing wrong here?
You're looking for the call operator (&):
& $licensegen "$inputtest" "$outputtest"
Invoke-Command is essentially for running scriptblocks on other hosts and/or in other user contexts.
Start-Process
is great because you can runas, redirect output, hide the child processes window and much more.
Start-Process -FilePath $licensegen -Argumentlist $inputtest,$outputtest
& "[path] command" [arguments]
Just replace Invoke-Command with &

How to pass path with spaces to script

I am trying to use PowerShell to call an EXE that is at a location/path containing spaces. When I call the script from the command line, the EXE's full path is not being passed to the script. Any ideas as to why this is happening?
PowerShell Script Contents (Untitled1.ps1)
Here is the entire script that gets called from the command line:
param(
[string] $ParamExePath
)
function Run-CallThisExe {
param(
[string] $ThisExePath
)
Write-Host "ThisExePath: " "$ThisExePath"
start-process -FilePath $ThisExePath
}
write-host "ParamExePath: " $ParamExePath
Run-CallThisExe -ThisExePath "$ParamExePath"
Command Line String
Here is the command line string being run from the PowerShell script's parent folder:
powershell -command .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
Output
Here is what is output after running the script
ParamExePath: C:\path
ThisExePath: C:\path
start-process : This command cannot be run due to the error: The system cannot
find the file specified.
At C:\sample\Untitled1.ps1:11 char:5
+ start-process -FilePath $ThisExePath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Just change this:
powershell -command .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
To This:
powershell -file .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
The -Command Parameter used to execute commands for example {Get-Date}
The -File Parameter used to Run .ps1 Script File
-Command
Executes the specified commands (and any parameters) as though they were
typed at the Windows PowerShell command prompt, and then exits, unless
NoExit is specified. The value of Command can be "-", a string. or a
script block.
-File
Runs the specified script in the local scope ("dot-sourced"), so that the
functions and variables that the script creates are available in the
current session. Enter the script file path and any parameters.
File must be the last parameter in the command, because all characters
typed after the File parameter name are interpreted
as the script file path followed by the script parameters.
Type Powershell /? to get full details on each Parameter
A couple of other ways to call it:
powershell -command .\Untitled1.ps1 -NonInteractive "-ParamExePath 'C:\path with spaces\myapp.exe'"
powershell -command ".\Untitled1.ps1 -ParamExePath 'C:\path with spaces\myapp.exe'" -NonInteractive
Note that if you pass a folder path to Powershell that has a trailing backslash it cannot handle it. e.g. -ParamFolder "C:\project folder\app\bin debug\". The parameter string ends up with a double quote at the end. So when you try to append the name of a file to it you end up with something like C:\project folder\app\bin debug"Filename.txt. In this case you have to send in a second backslash at the end.

Why doesn't Write-Host "$PSCommandPath" output my current path?

I have the following bit of code-
Set-Location "$PSCommandPath"
Write-Host "Starting script."
Write-Host "Current directory is... $PSCommandPath"
Which just returns-
Starting script.
Current directory is...
How do I remedy this?
If I had to guess, you are running an older version of PowerShell that does not support $PSCommandPath. The variable is only available in versions 3.0 and newer. From the documentation:
$PSCommandPath
Contains the full path and name of the script that is being run.
This parameter is valid in all scripts. This automatic variable is
introduced in Windows PowerShell 3.0.
So, like all undefined variables, $PSCommandPath is being treated as $null:
PS > ($undefined).GetType()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ ($undefined).GetType()
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
PS >
PS > $var = 123
PS > Write-Host "My variable: $var"
My variable: 123
PS > Write-Host "My variable: $undefined"
My variable:
PS >
To fix the problem, you need to upgrade PowerShell to version 3.0 or newer.
Also, it seems like you actually want Get-Location, which returns the current working directory:
Write-Host "Current directory is... $(Get-Location)"