0

下面是一个小的 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}"
4

3 回答 3

2

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

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

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

于 2013-09-23T23:31:43.277 回答
1

您可以使用 WMI 执行此操作。如果您使用 Win32_Process 创建进程,它会在您关闭 PowerShell 后继续存在。

例如:

invoke-wmimethod -path win32_process -name create -argumentlist calc
于 2013-09-24T01:08:10.817 回答
0
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;
于 2013-11-14T22:42:18.787 回答