powershell 2.0 Umleitung von Datei-handle-Ausnahme

Ich bin auf der Suche nach einer Lösung für das The OS handle's position is not what FileStream expected. Do not use a handle simultaneously in one FileStream and in Win32 code or another FileStream. Ausnahme, dass würde auch die Arbeit an Aufgabenstellungen innerhalb des Skripts mit "the fix".

Für die Zwecke dieser Frage, ich sage, dass ich zwei Skripte:

foo.ps1

# <fix>
$bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
$objectRef = $host.GetType().GetField( "externalHostRef", $bindingFlags ).GetValue( $host )
$bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetProperty"
$consoleHost = $objectRef.GetType().GetProperty( "Value", $bindingFlags ).GetValue( $objectRef, @() )
[void] $consoleHost.GetType().GetProperty( "IsStandardOutputRedirected", $bindingFlags ).GetValue( $consoleHost, @() )
$bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
$field = $consoleHost.GetType().GetField( "standardOutputWriter", $bindingFlags )
$field.SetValue( $consoleHost, [Console]::Out )
$field2 = $consoleHost.GetType().GetField( "standardErrorWriter", $bindingFlags )
$field2.SetValue( $consoleHost, [Console]::Out )
# </fix>

write-host "normal"
write-error "error"
write-host "yay"
.\bar.ps1

bar.ps1

write-host "normal"
write-error "error"
write-host "yay"

Sowie foo.ps1 wird ausgeführt, wie diese:

powershell .\foo.ps1 > C:\temp\redirecct.log 2>&1

Der erwartete output sollte sein:

normal
C:\foo.ps1 : error
At line:1 char:10
+ .\foo.ps1 <<<<
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,foo.ps1

yay
normal
C:\bar.ps1 : error
At C:\foo.ps1:17 char:6
+ .\bar <<<<  2>&1
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,bar.ps1

yay

Jedoch, aufgrund der bekannten Fehler, der Ausgang ist eigentlich:

normal
C:\foo.ps1 : error
At line:1 char:10
+ .\foo.ps1 <<<< 
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,foo.ps1

yay
normal
out-lineoutput : The OS handle's position is not what FileStream expected. Do not use a handle simultaneously in one FileStream and in Win3
2 code or another FileStream. This may cause data loss.
    + CategoryInfo          : NotSpecified: (:) [out-lineoutput], IOException
    + FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.OutLineOutputCommand

Also das beobachtete Verhalten ist, dass die änderungen durch den "fix" nicht geerbt wird von der 'Kind' - Skript (bar.ps1, in diesem Fall). Wenn bar.ps1 versucht zu schreiben, es stürzt schwer. Wenn ich nicht Wache gegen es irgendwie in foo.ps1 es werden auch crash-hart. Was kann ich vor/bei der Berufung von bar.ps1 um zu verhindern, dass bar.ps1 abstürzt, wenn er versucht zu schreiben?

Einschränkungen:

  • Powershell 2.0
  • Das Skript muss ausgeführt werden, wie oben
  • Ich kann es nicht ändern bar.ps1 (und es sollte nicht Abstürzen, wenn das schreiben auf stderr).

UPDATE

Unten ist eine halbe akzeptable Lösung. Ich sage halb, weil es verhindert nur, dass das 'parent' - Skript abstürzt. Die 'Kind' - Skript immer noch nicht hart, wenn er versucht zu schreiben. Auf der plus-Seite, es kann so weit gehen, wie die Erkenntnis, dass bar ist fehlgeschlagen.

foo.ps1:

function savepowershellfromitself {
    $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
    $objectRef = $host.GetType().GetField( "externalHostRef", $bindingFlags ).GetValue( $host )
    $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetProperty"
    $consoleHost = $objectRef.GetType().GetProperty( "Value", $bindingFlags ).GetValue( $objectRef, @() )
    [void] $consoleHost.GetType().GetProperty( "IsStandardOutputRedirected", $bindingFlags ).GetValue( $consoleHost, @() )
    $bindingFlags = [Reflection.BindingFlags] "Instance,NonPublic,GetField"
    $field = $consoleHost.GetType().GetField( "standardOutputWriter", $bindingFlags )
    $field.SetValue( $consoleHost, [Console]::Out )
    $field2 = $consoleHost.GetType().GetField( "standardErrorWriter", $bindingFlags )
    $field2.SetValue( $consoleHost, [Console]::Out )
}

savepowershellfromitself
write-host "normal"
write-error "error"
write-host "yay"
$output = .\bar.ps1 2>&1
savepowershellfromitself
write-host "$output"
if( $errors = $output | ?{$_.gettype().Name -eq "ErrorRecord"} ){
    write-host "there were errors in bar!"
}
write-error "error2"
write-host "done"
Schreibe einen Kommentar