2013-08-22 17 views
7

Używamy PsExec w naszych automatach do instalowania maszyn wirtualnych, ponieważ nie możemy używać psowych sesji zdalnych z naszymi maszynami z systemem Windows 2003. Wszystko działa wspaniale i nie ma problemów, ale PsExec ciągle popełnia błędy podczas rzucania, nawet jeśli wszystkie polecenia są wykonywane bez poprawnego działania. Na przykład:PsExec zgłasza komunikaty o błędach, ale działa bez żadnych problemów.

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" 

Umożliwia PsRemoting na gościa, ale także generuje komunikat o błędzie:

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. 

Tego rodzaju komunikaty o błędach wyświetlane, zawsze bez względu na to w jaki sposób mogę korzystać psexec, jak z cytatami, z vriables/ustalonymi wartościami, innymi flagami itp. Czy ktoś ma pomysł jak to naprawić? To nie jest prawdziwy problem, ale sprawia, że ​​znalezienie błędów to ból w dupie, ponieważ "błędy" są wszędzie. Wyłączenie komunikatów o błędach psexec w ogóle również pomogłoby ...

+1

mam ten sam problem, a ja używać '$ ErrorActionPreference = "SilentlyContinue"' przed poleceniem PsExec. Ale to nie jest prawdziwe rozwiązanie. – plunkets

+0

Cóż, nie jest to najlepszy pomysł, ale o wiele lepszy niż moje "rozwiązanie". Przypuszczam, że napiszę funkcję cichą psexec, włączając i wyłączając ErrorActionPreference przed komendą psexec. Przynajmniej mogę wyłączyć komunikat o błędzie, który wyraźnie nie jest. – Simons0n

+0

Sprawdź to; http://stackoverflow.com/a/2095623/469777 –

Odpowiedz

12

Dzieje się tak, ponieważ PowerShell czasami zgłasza NativeCommandError, gdy proces zapisuje do STDERR. PsExec zapisuje infolinie do STDERR, co oznacza, że ​​może to spowodować.

Aby uzyskać więcej informacji, zobacz te pytania/odpowiedzi:

+1

Nie dziękuję wystarczająco za tę odpowiedź i wszystkie linki. –

2

przekierować stderr do null pracował dla mnie najlepsza. patrz niżej linkiem

Error when calling 3rd party executable from Powershell when using an IDE

Oto odnośny odcinek z tego linku:

Aby tego uniknąć można przekierować stderr null np

du 2> $ zerowy Zasadniczo Host konsoli i ISE (a także Remoting) traktują strumień stderr w różny sposób. Na hoście konsoli ważne było, aby PowerShell obsługiwał aplikacje, takie jak edit.com, aby współpracować z innymi aplikacjami, które zapisują kolorowe wydruki i błędy na ekranie. Jeśli strumień I/O nie jest przekierowywany na hoście konsoli, PowerShell zapewnia natywnemu EXE uchwyt konsoli do bezpośredniego zapisu. Pomija to PowerShell, więc PowerShell nie widzi błędów napisanych, więc nie może zgłosić błędu poprzez błąd $ lub zapisując w strumieniu stderr PowerShella. ISE i usługi zdalne nie muszą obsługiwać tego scenariusza, aby wyświetlały błędy na stderr, a następnie zapisać błąd i zaktualizować błąd $.

\ PsExec.exe \ $ hostname -u $ script. Nazwa użytkownika -p $ script: hasło/ACCEPTEULA -h cmd/c $ powerShellArgs 2> $ zerowy

+0

Czy możesz rozwinąć informacje zawarte w linku, na wypadek gdyby przestał działać? – sushain97

+0

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić w nim istotne części odpowiedzi i podać link do odsyłacza. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. – Onik

+0

Naprawiono. Dodano odpowiednią sekcję z hiperłącza. –

0

Stworzyłem PsExec otoki dla PowerShell , które mogą być pomocne dla osób przeglądający to pytanie:

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 
    } 
} 
Powiązane problemy