PsExec引发错误消息,但没有任何问题

所以我们在自动化中使用PsExec来安装虚拟机,因为我们不能在Windows 2003机器上使用ps远程会话。 一切都很好,没有问题,但是PsExec不断抛出错误,即使每个命令都没有正确执行。 例如:

D:\tools\pstools\psexec.exe $guestIP -u $global:default_user -p $global:default_pwd -d -i C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "Enable-PSRemoting -Force" 

启用访客的PsRemoting,但也会引发此错误消息:

 psexec.exe : Bei D:\Scripts\VMware\VMware_Module5.ps1:489 Zeichen:29 + D:\tools\pstools\psexec.exe <<<< $guestIP -u $global:default_user -p $global:default_pwd -d -i C:\Windows\System32\WindowsPowerShell\ v1.0\powershell.exe -command "Enable-PSRemoting -Force" + CategoryInfo : NotSpecified: (:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError PsExec v1.98 - Execute processes remotely Copyright (C) 2001-2010 Mark Russinovich Sysinternals - www.sysinternals.com Connecting to 172.17.23.95...Starting PsExec service on 172.17.23.95...Connecting with PsExec service on 172.17.23.95...Starting C:\Windows\ System32\WindowsPowerShell\v1.0\powershell.exe on 172.17.23.95... C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe started on 172.17.23.95 with process ID 2600. 

这些types的错误信息apear总是不pipe我如何使用psexec,如引号,与vriables /固定值,其他标志等。有没有人有一个想法,我可以解决这个问题? 这不是一个真正的问题,但它使屁股发现错误是一个痛苦,因为“错误”无处不在。 禁用psexec的错误信息也将有所帮助…

这是因为当进程写入STDERR时,PowerShell有时会报告一个NativeCommandError。 PsExec写入信息

 PsExec v1.98 - Execute processes remotely Copyright (C) 2001-2010 Mark Russinovich Sysinternals - www.sysinternals.com 

到STDERR这意味着它可以导致这一点。

有关更多信息,请参阅以下问题/答案:

将stderr重定向到null对我来说最有效。 看下面的链接

使用IDE时从Powershell调用第三方可执行文件时出错

以下是该链接的相关部分:

为了避免这种情况,你可以将stderr重定向到null,例如:

杜2> $ null本质上,控制台主机和ISE(以及远程处理)不同地处理stderr流。 在控制台主机上,PowerShell支持像edit.com这样的应用程序与其他将颜色输出和错误写入屏幕的应用程序一起工作非常重要。 如果I / O流未在控制台主机上重定向,则PowerShell会为本机EXE提供控制台句柄以直接写入。 这绕过了PowerShell,所以PowerShell无法看到写入错误,因此无法通过$ error或通过写入PowerShell的stderr流来报告错误。 ISE和远程处理不需要支持这种情况,所以他们确实看到stderr上的错误,然后写错误和更新$错误。

。\ PsExec.exe \ $ hostname -u $ script:userName -p $ script:password / accepteula -h cmd / c $ powerShellArgs 2> $ null

我为PowerShell创建了一个psexec包装,这可能对浏览此问题的人有所帮助:

 function Return-CommandResultsUsingPsexec { param( [Parameter(Mandatory=$true)] [string] $command_str, [Parameter(Mandatory=$true)] [string] $remote_computer, [Parameter(Mandatory=$true)] [string] $psexec_path, [switch] $include_blank_lines ) begin { $remote_computer_regex_escaped = [regex]::Escape($remote_computer) # $ps_exec_header = "`r`nPsExec v2.2 - Execute processes remotely`r`nCopyright (C) 2001-2016 Mark Russinovich`r`nSysinternals - www.sysinternals.com`r`n" $ps_exec_regex_headers_array = @( '^\s*PsExec v\d+(?:\.\d+)? - Execute processes remotely\s*$', '^\s*Copyright \(C\) \d{4}(?:-\d{4})? Mark Russinovich\s*$', '^\s*Sysinternals - www\.sysinternals\.com\s*$' ) $ps_exec_regex_info_array = @( ('^\s*Connecting to ' + $remote_computer_regex_escaped + '\.{3}\s*$'), ('^\s*Starting PSEXESVC service on ' + $remote_computer_regex_escaped + '\.{3}\s*$'), ('^\s*Connecting with PsExec service on ' + $remote_computer_regex_escaped + '\.{3}\s*$'), ('^\s*Starting .+ on ' + $remote_computer_regex_escaped + '\.{3}\s*$') ) $bypass_regex_array = $ps_exec_regex_headers_array + $ps_exec_regex_info_array $exit_code_regex_str = ('^.+ exited on ' + $remote_computer_regex_escaped + ' with error code (\d+)\.\s*$') $ps_exec_args_str = ('"\\' + $remote_computer + '" ' + $command_str) } process { $return_dict = @{ 'std_out' = (New-Object 'system.collections.generic.list[string]'); 'std_err' = (New-Object 'system.collections.generic.list[string]'); 'exit_code' = $null; 'bypassed_std' = (New-Object 'system.collections.generic.list[string]'); } $process_info = New-Object System.Diagnostics.ProcessStartInfo $process_info.RedirectStandardError = $true $process_info.RedirectStandardOutput = $true $process_info.UseShellExecute = $false $process_info.FileName = $psexec_path $process_info.Arguments = $ps_exec_args_str $process = New-Object System.Diagnostics.Process $process.StartInfo = $process_info $process.Start() | Out-Null $std_dict = [ordered] @{ 'std_out' = New-Object 'system.collections.generic.list[string]'; 'std_err' = New-Object 'system.collections.generic.list[string]'; } # $stdout_str = $process.StandardOutput.ReadToEnd() while ($true) { $line = $process.StandardOutput.ReadLine() if ($line -eq $null) { break } $std_dict['std_out'].Add($line) } # $stderr_str = $process.StandardError.ReadToEnd() while ($true) { $line = $process.StandardError.ReadLine() if ($line -eq $null) { break } $std_dict['std_err'].Add($line) } $process.WaitForExit() ForEach ($std_type in $std_dict.Keys) { ForEach ($line in $std_dict[$std_type]) { if ((-not $include_blank_lines) -and ($line -match '^\s*$')) { continue } $do_continue = $false ForEach ($regex_str in $bypass_regex_array) { if ($line -match $regex_str) { $return_dict['bypassed_std'].Add($line) $do_continue = $true break } } if ($do_continue) { continue } $exit_code_regex_match = [regex]::Match($line, $exit_code_regex_str) if ($exit_code_regex_match.Success) { $return_dict['exit_code'] = [int] $exit_code_regex_match.Groups[1].Value } elseif ($std_type -eq 'std_out') { $return_dict['std_out'].Add($line) } elseif ($std_type -eq 'std_err') { $return_dict['std_err'].Add($line) } else { throw 'this conditional should never be true; if so, something was coded incorrectly' } } } return $return_dict } }