2013-08-22 19 views
7

Quindi usiamo PsExec molto nelle nostre automazioni per installare macchine virtuali, dato che non possiamo usare le sessioni remote di PS con le nostre macchine Windows 2003. Tutto funziona alla grande e non ci sono Problemi, ma PsExec continua a generare errori, anche se ogni comando viene eseguito senza correttamente. Per esempio:PsExec genera messaggi di errore, ma funziona senza problemi

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" 

Abilita la PSRemoting sul guest, ma getta anche questo messaggio di errore:

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. 

Questi tipi di messaggi di errore apear SEMPRE non importa quanto io uso psexec, come con le citazioni, con valori fissi/fissi, altre bandiere, ecc. Qualcuno ha un'idea di come potrei risolvere questo problema? Non è un vero problema, ma rende il trovare errori un rompicoglioni, perché gli "errori" sono ovunque. Disabilitare i messaggi di errore di psexec potrebbe anche aiutare ...

+1

ho lo stesso problema, e io uso '$ ErrorActionPreference = "SilentlyContinue"' prima del comando psexec. Ma non è una soluzione reale. – plunkets

+0

Beh, non è la migliore idea, ma molto meglio della mia "soluzione". Immagino, scriverò una funzione psexec-silent, mettendo a punto ErrorActionPreference prima e dopo il comando psexec. Almeno posso spegnere il messaggio di errore, che chiaramente non è uno. – Simons0n

+0

Controlla questo; http://stackoverflow.com/a/2095623/469777 –

risposta

12

Ciò è dovuto al fatto che a volte PowerShell segnala un errore NativeCommandError quando un processo scrive su STDERR. PsExec scrive l'infoline

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

a STDERR che significa che può causare questo.

Per ulteriori informazioni, vedere queste domande/risposte:

+1

Non posso ringraziarti abbastanza per questa risposta e tutti i link. –

2

reindirizzamento stderr a NULL lavorato meglio per me. vedi sotto collegamento

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

Ecco la relativa sezione da quel link:

per evitare questo è possibile reindirizzare stderr a null ad esempio:

du 2> $ null In sostanza la l'host della console e ISE (così come i servizi remoti) trattano lo stream stderr in modo diverso. Sull'host della console era importante che PowerShell supporti applicazioni come edit.com per lavorare insieme ad altre applicazioni che scrivono output e errori colorati sullo schermo. Se il flusso di I/O non viene reindirizzato sull'host della console, PowerShell fornisce all'EXE nativo un handle di console per scrivere direttamente. Ciò ignora PowerShell in modo che PowerShell non possa vedere che ci sono errori scritti in modo che non possa riportare l'errore tramite $ error o scrivendo nello stream stderr di PowerShell. ISE e remoting non devono supportare questo scenario in modo che visualizzino gli errori su stderr e successivamente scrivano l'errore e aggiornino $ error.

\ PsExec.exe \ $ hostname -u $ script:. UserName -p $ script: la password/AcceptEULA -h cmd/c $ powerShellArgs 2> $ null

+0

Puoi approfondire le informazioni fornite nel link nel caso in cui vadano stancate? – sushain97

+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. – Onik

+0

risolto. Aggiunta sezione pertinente dal collegamento ipertestuale. –

0

Ho creato un wrapper psexec per PowerShell , che può essere utile per le persone che stanno navigando domanda:

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 
    } 
}