Home > Blockchain >  Powershell Start-Process "PsExec" does not print results
Powershell Start-Process "PsExec" does not print results

Time:09-05

I'm starting a process with PsExec in the script and I want the results to appear on the screen.

The command runs without problem. There is no error message And no result message either.

How can I start the process in the same window. The -NoNewWindow argument just hides the newly opened window. It doesn't print the result to Powershell.

$PSExec = "C:\Windows\System32\PsExec.exe"
$hostname = Read-Host -Prompt 'Hostname or IP Adress'
$command1 = 'cmd /c "net stop issuser"'
$command2 = 'cmd /c "net start issuser"'

Start-Process -Wait -Filepath "$PSExec" -ArgumentList "\\$hostname $command1" -NoNewWindow
Start-Process -Wait -Filepath "$PSExec" -ArgumentList "\\$hostname $command2" -NoNewWindow

Thanks.

CodePudding user response:

getting somthing back: add the parameter -passthru to start-process.

But I think why do you use psexec and net start/stop - welcome to powershell:

$hosts = @("hostA","hostB")
$code = {
    try {
        $null = Stop-Service -Name issuer -ErrorAction:stop
        $stopOperation='success'
    }
    Catch {
        $stopOperation='failed'
        $stopException=$_
    }
    try {
        $startOperation = start-service -Name issuer -ErrorAction:stop
        $startOperation='success'
    }
    Catch {
        $startOperation='failed'
        $startException=$_        
    }
    $attrsht = @{
        Name=Issuer 
        stopOperation=$stopOperation
        stopOperationExecption=$stopException
        startOperation=$startOperation
        startOperationException=$startException
    }
    return New-Object -typename psobject -Property $attrsht
 
}
$result = invoke-command -computername $hosts -ScriptBlock $code

ok that makes much sense, but it is what it is ;-) alternatively:

Invoke-CimMethod -Query "select name from win32_service where name = 'issuer'" -MethodName startservice -ComputerName $host

Invoke-CimMethod -Query "select name from win32_service where name = 'issuer'" -MethodName stopservice -ComputerName $host

Hehe, sorry the cim cmdlets are also using WinRm behind the scenes. Back to the old/outdated wmi:

(Get-WmiObject -Query "select name from win32_service where name = 'issuer'" -ComputerName $host).startservice()

(Get-WmiObject -Query "select name from win32_service where name = 'issuer'" -ComputerName $host).stopservice()

CodePudding user response:

Why don't you use PowerShell Remoting instead of PSExec for this? That way your command would be something like this

Invoke-Command -ComputerName $hostname -ScriptBlock { Stop-Service iisuser -PassThru }
Invoke-Command -ComputerName $hostname -ScriptBlock { Start-Service iisuser -PassThru }

Of course you have to have enabled PowerShell remoting for that, but capturing output will be much easier from remote machines to your machine.

If you really want to use PSExec, you should use Invoke-Expression instead of Start-Process.

For example, starting remote notepad process:

Invoke-Expression -Command 'psexec -i \\server01 notepad'

Your command would be something like this then

Invoke-Expression -Command "psexec \\$hostname $command1"

This will open a new window and stop the service, but after is finishes it will close the window. If you want to capture the output you need to redirect that to a text file you could do something like this

Invoke-Expression -Command "psexec \\$hostname $command2" 2> C:\Scripts\output2.txt

CodePudding user response:

Note:

  • You stated that use of psexec is a must in your case - see the next section.

  • In cases where PowerShell remoting is available or can be set up, you could use Invoke-Command, which, like psexec, relays the output from remotely executed commands:

    # Add -ErrorAction Stop to abort the script if stderr output is received.
    # To act on process exit codes, examine $LASTEXITCODE in the script block.
    Invoke-Command -ComputerName $hostname { net stop issuser; net start issuser }
    

In order to invoke console applications synchronously in the current window, with their stdout and stderr streams connected to PowerShell's, invoke them directly - do not use Start-Process:

  • Start-Process cannot directly return a command's output (you can only redirect to files, with -RedirectStandardOutput and -RedirectStandardError).
  • See this answer for more information about direct invocation vs. Start-Process.

Therefore:

# Directly executes psexec and outputs its results (stdout and stderr).
# Note: 
#   -replace '"', '\"' is unfortunately needed up to a least PowerShell 7.2.x
& $PSExec \\$hostname ($command1 -replace '"', '\"')
& $PSExec \\$hostname ($command2 -replace '"', '\"')

Note: You could combine the net stop and net start commands into a single cmd /c invocation and therefore a single psexec call.

Note:

  • Since your executable path is specified as a variable, you must use &, the call operator for invocation; the same would apply if the path were quoted - see this answer for more information.

  • Unfortunately, -replace '"', '\"', which escapes embedded " characters as \", is necessary up to at least PowerShell 7.2.x, due to a long-standing bug - see this answer. (Note that your particular commands don't strictly need embedded " characters.)

  • Related