问题
Inspired by this post, I created the script below DOSCommands.ps1
Function Invoke-DOSCommands {
Param(
[Parameter(Position=0,Mandatory=$true)]
[String]$cmd,
[String]$tmpname = $(([string](Get-Random -Minimum 10000 -Maximum 99999999)) + ".cmd"),
[switch]$tmpdir = $true)
if ($tmpdir) {
$cmdpath = $(Join-Path -Path $env:TEMP -ChildPath $tmpname);
}
else {
$cmdpath = ".\" + $tmpname
}
Write-Debug "tmpfile: " + $cmdpath
Write-Debug "cmd: " + $cmd
echo $cmd | Out-File -FilePath $cmdpath -Encoding ascii;
& cmd.exe /c $cmdpath | Out-Null
}
Invoke-DOSCommands "Echo ""Hello World""", -tmpdir $false
However, on execution it returns this error:
Invoke-DOSCommands : Cannot process argument transformation on parameter 'cmd'. Cannot convert value to type S ystem.String.
At DOSCommands.ps1:20 char:19
+ Invoke-DOSCommands <<<< "Echo ""Hello World""", -tmpdir $false
+ CategoryInfo : InvalidData: (:) [Invoke-DOSCommands], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Invoke-DOSCommands
I've searched for this error but can't figure it out. It seems to me that it can't convert the string type correctly! Please help!
回答1:
Your best bet is to use --% in PowerShell V3 or higher. See this blog post I wrote on using --%. In V1/V2 the situation is just bad as you can see in this Connect bug on the issue. The common workaround in V1/V2 is to use Start-Process or .NET's Process.Start. From those list of workarounds, I kind of like this one:
[System.Diagnostics.Process]::Start("Cmd", "/c anything you want to put here with embedded quotes, and variables")
Which is effectively what --% does to the parsing of all parameters following it i.e. it parses them in a dumbed down mode similar to cmd.exe parameter parsing including expanding env vars referenced with %envVarName%.
回答2:
Alright based on the answer by Keith I've modified my function as follows:
Function Invoke-DOSCommands {
Param(
[Parameter(Position=0,Mandatory=$true)]
[String]$cmd)
$comspec = $env:comspec # have to get comspec
$cwd = Get-Location # ensure correct working directory
$pstartinfo = new-object -type System.Diagnostics.processStartInfo -Argumentlist "$comspec","/c $cmd"
$pstartinfo.WorkingDirectory= $cwd
Write-Debug "cmd: $pstartinfo.FileName"
Write-Debug "args: $pstartinfo.Arguments"
Write-Debug "dir: $pstartinfo.WorkingDirectory"
#[System.Diagnostics.Process]::Start("Cmd", "/c $cmd")
[System.Diagnostics.Process]::Start($pstartinfo)
}
Invoke-DOSCommands "Echo ""Hello World"" & dir & pause" # testing function
来源:https://stackoverflow.com/questions/21524101/cannot-process-argument-transformation