【问题标题】:Launch PowerShell scriptblock asynchronously without dependency on parent process在不依赖父进程的情况下异步启动 PowerShell 脚本块
【发布时间】:2013-09-23 22:09:31
【问题描述】:

下面是一个小的 PowerShell 脚本,它异步运行一些 PowerShell 代码以显示一个对话框(用于演示我的问题)。

如果我关闭父 PowerShell 进程,子进程也将关闭并且对话框消失。有什么方法可以异步启动 PowerShell 脚本块,包括函数和参数,并且不依赖于父 PowerShell 进程?

    $testjob = [PowerShell]::Create().AddScript({ $a = new-object -comobject wscript.shell
    $b = $a.popup('This is a test',5,'Test Message Box',1) })
    $result = $testJob.BeginInvoke()

更新 #2

我正在尝试执行脚本块,而不是外部脚本。脚本块应使用父脚本中的函数和变量。问题是,除非它们直接包含在脚本块中,否则我无法将这些函数或变量传递给新进程。知道这是否可行吗?

    Function Show-Prompt {
        Param ($title,$message)
            $a = new-object -comobject wscript.shell
            $b = $a.popup($message,5,$title,1)
    }  

    $scriptContent = {Show-Prompt -Message 'This is a test' -Title 'Test Message Box'}  
    $scriptBlock = [scriptblock]::Create($scriptContent)
    Start-process powershell -argumentlist "-noexit -command &{$scriptBlock}"

【问题讨论】:

    标签: multithreading powershell asynchronous process parent


    【解决方案1】:

    您可以使用中间 PowerShell 进程。必须有一个直接父级来处理来自异步脚本的返回值。例如,将您的脚本放在一个名为 popup.ps1 的文件中,然后尝试像这样执行:

    Start-Process PowerShell -Arg c:\popup.ps1
    

    您可能希望将超时时间从 5 秒提高到 10 秒。您可以关闭原始 PowerShell,弹出窗口将保留。当您关闭弹出窗口(或超时)时,辅助 PowerShell 窗口将消失。

    【讨论】:

    • 感谢 Keith,请参阅我的问题中的更新 #2 - 我正在尝试执行脚本块而不是外部脚本。
    • @thebitsandthebytes 您可以将脚本块作为参数传递给 PowerShell.exe(请参阅 PowerShell.exe 上的 -Command 参数)。但是,您以异步方式运行脚本块,父 PowerShell 进程会挂起以从脚本块中获取结果和错误。现在我认为您可以使用 Invoke-Command -InDisconnectedSession 但 UI 不会出现在您的桌​​面上。
    • 我不得不使用脚本方法 - 无法让脚本块工作。感谢您的帮助。
    【解决方案2】:

    您可以使用 WMI 做到这一点。如果你使用 Win32_Process 创建进程,在你关闭 PowerShell 后它会一直存在。

    例如:

    invoke-wmimethod -path win32_process -name create -argumentlist calc
    

    【讨论】:

      【解决方案3】:
      function GeneratePortableFunction {
          param ([string] $name, [scriptblock] $sb)
          $block = [ScriptBlock]::Create("return `${function:$name};");
          $script = $block.Invoke();
          $block = [ScriptBlock]::Create($script);
          return ("function {0} {{ {1} }}" -f $name, $block.ToString());
      }
      function RemoteScript {
          param ([string] $header, [string[]] $functions, [string] $footer)
          $sb = New-Object System.Text.StringBuilder;
          [void]$sb.Append("$header`n");
          $functions | % {
              [void]$sb.Append($_);
              [void]$sb.Append("`n");
          }
          [void]$sb.Append($footer);
          return [ScriptBlock]::Create($sb.ToString());
      }
      
      $fnc = @();
      $fnc += GeneratePortableFunction -name "NameOfYourFunction1";
      $fnc += GeneratePortableFunction -name "NameOfYourFunction2(CallsNameOfYourFunction1)";
      $script = RemoteScript -header "param([int] `$param1)" -functions @($fnc) -footer "NameOfYourFunction2 -YourParameter `$param1;";
      $p1 = 0;
      $job = Start-Job -ScriptBlock $script -ArgumentList @($p1);
      while($job.State -eq "Running")
      {
          write-host "Running...";
          Start-Sleep 5;
      }
      $result = $job | Receive-Job;
      Remove-Job -Id $job.Id;
      

      【讨论】:

        猜你喜欢
        • 2017-02-15
        • 1970-01-01
        • 2017-04-29
        • 2010-10-03
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多