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
.