Paxz
Paxz

Reputation: 3036

Forwarding output of Invoke-Command on Remote Server

To delete old files on our servers we run a remote command on the server using PowerShell and Invoke-Command:

Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose
} -Computer servername -Credential $Credential -ArgumentList $ServerPath
# The parsed credentials are from a different user than the one who opened the
# shell

The command itself works as wanted. But this only writes the deleted files to the console, instead I want to forward it to an variable / file (preferably stored on the client executing the command).

I tried the following options without sucess:

Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose 4>>"%ScriptPath%\log.txt"
} -Computer servername -Credential $Credential -ArgumentList $ServerPath
Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose >>"%ScriptPath%\log.txt"
} -Computer servername -Credential $Credential -ArgumentList $ServerPath
Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose
} 4>>"%ScriptPath%\log.txt" -Computer servername -Credential $Credential -ArgumentList $ServerPath
$log = Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose
} -Computer servername -Credential $Credential -ArgumentList $ServerPath
$log = Invoke-Command {
    Param($ServerPath)
    return (Remove-Item -Path $ServerPath -Recurse -Force -Verbose)
} -Computer servername -Credential $Credential -ArgumentList $ServerPath

A workaround maybe could be to start a remote session to the server and execute there, but I don't want to start and cancel a remote session for just one command.

Does anyone know what I did wrong with forwarding?

Upvotes: 1

Views: 2232

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200293

My initial guess was that your 3rd variant should have worked:

Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose
} 4>>"%ScriptPath%\log.txt" -Computer servername ...

However, unfortunately redirecting the verbose output stream doesn't seem to work for remote connections. To get the result you want you need to merge the verbose output stream into the success output stream inside the scriptblock, then redirect the success output stream outside the scriptblock:

Invoke-Command {
    Param($ServerPath)
    Remove-Item -Path $ServerPath -Recurse -Force -Verbose 4>&1
} >>"%ScriptPath%\log.txt" -Computer servername ...

About your other approaches:

  • #1 doesn't work because the redirection creates the file on the remote host.
  • #2 doesn't work because >> redirects the success output stream, not the verbose output stream, and it still creates the file on the remote host.
  • #4 doesn't work because $variable = ... assigns the output on the success output stream to the variable, not the output on the verbose stream.
  • #5 doesn't work for the same reason as #4. The return keyword only affects the control flow, not the output a function returns (except for output that would be created after the return statement, obviously).

Upvotes: 3

Related Questions