JohnLBevan
JohnLBevan

Reputation: 24430

Run batch file on UNC path with parameters and capture output to variable without Community Extensions

I'd like to run a command such as:

pushd \\myServer\share\scripts
myBatchFile.bat param1 param2 "parameter 3"
popd

Only initiating through powershell.

NB: The name of the batch file is held in a variable, as are each of the parameters.

function Escape-StringForCmd($a)
{
    if(($a -like '*"*') -or ($a -like '* *'))
    {
        ('"{0}"' -f ($a -replace '"','""'))
    }
    else
    {
        $a
    }
}

$batch = "myBatchFile.bat"
$p1 = "param1"
$p2 = "param2"
$p3 = "parameter 3"

$batch = Escape-StringForCmd($batch)
$p1 = Escape-StringForCmd($p1)
$p2 = Escape-StringForCmd($p2)
$p3 = Escape-StringForCmd($p3)

pushd \\myServer\share\scripts

cmd.exe /c $batch $p1 $p2 $p3
#above fails; no error returned; I think because cmd doesn't like the UNC path, so reverts to the system directory

Start-Process "cmd.exe" -ArgumentList "/c",$batch,$p1,$p2,$p3 -NoNewWindow -Wait -WorkingDirectory "\\myServer\share\scripts"
#above also fails; not sure why as looks healthy when running outside of ps1 file

popd

I've also interested in capturing the output - though as at present the batch file's not being run I'll focus on that initially.

I've not yet tried the ProcessStartInfo solution (see link below) as it seems start-process, or simply cmd.exe /c should work (certainly when I've run tests outside of a ps1 file this has worked), but I'll resort to trying that method shortly.

ProcessStartInfo solution: Powershell: Capturing standard out and error with Process object

Upvotes: 2

Views: 2003

Answers (2)

JohnLBevan
JohnLBevan

Reputation: 24430

Using @JNK's answer along with the below hack, I found a way to get this to work

$tempBatchName = ".\~myTempBatchFile.bat" #put this in a variable so we can easily amend if required

"
pushd \\myServer\share\scripts
$batch $p1 $p2 $p3
popd
" | out-file $tempBatchName -encoding ascii

$MyCmd = ("{0} *>&1" -f $tempBatchName)

$ReturnOutput = Invoke-Expression $MyCmd
$ReturnOutput | out-file ("{0}.log" -f $tempBatchName)
remove-item $tempBatchName

Upvotes: 2

JNK
JNK

Reputation: 65167

Is there a reason you can't use invoke-expression for this?

$MyCmd = "$batch $p1 $p2 $p3 *>&1"

$ReturnOutput = Invoke-Expression $MyCmd

The *>&1 puts all output from the StdErr and StdOut to the output stream.

More info on redirection operators here.

Upvotes: 1

Related Questions