21

我们有一个自定义组件,它封装了 powershell 的一些功能,因此它可以在 BizTalk 2006 中使用。对于大多数操作(检查文件路径、复制或移动文件),这都可以正常工作。然而,我们需要远程启动一个 GUI 应用程序来进行一些处理。组件本身处理与远程盒子的连接,我们所要做的就是设置一些参数,然后告诉它执行命令

Start-Process -FilePath "path to exe" -ArgumentList "arguments for exe" -WorkingDirectory "workingdir for exe"

问题是这样的:如果我们从盒子本身的 powershell 命令行运行它,这工作正常。但是,当我们远程启动它时(从 BizTalk、从测试工具,甚至使用远程 Powershell 命令行和通过 Start-PSSession 连接),此应用程序将短暂运行然后退出,而无需实际执行任何操作。我的怀疑是,因为有问题的 exe 需要加载 GUI 才能运行该进程,所以这就是导致问题的原因。我已经尝试了所有我能想到的方法,包括 -NoNewWindow 和 -WindowStyle 但无济于事。非常感谢任何帮助使这项工作正常进行。

注意:我们无法访问我们尝试运行的应用程序的源代码,因为它是较旧的 win32 应用程序,并且没有提供此应用程序的批处理或命令行版本。

4

2 回答 2

20

使用标准 PowerShell 方法(WinRM、WMI),您无法使用 GUI 启动应用程序。我知道的唯一解决方案是使用SysInternals(或类似工具)的 PsExec。它可以启动向用户呈现 GUI 的应用程序。您的命令行将如下所示:

& ".\psexec" -accepteula -i "\\computername" -u "domain\username" -p "password" "command line"
  • -accepteula— 默默接受 EULA。
  • -i— 允许 GUI。

其他解决方案更老套,包括向调度程序远程添加任务。

于 2010-10-25T06:43:30.623 回答
11

因为我最近遇到了这个问题,所以这是我使用 Discord 建议添加远程任务的解决方案。我更喜欢“hack”而不是必须设置一个单独的工具。

function Start-Process-Active
{
    param
    (
        [System.Management.Automation.Runspaces.PSSession]$Session,
        [string]$Executable,
        [string]$Argument,
        [string]$WorkingDirectory,
        [string]$UserID,
        [switch]$Verbose = $false

    )

    if (($Session -eq $null) -or ($Session.Availability -ne [System.Management.Automation.Runspaces.RunspaceAvailability]::Available))
    {
        $Session.Availability
        throw [System.Exception] "Session is not availabile"
    }

    Invoke-Command -Session $Session -ArgumentList $Executable,$Argument,$WorkingDirectory,$UserID -ScriptBlock {
        param($Executable, $Argument, $WorkingDirectory, $UserID)
        $action = New-ScheduledTaskAction -Execute $Executable -Argument $Argument -WorkingDirectory $WorkingDirectory
        $principal = New-ScheduledTaskPrincipal -userid $UserID
        $task = New-ScheduledTask -Action $action -Principal $principal
        $taskname = "_StartProcessActiveTask"
        try 
        {
            $registeredTask = Get-ScheduledTask $taskname -ErrorAction SilentlyContinue
        } 
        catch 
        {
            $registeredTask = $null
        }
        if ($registeredTask)
        {
            Unregister-ScheduledTask -InputObject $registeredTask -Confirm:$false
        }
        $registeredTask = Register-ScheduledTask $taskname -InputObject $task

        Start-ScheduledTask -InputObject $registeredTask

        Unregister-ScheduledTask -InputObject $registeredTask -Confirm:$false
    }

}
于 2016-05-31T03:22:46.713 回答