Перенаправление PowerShell не всегда работает - PullRequest
7 голосов
/ 01 мая 2020

Перенаправление потока предупреждений для New-PSSession не работает так, как мне кажется. Я всегда получаю следующее ( желтое ) предупреждение на консоль, независимо от того, что я делаю, чтобы попытаться подавить / перенаправить его:

WARNING: Using New-PSSession with Basic Authentication is going to be deprecated soon, checkout https://aka.ms/exops-docs for using Exchange Online V2 Module which uses Modern Authentication.

Что мне не хватает в перенаправлении / потоках PowerShell, которое это позволяя этому сообщению проникнуть в консоль / std_out?

Что не работает

Я пробовал следующее, согласно мудрости inte rnet:

New-PSSession *>$null ...
New-PSSession ... | Out-Null
New-PSSession *>$null ... -OutVariable x -ErrorVariable y -WarningVariable z
New-PSSession *>$null ... -WarningAction SilentlyContinue
$WarningPreference = 'SilentlyContinue'
New-PSSession ...

Я даже пытался взять временный контроль над std_out:

$std_out = [System.Console]::Out
$out_writer = New-Object IO.StringWriter
[System.Console]::SetOut($out_writer)

$std_err = [System.Console]::Error
$err_writer = New-Object IO.StringWriter
[System.Console]::SetOut($err_writer)

$sess = New-PSSession ...

[System.Console]::SetOut($std_out)
[System.Console]::SetError($std_err)

Наряду с каждой комбинацией выше, что я могу придумать, плюс еще несколько методов, которые я забыл.

Что должно работать

Тестирование каждого из этих методов с использованием Invoke-Command работает для других предупреждения, как и ожидалось:


$std_out = [System.Console]::Out
$out_writer = New-Object IO.StringWriter
[System.Console]::SetOut($out_writer)

$std_err = [System.Console]::Error
$err_writer = New-Object IO.StringWriter
[System.Console]::SetOut($err_writer)

Invoke-Command -ScriptBlock {

    Write-Error "My Error"
    Write-Warning "My Warning"
    [console]::WriteLine('Directly to std_out!')

} *>$null -OutVariable x -ErrorVariable y -WarningVariable z

[System.Console]::SetOut($std_out)
[System.Console]::SetError($std_err)

Но ничто из того, что я пробовал, не подавит и не перенаправит это сообщение с New-PSSession.

Воспроизвести

param (
    $username,
    $password
)

$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$URL = "https://ps.outlook.com/powershell"
New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $URL -Credential $creds -Authentication Basic -AllowRedirection

Протестированные среды

Windows 10:

Name                           Value
----                           -----
PSVersion                      7.1.0-preview.2
PSEdition                      Core
GitCommitId                    7.1.0-preview.2
OS                             Microsoft Windows 10.0.18363
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Windows 10:

Name                           Value
----                           -----
PSVersion                      5.1.18362.752
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.18362.752
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Сервер 2019:

Name                           Value
----                           -----
PSVersion                      5.1.17763.1007
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17763.1007
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

WinRM (одинаково для всех систем):

Config
    MaxEnvelopeSizekb = 500
    MaxTimeoutms = 60000
    MaxBatchItems = 32000
    MaxProviderRequests = 4294967295
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts
    Service
        RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
        MaxConcurrentOperations = 4294967295
        MaxConcurrentOperationsPerUser = 1500
        EnumerationTimeoutms = 240000
        MaxConnections = 300
        MaxPacketRetrievalTimeSeconds = 120
        AllowUnencrypted = false
        Auth
            Basic = false
            Kerberos = true
            Negotiate = true
            Certificate = false
            CredSSP = false
            CbtHardeningLevel = Relaxed
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        IPv4Filter = *
        IPv6Filter = *
        EnableCompatibilityHttpListener = false
        EnableCompatibilityHttpsListener = false
        CertificateThumbprint
        AllowRemoteAccess = true
    Winrs
        AllowRemoteShellAccess = true
        IdleTimeout = 7200000
        MaxConcurrentUsers = 2147483647
        MaxShellRunTime = 2147483647
        MaxProcessesPerShell = 2147483647
        MaxMemoryPerShellMB = 2147483647
        MaxShellsPerUser = 2147483647

Ответы [ 2 ]

2 голосов
/ 05 мая 2020

Обычно перенаправление вывода работает так, как вы уже пробовали. Чтобы быть более точным, c:

New-PSSession -... 3> $null

перенаправит ваше нежелательное предупреждение, поскольку 3 описывает поток предупреждений начиная с PowerShell 3.0 ( см. Документы ).

Тот факт, что это не работает в данном конкретном случае, кажется ошибкой, и уже была открыта проблема здесь несколько дней go.

0 голосов
/ 12 мая 2020

Возможно, не ответ, но слишком длинный для комментария. Не проси меня объяснить, что это делает, и как это работает. Это было найдено где-то здесь или где-то еще. Я поместил его здесь, потому что он, похоже, связан с powershell и какими-то взаимодействиями потоков ... Я позволю вам извлечь из этого все, что вам нужно.

Вот наш контекст: нам пришлось запустить скрипт powershell из сценария летучей мыши. Сценарий powershell запускал какую-то системную команду (zip и т. Д.). У нас были трудные времена, чтобы правильно собрать информацию о времени выполнения. В качестве решения мы должны были передать сценарий ps1 в качестве параметра другого сценария ps1, который мы назвали bug.ps1. Его содержимое показано ниже.

Вот команда в файле .bat:

powershell.exe -ExecutionPolicy Bypass -command "C:\path\to\bug.ps1" "my_script.ps1" %arg%

, а вот содержимое файла bug.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>
invoke-expression "$args"
exit $lastexitcode
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...