gpt4 book ai didi

powershell - 通过启动进程以管理员身份从 powershell 脚本重定向 stdout、stderr

转载 作者:行者123 更新时间:2023-12-04 14:54:20 25 4
gpt4 key购买 nike

在 powershell 脚本中,我正在运行一个命令,该命令以管理员身份启动一个新的 powershell(如果我不是,如果需要,取决于 $arg),然后运行该脚本。

我正在尝试将 stdout 和 stderr 重定向到第一个终端。

不是试图让事情变得更容易,也有争论。

param([string]$arg="help")

if($arg -eq "start" -Or $arg -eq "stop")
{
if(![bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544"))
{
Start-Process powershell -Verb runas -ArgumentList " -file servicemssql.ps1 $arg"
exit
}
}

$Services = "MSSQLSERVER", "SQLSERVERAGENT", "MSSQLServerOLAPService", "SSASTELEMETRY", "SQLBrowser", `
"SQLTELEMETRY", "MSSQLLaunchpad", "SQLWriter", "MSSQLFDLauncher"

function startsql {
"starting SQL services"
Foreach ($s in $Services) {
"starting $s"
Start-Service -Name "$s"
}
}

function stopsql {
"stopping SQL services"
Foreach ($s in $Services) {
"stopping $s"
Stop-Service -Force -Name "$s"
}
}

function statussql {
"getting SQL services status"
Foreach ($s in $Services) {
Get-Service -Name "$s"
}
}

function help {
"usage: StartMssql [status|start|stop]"
}

Switch ($arg) {
"start" { startsql }
"stop" { stopsql }
"status" { statussql }
"help" { help }
"h" { help }
}

在 SO 上使用以下答案不起作用:
  • Capturing standard out and error with Start-Process
  • Powershell: Capturing standard out and error with Process object

  • 如何在保留变量( $arg )扩展的同时处理双引号内的双引号?

    最佳答案

    PowerShell 的 Start-Process小命令:

  • 确实有-RedirectStandardOut-RedirectStandardError参数,
  • 但在语法上它们不能与 -Verb Runas 结合使用,启动进程所需的参数提升(具有管理权限)。

  • 此约束也反射(reflect)在底层 .NET API 中,其中设置了 .UseShellExecute System.Diagnostics.ProcessStartInfo 上的属性(property)实例到 true - 能够使用的先决条件 .Verb = "RunAs"为了运行提升 - 意味着您不能使用 .RedirectStandardOutput.RedirectStandardError特性。
    总的来说,这表明您不能直接从非提升过程中捕获提升过程的输出流。
    A 纯 PowerShell 解决方法 不是微不足道的:
    param([string] $arg='help')

    if ($arg -in 'start', 'stop') {
    if (-not (([System.Security.Principal.WindowsPrincipal] [System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole('Administrators'))) {

    # Invoke the script via -Command rather than -File, so that
    # a redirection can be specified.
    $passThruArgs = '-command', '&', 'servicemssql.ps1', $arg, '*>', "`"$PSScriptRoot\out.txt`""

    Start-Process powershell -Wait -Verb RunAs -ArgumentList $passThruArgs

    # Retrieve the captured output streams here:
    Get-Content "$PSScriptRoot\out.txt"

    exit
    }
    }

    # ...
  • 而不是 -File , -Command用于调用脚本,因为这允许将重定向附加到命令:*>重定向所有输出流。
  • @soleil 建议使用 Tee-Object作为替代方案,不仅可以捕获提升进程产生的输出,还可以在生成时将其打印到(总是新窗口的)控制台:..., $arg, '|', 'Tee-Object', '-FilePath', "`"$PSScriptRoot\out.txt`""
  • 警告:虽然在这个简单的情况下没有区别,但重要的是要知道 -File 之间的参数解析方式不同。和 -Command模式;简而言之,与 -File ,脚本名称后面的参数被视为文字,而 -Command 后面的参数被视为文本。形成一个命令,根据目标 session 中的正常 PowerShell 规则进行评估,例如,这对转义有影响;值得注意的是,带有嵌入空格的值必须用引号括起来作为值的一部分。

  • $PSScriptRoot\输出捕获文件中的路径组件 $PSScriptRoot\out.txt确保文件与调用脚本在同一文件夹中创建(提升的进程默认为 $env:SystemRoot\System32 作为工作目录。)
  • 同样,这意味着脚本文件 servicemssql.ps1 ,如果它在没有路径组件的情况下被调用,则必须位于 $env:PATH 中列出的目录之一中。为了让提升的 PowerShell 实例找到它;否则,还需要完整路径,例如$PSScriptRoot\servicemssql.ps1 .

  • -Wait确保在提升的进程退出之前控制权不会返回,此时文件 $PSScriptRoot\out.txt可以检查。

  • 至于后续问题:

    To go even further, could we have a way to have the admin shell running non visible, and read the file as we go with the Unix equivalent of tail -f from the non -privileged shell ?


    可以不可见地运行提升的进程本身,但请注意,您仍然会收到 UAC 确认提示。 (如果您要关闭 UAC(不推荐),您可以使用 Start-Process -NoNewWindow 在同一窗口中运行该进程。)
    监控正在生成的输出,tail -f ,仅 PowerShell 的解决方案既重要又不是最有效的;以机智:
    param([string]$arg='help')

    if ($arg -in 'start', 'stop') {
    if (-not (([System.Security.Principal.WindowsPrincipal] [System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole('Administrators'))) {

    # Delete any old capture file.
    $captureFile = "$PSScriptRoot\out.txt"
    Remove-Item -ErrorAction Ignore $captureFile

    # Start the elevated process *hidden and asynchronously*, passing
    # a [System.Diagnostics.Process] instance representing the new process out, which can be used
    # to monitor the process
    $passThruArgs = '-noprofile', '-command', '&', "servicemssql.ps1", $arg, '*>', $captureFile
    $ps = Start-Process powershell -WindowStyle Hidden -PassThru -Verb RunAs -ArgumentList $passThruArgs

    # Wait for the capture file to appear, so we can start
    # "tailing" it.
    While (-not $ps.HasExited -and -not (Test-Path -LiteralPath $captureFile)) {
    Start-Sleep -Milliseconds 100
    }

    # Start an aux. background that removes the capture file when the elevated
    # process exits. This will make Get-Content -Wait below stop waiting.
    $jb = Start-Job {
    # Wait for the process to exit.
    # Note: $using:ps cannot be used directly, because, due to
    # serialization/deserialization, it is not a live object.
    $ps = (Get-Process -Id $using:ps.Id)
    while (-not $ps.HasExited) { Start-Sleep -Milliseconds 100 }
    # Get-Content -Wait only checks once every second, so we must make
    # sure that it has seen the latest content before we delete the file.
    Start-Sleep -Milliseconds 1100
    # Delete the file, which will make Get-Content -Wait exit (with an error).
    Remove-Item -LiteralPath $using:captureFile
    }

    # Output the content of $captureFile and wait for new content to appear
    # (-Wait), similar to tail -f.
    # `-OutVariable capturedLines` collects all output in
    # variable $capturedLines for later inspection.
    Get-Content -ErrorAction SilentlyContinue -Wait -OutVariable capturedLines -LiteralPath $captureFile

    Remove-Job -Force $jb # Remove the aux. job

    Write-Verbose -Verbose "$($capturedLines.Count) line(s) captured."

    exit
    }
    }

    # ...

    关于powershell - 通过启动进程以管理员身份从 powershell 脚本重定向 stdout、stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50765949/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com