How to pass command-line arguments to a PowerShell ps1 file
Solution 1
This article helps. In particular, this section:
-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.
i.e.
powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3
means run the file myfile.ps1 and arg1 arg2 & arg3 are the parameters for the PowerShell script.
Solution 2
After digging through the PowerShell documentation, I discovered some useful information about this issue. You can't use the $args
if you used the param(...)
at the beginning of your file; instead you will need to use $PSBoundParameters
. I copy/pasted your code into a PowerShell script, and it worked as you'd expect in PowerShell version 2 (I am not sure what version you were on when you ran into this issue).
If you are using $PSBoundParameters
(and this ONLY works if you are using param(...)
at the beginning of your script), then it is not an array, it is a hash table, so you will need to reference it using the key / value pair.
param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
$Script:args+= "`$$key=" + $PSBoundParameters["$key"] + " "
}
write-host $Script:args
And when called with...
PS> ./foo.ps1 a b c d
The result is...
Num Args: 4
$p1=a $p2=b $p3=c $p4=d
Solution 3
OK, so first this is breaking a basic security feature in PowerShell. With that understanding, here is how you can do it:
- Open an Windows Explorer window
- Menu Tools -> Folder Options -> tab File Types
- Find the PS1 file type and click the advanced button
- Click the New button
- For Action put: Open
- For the Application put: "C:\WINNT\system32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" %*
You may want to put a -NoProfile
argument in there too depending on what your profile does.
Solution 4
You could declare your parameters in the file, like param:
[string]$para1
[string]$param2
And then call the PowerShell file like so .\temp.ps1 para1 para2....para10
, etc.
Solution 5
Maybe you can wrap the PowerShell invocation in a .bat
file like so:
rem ps.bat
@echo off
powershell.exe -command "%*"
If you then placed this file under a folder in your PATH
, you could call PowerShell scripts like this:
ps foo 1 2 3
Quoting can get a little messy, though:
ps write-host """hello from cmd!""" -foregroundcolor green
Daniel 'Dang' Griffith
Updated on June 23, 2021Comments
-
Daniel 'Dang' Griffith about 3 years
For years, I have used the
cmd/DOS/Windows
shell and passed command-line arguments to batch files. For example, I have a file,zuzu.bat
and in it, I access%1
,%2
, etc. Now, I want to do the same when I call aPowerShell
scriptwhen I am in a Cmd.exe shell
. I have a script,xuxu.ps1
(and I've added PS1 to my PATHEXT variable and associated PS1 files with PowerShell). But no matter what I do, I seem unable to get anything from the$args
variable. It always has length 0.If I am in a
PowerShell
shell, instead ofcmd.exe
, it works (of course). But I'm not yet comfortable enough to live in the PowerShell environment full time. I don't want to typepowershell.exe -command xuxu.ps1 p1 p2 p3 p4
. I want to typexuxu p1 p2 p3 p4
.Is this possible, and if so, how?
The sample I cannot get to work is trivial, foo.ps1:
Write-Host "Num Args:" $args.Length; foreach ($arg in $args) { Write-Host "Arg: $arg"; }
The results are always like this:
C:\temp> foo Num Args: 0 C:\temp> foo a b c d Num Args: 0 c:\temp>
-
Keith Hill almost 15 yearsI think the key is in your step 6 where you pass in the parameters to powershell.exe. Daniel says he has associated PS1 files with PowerShell but that doesn't pass arguments without the extra %1 %* specs. Also note that the -File parameter is not available in V1. It is new to V2.
-
EBGreen almost 15 yearsGood catch regarding the -file parameter I had forgotten that.
-
Daniel 'Dang' Griffith almost 15 yearsI'll have to install V2 before I can try your suggestion. Thanks. When you say this is breaking a basic security feature, what does "this" you mean? Calling a PowerShell script from Cmd.exe as though it were a .com/.bat/.exe file? Passing parameters to the script?
-
EBGreen almost 15 yearsSorry I should have been more clear. The calling the script without explicitly calling powershell.exe. I'm not saying it is a significant security feature for you personally and it is security through obscurity which I am not always a fan of anyway.
-
Keith Hill almost 15 yearsTo add to EBGreen's comment, the basic security problem that PowerShell's tries to avoid is folks double-clicking on PS1 files attached to email and having the script run. That's why PS1 files are only associated with an editor by default. Microsoft really doesn't want a PowerShell version of the ILoveYou virus e.g. "LOVE-LETTER-FOR-YOU.TXT.ps1"
-
DeanOC almost 10 years+1 for showing the triple quotes. that had me stuck for a while.
-
Teoman shipahi about 8 yearswhat is the meaning of "%1" %* ?
-
thdoan about 6 yearsThis still doesn't help with what the op wants ("I want to type
xuxu p1 p2 p3 p4
"). -
Eric Hansen almost 5 yearsThis doesn't account for OP starting his command line with powershell.exe or pwsh. The behavior changes when OP does that.
-
Randall Borck almost 5 years@EricHansen I don't know what you mean, I get the same result either way: ` Powershell>powershell.exe .\ParamTest.ps1 val1 val2 val3 val4 Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4 `
-
Eric Hansen almost 5 years@RandallBrock The behavior of the arguments changes for me. If I'm in CMD/batch, and I do something like
pwsh .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4
, it really doesn't like that. On the other hand, if I'm in PowerShell and do.\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4
, that works like I'd expect. I've heard that this is how it's intended to function due to "security reasons." -
Randall Borck almost 5 years@EricHansen I wonder if it is a version thing. For me, pwsh launches 6.2.0, but powershell.exe launches 5.1.17134.858, both of which produce the same results listed:
Powershell>pwsh .\ParamTest.ps1 val1 val2 val3 val4
yields:Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4
-
Randall Borck almost 5 years@EricHansen One other thing I notice in your comment is that you are passing 2 of your variables as named parameters for parameters that aren't named (if you're using my script). One interesting thing that happens is that
arg1
andlistOfArgs
end up in the $args variable as-arg1 val1 -listofargs val2
and val3 and val4 end up in $p1 and $p2. Is this what you are referring to? -
Eric Hansen almost 5 yearsI wasn't going off of your script. In my head, I was imagining arg1 as [string] and arg2 as [string[]]. Sorry if I'm dragging this too off topic.
-
Timo almost 5 yearsI get:
param : Die Benennung "param" wurde nicht als Name eines Cmdlet, einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt.
. I call it on the ps terminal:greatstuff.ps1 argu1
-
Randall Borck almost 5 years@Timo I don't know what you are doing exactly, but
param
is a language construct, however it must be the first thing in the file. Did you declare a variable or something else before it? More info here: docs.microsoft.com/en-us/powershell/module/… -
David Airapetyan about 4 yearsI'm not sure I buy the security argument - for me Powershell is just .cmd on steroids so I'd expect the same out-of-the-box functionality as .bat/.cmd files (I'm essentially using Powershell where I would have used batch files before).
-
David Airapetyan about 4 yearsWorth noting that this requires running the cmd prompt as Administrator. Also, I am struggling to actually make it work on Windows 10 version 1903 (18362.778) - all commands run successfully but the arguments still don't get passed in. I think wrapping with a .bat file is the most portable solution.
-
David Airapetyan about 4 yearsAlso, it looks like these instructions won't work on Windows 10 - but @ta32's answer using ftype should (but also don't work)
-
DennisVM-D2i over 2 yearsJust for completeness - regarding quoting (and passing tab chars & interoperability); if you have a 'SetTabEV.cmd' named Command Prompt script, to set a "Tab" named environment variable to be set to/have a value of a tab character - 'Set Tab= ', run the script, then you can also use it with 4 quotes; e.g. from the Command Prompt: ``` SetTab.cmd powershell MyScript.ps1 -dol """"1%Tab%Dennis%Tab%2047"""" ``` But only 3/triple-quoting is required if you use/pass the PowerShell tab character escape-sequence instead - '
t': ``` powershell MyScript.ps1 -dol """1
tDennis`t2047""" ``` -
Andrei Krasutski about 2 yearsbut what about the gaps? if arg1 it's a path with space.