introduction
This morning I decided I wanted to update all my lab servers to Windows Management Framework 5.0 so I could do some work on the new DSC features that come with it. To do this, I though I’d use a GPO with a startup PowerShell script that would perform the installation of the WMF 5.0 April hotfix (available here).
On thinking about this I decided it might also be a good idea to modify the PowerShell script designed to install Microsoft Office 2013 products via GPO (see the post here). After producing the new scripts and testing them by manually running them to ensure they worked correctly, I put them into some GPOs. And that is when things started to go wrong!
Parameter Problems
The issue I ran into was that the parameters set in the GPO PowerShell script parameters seemed to misbehave in several ways. After about 6 hours of investigating and testing I’ve found the following things cause problems when you do them.
Parameter Length Limit
There seems to be a maximum number of characters that will be used in the Script Parameters setting in a GPO Startup/Shutdown/Logon/Logoff PowerShell script. The limit appears to be 207 but I can’t find official documentation of this. If script parameters longer than this limit is entered the additional characters will simply be ignored, leading to the script either failing to run or running incorrectly.
If you do run into this issue, one way around it is to edit the script and wrap all the code in a function definition and then add a call with the parameters to the end of the script after the end of the function definition. For Example:
Function Install-Application { ... Existing script code here ... } Install-Application -InstallerPath "\\Server\Software$\Notepad++\npp.6.7.8.2.Installer.exe" -InstallerParameters "/S" -RegistryKey "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Notepad++" -RegistryName "DisplayVersion" -RegistryValue "6.7.8.2" -LogPath \\Server\Logfiles$\
The PowerShell script parameters in the GPO can then be dropped as they are contained in the script itself – this is not ideal, but unless Microsoft lifts this limitation it may be required.
Parameter Quotes
There is also some odd behaviour passing parameters with quotes (single or double) to the PowerShell scripts in a GPO. I have run into several situations where the use of quotes causes the parameters to either not be passed to the script or passed with additional quotes in them. I recommend the following:
- DO NOT use single quotes around any parameters – use double quotes around string parameters only.
- DO NOT end the parameter list with a quoted parameter – this seems to cause the last parameter content to contain an extra quote.
Summary
In short, if you stick to the above when calling PowerShell scripts with parameters from GPO then you might save yourself a lot of time scratching your head.
As a quick aside, the scripts I wrote as part of this (for installing Windows QFE Hotfixes and Applications via GPO) are available on Microsoft Script Center here. I will be writing a full post on these scripts later in the week.
Parameter Length Limit is exactly 256 characters.
LikeLike
That is really good to know. Thanks for the info 🙂
LikeLike
Hi I am reply to your comments with regards to
– DO NOT use single quotes around any parameters – use double quotes around string parameters only.
– DO NOT end the parameter list with a quoted parameter – this seems to cause the last parameter content to contain an extra quote.
You may be running into these issues due to how the script is written; in particular this one from the
Gallery Technet: https://gallery.technet.microsoft.com/scriptcenter/PowerShell-to-Install-70009e38/view/Discussions#content
You are running into the issue when using: $Command=
and then calling it with & cmd.exe /c “$Command”
Depending on the command; if the install path has spaces and if the command or parameters require quotes. you will run into the issues highlighted above
Example: .\Install-Application.ps1 -InstallerPath ‘C:\temp\ATP\Azure ATP Sensor Setup.exe’ -InstallerParameters “””/quiet””” “NetFrameworkCommandLineArguments=””/q””” “AccessKey=””+xQYEBScKr1b4s7aA==”””
Rather use Start-Process instead of & cmd.exe /c “$Command”
or better still
# Call the product install, passing parameters (if any), waiting for the installer to complete and capturing the stdout/err and exitcode
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $InstallerPath
$pinfo.Arguments = $InstallerParameters
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$ExitCode = $p.ExitCode
$StdOut = $p.StandardOutput.ReadToEnd();
$StdErr = $p.StandardError.ReadToEnd();
If ($ExitCode) {Add-LogEntry -Path $LogFile -Message ” exitcode: $ExitCode”}
If ($StdOut) {Add-LogEntry -Path $LogFile -Message ” stdout: $StdOut”}
If ($StdErr) {Add-LogEntry -Path $LogFile -Message ” stderr: $StdErr”}
Switch ($ExitCode) {
0 { Add-LogEntry -Path $LogFile -Message “Install using [$Command] completed successfully.” }
1641 { Add-LogEntry -Path $LogFile -Message “Install using [$Command] completed successfully and computer is rebooting (exit code: $ExitCode).” }
default { Add-LogEntry -Path $LogFile -Message “Install using [$Command] ended with exit code $ExitCode.” }
} # ($ExitCode)
} Else {
Add-LogEntry -Path $LogFile -Message “Application is already installed.”
}
Also in the param section allowing the string to be comma separated instead of passing one long string will also help
[String[]]
[Parameter(
Position=3
)]
$InstallerParameters=”,
LikeLike
Great info! Thank you for the detail and examples. Hopefully helps others too!
LikeLike
Oh and I just worked out it was you Russell 🙂 Hahaha. Cool! I’d also say my PS code is a lot better these days (wrote this back 3.5 years ago now 😉 ).
LikeLike
Most issues are due to GPO scripts being run by gpscript.exe {/logon,/startup,etc.} which uses PowerShell.exe -File for execution.
1. During command line parsing for the PowerShell.exe call certain double quotes may get mangled, arguments are split at non-quoted whitespace (so right to use around strings containing whitespace), single quotes have no special meaning (always end up in the value as-is), etc. You can use EchoArgs.exe to check what happens. (I could find an issue with a trailing quoted parameter.)
2. Additionally, if your parameters survive this treatment, PowerShell.exe -File simply treats the values as plain strings, so passing complex types like arrays is not supported.
You can get around the latter by processing the parameter inside your script with something like:
$myparam = $myparam -split ‘,’ # In GPO, specify like: -myparam “a,b b, c”
or
$myparam = Invoke-Expression $myparam # In GPO, specify like: -myparam “‘a’,’b b’,’ c'”
LikeLike