4

私はこのコードをスレッドで使用します(Indy Onexecuteイベントを介して)。何か問題ある ?

function TFrmMain.ShellExecute_AndWait(FileName, Params: string): bool;
var
  exInfo: TShellExecuteInfo;
  Ph: DWORD;
begin
  FillChar(exInfo, SizeOf(exInfo), 0);
  with exInfo do
  begin
    cbSize := SizeOf(exInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
    Wnd := GetActiveWindow();
    exInfo.lpVerb := 'open';
    exInfo.lpParameters := PChar(Params);
    lpFile := PChar(FileName);
    nShow := SW_NORMAL;
  end;
  if ShellExecuteEx(@exInfo) then
    Ph := exInfo.hProcess
  else
  begin
    Result := true;
    exit;
  end;
  while WaitForSingleObject(exInfo.hProcess, 50) <> WAIT_OBJECT_0 do
  begin

  end;
  CloseHandle(Ph);
  Result := true;
end;
4

1 に答える 1

8

MSDNには次のアドバイスがあります。

ShellExecuteExは、コンポーネントオブジェクトモデル(COM)を使用してアクティブ化されるシェル拡張機能(データソース、コンテキストメニューハンドラー、動詞の実装)に実行を委任できるため、ShellExecuteExを呼び出す前にCOMを初期化する必要があります。一部のシェル拡張には、COMシングルスレッドアパートメント(STA)タイプが必要です。その場合、COMは次のように初期化する必要があります。

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

ShellExecuteExがこれらのタイプのシェル拡張の1つを使用せず、それらのインスタンスでCOMを初期化する必要がまったくない場合があります。それでも、この関数を使用する前に、常にCOMを初期化することをお勧めします。

(Delphiでは、もちろん最初のパラメーターをビット単位の操作に置き換えてnil使用します。)or

レイモンド・チェンは最近、これを間違えた場合の結果について書いています。具体的な例は、関数がError_Access_Deniedエラーコードで失敗する可能性があることです。

これが、コードに見られる唯一の潜在的なマルチスレッドの問題です。以下は、私があなたのコードを読んだときに私に起こったさらなることですが、それらはマルチスレッドとは何の関係もありません(そしてIndyとはあまり関係がありません)。


プログラムの実行が停止するのを待つ独特の方法があります。一度に50ミリ秒待つことを繰り返しますが、プロセスがまだ終了していない場合は、もう一度待つだけです。Infiniteタイムアウトを指定して、意図をより正確に説明します。


関数は常にを返しますTrue。有用な戻り値がない場合は、それをプロシージャにして、戻り値がまったくないようにする必要があります。発信者を役に立たない情報と混同しないでください。関数として保持する場合は、戻り型にBooleanWindows互換型の代わりにDelphiネイティブ型を使用してください。Bool


サーバーがネットワークメッセージの受信時にユーザーインタラクティブプログラムを実行するという考えには少し警戒しています。


MSDNが、プロセスハンドルを取得できない可能性があると言っていることに注意してください。新しいプロセスを作成せずにリクエストを処理できる場合があるShellExecuteExため、待つ必要はありません。

ユーザーがしばらくの間プログラムを使用することになり、サーバーがその間ずっと待機し続ける可能性があります。本当に待つ必要があるのか​​しら。クライアントもサーバーからの応答を待っていますか?

于 2010-11-30T04:48:46.267 に答える