简体   繁体   中英

Powershell - capture output from Invoke-Command running exe on remote machine

I need to configure the auditing policy on a collection of remote servers. I'm trying to use the Invoke-Command commandlet to run auditpol.exe on each server. The issue is that I can't seem to capture any output from the auditpol command.

I tried the obvious (assigning the result of Invoke-Command to a string):

> $command =  "Start-Process -FilePath `"auditpol.exe`" -ArgumentList `"/set`", `"/subcategory`", `"```"File System```"`", `"/success:enable`""
> $command
"auditpol.exe" -ArgumentList "/set", "/subcategory", "`"File System`"", "/success:enable"

> $out = Invoke-Command -ComputerName MyServer -ScriptBlock {$command}
> $out
>

But $out is empty.

I also tried the method detailed in this MSDN blog using Wait-Job and Receive-Job. The results are somewhat promising, but inconclusive:

> $command =  "Start-Process -FilePath `"auditpol.exe`" -ArgumentList `"/set`", `"/subcategory`", `"```"File System```"`", `"/success:enable`""
> $command
"auditpol.exe" -ArgumentList "/set", "/subcategory", "`"File System`"", "/success:enable"
> $job = Invoke-Command -ComputerName MyServer -ScriptBlock {$command} -AsJob
> Wait-Job $job

Id              Name            State      HasMoreData     Location             Command                  
--              ----            -----      -----------     --------             -------                  
3               Job3            Completed  True            MyServer  $command

> $output = Receive-Job $job
> $output
>

I was hoping that I would be able to capture the actual output from auditpol.exe using Receive-Job, but as indicated above, that doesn't seem to be the case.

I do get some information from Wait-Job. According to the Microsoft documentation of Wait-Job State=Completed should indicate that the operation was successful, but I'm not entirely convinced that it really has visibility into whether or not the auditpol operation was successful or not. Any advice would be greatly appreciated!

To run a console program synchronously and with its stdout and stderr output available for capture invoke it directly - do not use Start-Process (whether you run that program locally or remotely, via Invoke-Command ):

$out = Invoke-Command -ComputerName MyServer -ScriptBlock {
  auditpol.exe /set /subcategory 'File System' /success:enable
}

If you also want to capture stderr output, append 2>&1 to the auditpol.exe call.


If your script block is stored in local variable $command (as a [scriptblock] instance, not as a string ), simply pass it directly to -ScriptBlock :

# Create a script block (a piece of code that can be executed on demand later)
# and store it in a (local) variable.
# Note that if you were to use any variable references inside the block,
# they would refer to variables on the remote machine if the block were to be
# executed remotely.
$command = { auditpol.exe /set /subcategory 'File System' /success:enable }

# Pass the script block to Invoke-Command for remote execution.
$out = Invoke-Command -ComputerName MyServer -ScriptBlock $command

As for what you tried :

$out = Invoke-Command -ComputerName MyServer -ScriptBlock {$command}

You're passing a script-block literal ( { ... } ) that, when it is executed on the target computer, references a variable named $command .

Generally, simply referencing a variable outputs its value - it doesn't execute anything.

More importantly, however, $command is a local variable, which the remotely executing script block cannot see, so referencing the there-uninitialized $command variable will effectively yield $null .

In short: your Invoke-Command call does nothing and returns $null .


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM