web-dev-qa-db-ja.com

PowershellでリモートGUIアプリを実行する

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アプリケーションであり、このアプリケーションのバッチバージョンまたはコマンドラインバージョンが提供されていないため、ソースにアクセスできません。

19

標準のPowerShellメソッド(WinRM、WMI)を使用すると、GUIでアプリケーションを起動できません。私が知っている唯一の解決策は、 SysInternalsのPsExec (または同様のツール)を使用することです。 GUIをユーザーに提示するアプリケーションを起動できます。コマンドラインは次のようになります。

& ".\psexec" -accepteula -i "\\computername" -u "domain\username" -p "password" "command line"
  • -accepteula —EULAを黙って受け入れます。
  • -i —GUIを許可します。

スケジューラーへのタスクのリモート追加など、他のソリューションはよりハッキーです。

18
Athari

最近これに遭遇したので、リモートタスクを追加するというDiscordの提案を使用した私の解決策を次に示します。別のツールをセットアップするよりも「ハック」の方が好きでした。

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
    }

}
8
Ben