How do I pass a string parameter to Powershell for ConvertFrom-StringData from command line? - powershell

I'm having trouble running powershell with a script that should use a variable number of parameters.
The script file looks like this:
param( [string]$paramString )
$params = ConvertFrom-StringData $paramString
$params
Running the script directly in powershell yields the expected result:
[PS] C:\some\path>.\test.ps1 "a=foo `n b=bar `n c=moo"
Name Value
---- -----
c moo
a foo
b bar
Calling powershell from the command line with the same script and parameters shows this:
C:\some\path>powershell -nologo -file ./test.ps1 "a=foo `n b=bar `n c=moo"
Name Value
---- -----
a foo `n b=bar `n c=moo
It seems like the passed string is in some format so the ConvertFrom-StringData function is unable to parse it anymore.

Approach with -File is problematic because the parameter is not evaluated by cmd (at it is in PowerShell) and new lines equivalents are not expanded, they are passed in literally.
The problem can be solved if we still let PowerShell to do that by using -Command instead:
powershell -nologo -command "./test.ps1 ""a=foo `n b=bar `n c=moo"""
It is ugly: we have to double every inner " in the command. But it works. (The command can be defined by several parameters; I just prefer to use a single parameter: this way looks simpler to me).

Use single quote to pass parameters to powershell with script like this:
C:\some\path>powershell .\test.ps1 'a=foo' 'b=bar' 'c=moo'

Related

Multiline powershell function inside batch script

I want to run .bat-script which calls some powershell function inside it. Function is not so small, so I want to split it. But I cannot do it, escape symbols doesn`t help ( ` ,^).
Script example:
set file=%1
set function="$file=$Env:file; ^
$hash = CertUtil -hashfile $file SHA256 | Select -Index 1"
powershell -command %function%
You can leave the quote at the end of each line like so:
set file=%1
set function="$file=$Env:file; "^
"$hash = CertUtil -hashfile $file SHA256 | Select -Index 1; "^
"example break line further...."
powershell -command %function%
The ^ works as multiline character but it also escapes the first character, so also a quote would be escaped.
Do not mix batchfile syntax with PowerShell. As #Stephan mentioned $function= won't work in batch file. You need to use set function= instead. Let's say I want to execute the following:
Get-Process
Get-ChildItem
Then the code should look like this:
set function=Get-Process; ^
Get-ChildItem;
And you start PowerShell with:
powershell -noexit -command %function%
-noexit added so that you can verify that the code was successfully executed.
Also keep in mind that what you pass to PowerShell is batch multiline and in PowerShell it's visible as one line so you have to remember about semicolon (which you actually do but I'm leaving this comment here for future readers).
There's also another option how to pass variable from batch script to PowerShell. You can do it like this:
set name=explorer
set function=get-process $args[0]; ^
get-childitem
powershell -noexit -command "& {%function% }" %name%
Explanation:
$args[0] represents first argument passed to the scriptblock. To pass that argument, add %name% after the scriptblock while starting powershell. Also, as pointed out in this answer (credits to #Aacini for pointing this out in comments), you have to add & operator and keep your scriptblock inside curly brackets { }.
Sidenote: to be honest, I'd avoid running scripts like this. Much simpler way would be to just save the file as .ps1 and run this in your batch file:
powershell -noexit -file .\script.ps1

Call program from powershell.exe command and manipulate parameters

I'm trying to call an EXE file program that accepts command line parameters from PowerShell. One of the parameters I'm required to send is based on the string length of the parameters.
For example,
app.exe /param1:"SampleParam" /paramLen:"SampleParam".length
When I run the above, or for example:
notepad.exe "SampleParam".length
Notepad opens with the value 11 as expected.
I would like to achieve the same result when calling PowerShell from cmd / task scheduler.
For example,
powershell notepad.exe "SampleParam".length
But when I do that I get "SampleParam".length literally instead of the "SampleParam".length calculated value.
The expected result was:
running notepad.exe 11
Use the -Command parameter for powershell.exe:
powershell -Command "notepad.exe 'SampleParam'.length"
Be careful with the "'s since they can be picked up by the Windows command processor. This will also work:
powershell -Command notepad.exe 'SampleParam'.length
But this will not:
powershell -Command notepad.exe "SampleParam".length
I'd suggest using variables to store your string, etc.
$Arg1 = 'SampleParam'
## This will try to open a file named 11.txt
powershell notepad.exe $Arg1.Length
In your specific example:
app.exe /param1:$Arg1 /paramLen:$Arg1.Length
Utilizing splatting:
## Array literal for splatting
$AppArgs = #(
"/param1:$Arg1"
"/paramLen:$($Arg1.Length)"
)
app.exe #AppArgs

Run MSBuild from PowerShell can't find project file [duplicate]

I've just tested this on PowerShell v1.0. Setup is as follows:
Id CommandLine
-- -----------
1 $msbuild = "C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe"
4 $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"
.
This line fails with an unintuitive error message:
Id CommandLine
-- -----------
5 & $msbuild $a
.
This line fails because & expects the first argument to be the command itself.
Id CommandLine
-- -----------
10 & "$msbuild $a"
.
This line works:
Id CommandLine
-- -----------
16 cmd /c "$msbuild $a"
.
Please explain. I'm more interested in why the & syntax isn't working, than an MSBuild-specific workaround.
Ugh.
$collectionOfArgs = #("C:\some\project\or\other\src\Solution.sln",
"/target:Clean", "/target:Build")
& $msbuild $collectionOfArgs
This works. & takes a collection of arguments, so you must split up strings containing multiple arguments into a collection of string arguments.
The issues you are seeing results from PowerShell parsing arguments. In the first example, when PowerShell sees $a it passes it as a single parameter msbuild. We can see this using the echoargs utility from PSCX:.
PS> $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"
PS> & echoargs $a
Arg 0 is <C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build>
The second example is even worse because you are telling powershell to invoke "$echoargs $a" as the command name and it isn't a valid command name.
The third line works because CMD.exe gets the expanded form of "$echoargs $a" as a single argument which is parses and executes:
You have a couple of options here. First I do it this way:
PS> & $msbuild C:\some\project\or\other\src\Solution.sln `
/target:Clean /target:Build
The other option is to use Invoke-Expression like so:
PS> Invoke-Expression "$msbuild $a"
In general I try to be very careful with Invoke-Expression particularly if any part of the string that gets invoked is provided by the user.
You can also try using the free Invoke-MsBuild powershell script/module. This essentially gives you an Invoke-MsBuild PowerShell cmdlet that you can call instead of trying to invoke the msbuild.exe manually yourself.
That works well for me:
PS> cmd.exe /c 'C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe' /target:Clean /target:Build 'C:\some\project\or\other\src\Solution.sln'

Passing a variable to a powershell script via command line

I am new to powershell, and trying to teach myself the basics. I need to write a ps script to parse a file, which has not been too difficult.
Now I want to change it to pass a variable to the script. that variable will be the parsing string. Now, the variable will always be 1 word, and not a set of words or multiple words.
This seems uber simple yet is posing a problem for me. Here is my simple code:
$a = Read-Host
Write-Host $a
When I run the script from my command line the variable passing doesn't work:
.\test.ps1 hello
.\test.ps1 "hello"
.\test.ps1 -a "hello"
.\test.ps1 -a hello
.\test.ps1 -File "hello"
As you can see, I have tried many methos with no success, of the script taking the value an outputting it.
The script does run, and waits for me to type a value, and when I do, it echos that value.
I just want it to output my passed in value, what minuscule thing am I missing?
Thank you.
Make this in your test.ps1, at the first line
param(
[string]$a
)
Write-Host $a
Then you can call it with
./Test.ps1 "Here is your text"
Found here (English)
Here's a good tutorial on Powershell params:
PowerShell ABC's - P is for Parameters
Basically, you should use a param statement on the first line of the script
param([type]$p1 = , [type]$p2 = , ...)
or use the $args built-in variable, which is auto-populated with all of the args.
Declare the parameter in test.ps1:
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$input_dir,
[Parameter(Mandatory=$True)]
[string]$output_dir,
[switch]$force = $false
)
Run the script from Run OR Windows Task Scheduler:
powershell.exe -command "& C:\FTP_DATA\test.ps1 -input_dir C:\FTP_DATA\IN -output_dir C:\FTP_DATA\OUT"
or,
powershell.exe -command "& 'C:\FTP DATA\test.ps1' -input_dir 'C:\FTP DATA\IN' -output_dir 'C:\FTP DATA\OUT'"
Passed parameter like below,
Param([parameter(Mandatory=$true,
HelpMessage="Enter name and key values")]
$Name,
$Key)
.\script_name.ps1 -Name name -Key key
Using param to name the parameters allows you to ignore the order of the parameters:
ParamEx.ps1
# Show how to handle command line parameters in Windows PowerShell
param(
[string]$FileName,
[string]$Bogus
)
write-output 'This is param FileName:'+$FileName
write-output 'This is param Bogus:'+$Bogus
ParaEx.bat
rem Notice that named params mean the order of params can be ignored
powershell -File .\ParamEx.ps1 -Bogus FooBar -FileName "c:\windows\notepad.exe"

Pass parameter from a batch file to a PowerShell script

In my batch file, I call the PowerShell script like this:
powershell.exe "& "G:\Karan\PowerShell_Scripts\START_DEV.ps1"
Now, I want to pass a string parameter to START_DEV.ps1. Let's say the parameter is w=Dev.
How can I do this?
Let's say you would like to pass the string Dev as a parameter, from your batch file:
powershell -command "G:\Karan\PowerShell_Scripts\START_DEV.ps1 Dev"
put inside your powershell script head:
$w = $args[0] # $w would be set to "Dev"
This if you want to use the built-in variable $args. Otherwise:
powershell -command "G:\Karan\PowerShell_Scripts\START_DEV.ps1 -Environment \"Dev\""
and inside your powershell script head:
param([string]$Environment)
This if you want a named parameter.
You might also be interested in returning the error level:
powershell -command "G:\Karan\PowerShell_Scripts\START_DEV.ps1 Dev; exit $LASTEXITCODE"
The error level will be available inside the batch file as %errorlevel%.
Assuming your script is something like the below snippet and named testargs.ps1
param ([string]$w)
Write-Output $w
You can call this at the commandline as:
PowerShell.Exe -File C:\scripts\testargs.ps1 "Test String"
This will print "Test String" (w/o quotes) at the console. "Test String" becomes the value of $w in the script.
When a script is loaded, any parameters that are passed are automatically loaded into a special variables $args. You can reference that in your script without first declaring it.
As an example, create a file called test.ps1 and simply have the variable $args on a line by itself. Invoking the script like this, generates the following output:
PowerShell.exe -File test.ps1 a b c "Easy as one, two, three"
a
b
c
Easy as one, two, three
As a general recommendation, when invoking a script by calling PowerShell directly I would suggest using the -File option rather than implicitly invoking it with the & - it can make the command line a bit cleaner, particularly if you need to deal with nested quotes.
Add the parameter declaration at the top of ps1 file
test.ps1
param(
# Our preferred encoding
[parameter(Mandatory=$false)]
[ValidateSet("UTF8","Unicode","UTF7","ASCII","UTF32","BigEndianUnicode")]
[string]$Encoding = "UTF8"
)
write ("Encoding : {0}" -f $Encoding)
Result
C:\temp> .\test.ps1 -Encoding ASCII
Encoding : ASCII
The answer from #Emiliano is excellent. You can also pass named parameters like so:
powershell.exe -Command 'G:\Karan\PowerShell_Scripts\START_DEV.ps1' -NamedParam1 "SomeDataA" -NamedParam2 "SomeData2"
Note the parameters are outside the command call, and you'll use:
[parameter(Mandatory=$false)]
[string]$NamedParam1,
[parameter(Mandatory=$false)]
[string]$NamedParam2