web-dev-qa-db-ja.com

昇格と待機が必要な子プロセスを実行するにはどうすればよいですか?

勝利7/UACは私を夢中にさせています。

私のC++アプリケーション内から、Windows 7で昇格を必要とする実行可能ファイルを実行する必要があります。これを実行し、処理が完了するのを待ってから続行します。これを行う最も簡単な方法は何ですか?

通常、このようなことはCreateProcess()を介して行いますが、昇格が必要な実行可能ファイルでは失敗します。

_cmd.exe /c ..._からCreateProcessを使用して実行してみましたが、機能しますが、醜いcmdターミナルウィンドウがポップアップします。

私はShellExecute()が昇格を許可することを読んでいますが、ShellExecute()を使用する場合、exeが完了するのを待つのは簡単ではないようです。 system()のような単純なものが機能しますか?

他のアイデアは大歓迎です!

30
KenG

ShellExecuteExではなく、ShellExecuteを使用します。この関数は、作成されたプロセスのハンドルを提供します。これを使用して、WaitForSingleObjectを呼び出すことができます。そのプロセスが終了するまでブロックするハンドル。最後に、プロセスハンドルでCloseHandleを呼び出して、それを閉じます。

サンプルコード(エラーチェックの大部分は、明確さと簡潔さのために省略されています):

SHELLEXECUTEINFO shExInfo = {0};
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = _T("runas");                // Operation to perform
shExInfo.lpFile = _T("C:\\MyApp.exe");       // Application to start    
shExInfo.lpParameters = "";                  // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;  

if (ShellExecuteEx(&shExInfo))
{
    WaitForSingleObject(shExInfo.hProcess, INFINITE);
    CloseHandle(shExInfo.hProcess);
}

lpVerbに "runas"動詞を指定すると、起動しようとしているアプリケーションがUACによって昇格されます。これは、アプリケーションのマニフェストでアクセス許可レベルを "requireAdministrator"に設定することと同じです。管理者と制限付きユーザーの両方にUAC昇格が必要になります。

ただし、絶対に必要な場合を除いて、起動するアプリケーションに必要な実行レベルを指定するマニフェストを「標準」の方法で追加することをお勧めします。このルートを使用する場合は、lpVerbとして「open」を渡すだけです。マニフェストの例を以下に示します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Assembly xmlns="urn:schemas-Microsoft-com:asm.v1" manifestVersion="1.0">
        <dependency>
                <dependentAssembly>
                        <assemblyIdentity
                                type="win32"
                                name="Microsoft.Windows.Common-Controls"
                                version="6.0.0.0"
                                processorArchitecture="X86"
                                publicKeyToken="6595b64144ccf1df"
                                language="*"
                        />
                </dependentAssembly>
        </dependency>
        <trustInfo xmlns="urn:schemas-Microsoft-com:asm.v2">
                <security>
                        <requestedPrivileges>
                                <requestedExecutionLevel 
                                       level="requireAdministrator" 
                                       uiAccess="false"/>
                        </requestedPrivileges>
                </security>
        </trustInfo>
</Assembly>

最後に、UAC昇格を必要とするプロセスの実行をトリガーするアプリケーション内の要素が それに応じてマークされている であることを確認してください。ユーザーインターフェイスでこれをモデル化するのはあなたの仕事です。 Windowsはそれを処理しません。これは、エントリポイントに盾アイコンを表示することによって行われます。例えば:

UAC shield displayed on a buttonUAC shield displayed on a menu item

42
Cody Gray

できることは、子プロセス "stdin"のパイプを作成し(入力をそのプロセスにリダイレクトする場合のように)、パイプが壊れるのを待ちます。

プロセスはリダイレクトされた入力を実際には受信しないことに注意してください。

例えば。昇格していないコマンドプロンプトから実行しようとした場合

echo help | diskpart

高度が表示され、コマンドウィンドウは別のウィンドウを閉じるまで待機します。

0
John

昇格された特権で実行するには、これを起動するプロセスに昇格された特権が必要です。これには通常、プロセスを起動するために安全なサービスまたはすでに実行されているものが必要です。これはVista以降の変更点です。プロセスを起動し、起動プロセスから継承された適切なレベルの特権で起動できるようにするには、(ACLトークンを介して)権限を持っている必要があります。マイクロソフトは、すべての高度な機能のニーズを処理し、残りの権限を最低限の特権のユーザースペースに残す高度なプロセスを人々に作成させることを強く求めてきました。 Vistaがアルファ版だったので、これを何度も何度も繰り返してきました。それは苦痛ですが、マイクロソフトがセキュリティ上の理由であなたが何かをすることを好む方法です。

ちなみに、Program Filesディレクトリなどの安全な場所からアプリを起動している場合、ShellExec呼び出しは機能しません。数年前にサービスモデルに移動する前に、それを試してみました。

したがって、プロセスを起動してUACをバイパスする唯一の方法は、継承する特権が既にセキュリティに付与されているプロセスから起動することです。

0
Greg