1. ホーム
  2. windows

[解決済み] CreateProcess でエラー 193 (%1 は有効な Win32 アプリではありません) が発生する理由

2022-02-10 14:38:49

質問

以下のコードでは、ドキュメントの起動に失敗します。エラー193(%1 is not a valid Win32 app)が表示されます。実行ファイルの起動はうまくいきます。 ファイルは適切に関連付けられ、ダブルクリックすると対応するアプリが起動します。 エラーメッセージ、createprocessのものなどをSOや他の場所で検索してみました(例. Windows Server 2003 64ビットでCreateProcessが失敗するのはなぜですか? コマンドラインの引用について知っています。

  • Delphi XE2 (Update 4) Win32 app in a Win7 64bit VMWare VMです。

  • このコードは、ホストマシン(Win7 64bit)と32bit XPのVirtual PC VM上でも失敗します。

  • Win7のVMで起動するはずのアプリ(Excel 2003とCrimson Editor)は32ビットです。

  • IDEから起動した場合とテストアプリをスタンドアロンで実行した場合の両方で不具合が発生する

  • 以前はDelphi2007のコードで、このコードの元となるコンパイル済みのD2007アプリはどこでも問題なく動作します。

このコードのどこが悪いのでしょうか?何かとても当たり前のことを見落としているような気がするのですが...。

よろしくお願いします。

ジャン

procedure StartProcess(WorkDir, Filename: string; Arguments : string = '');
var
  StartupInfo  : TStartupInfo;
  ProcessInfo  : TProcessInformation;
  lCmd         : string;
  lOK          : Boolean;
  LastErrorCode: Integer;
begin
  FillChar( StartupInfo, SizeOf( TStartupInfo ), 0 );
  StartupInfo.cb := SizeOf( TStartupInfo );
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := sw_Normal;

  FillChar( ProcessInfo, SizeOf( TProcessInformation ), 0 );

  lCmd := '"' +  WorkDir + FileName + '"';     // Quotes are needed https://stackoverflow.com/questions/265650/paths-and-createprocess
  if Arguments <> '' then lCmd := lCmd + ' ' + Arguments;

  lOk := CreateProcess(nil,
                       PChar(lCmd),
                       nil,
                       nil,
                       FALSE,  // TRUE makes no difference
                       0,      // e.g. CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS makes no difference
                       nil,
                       nil,    // PChar(WorkDir) makes no difference
                       StartupInfo,
                       ProcessInfo);

  if lOk then
  begin
    try
      WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    finally
      CloseHandle( ProcessInfo.hThread );
      CloseHandle( ProcessInfo.hProcess );
    end;
  end
  else
  begin
    LastErrorCode := GetLastError;
    ShowMessage(IntToStr(LastErrorCode) + ': ' + SysErrorMessage(LastErrorCode));
  end;
end;

procedure TFrmStartProcess.Button1Click(Sender: TObject);
begin
   StartProcess('c:\program files (x86)\axe3\','axe.exe');    // Works
end;

procedure TFrmStartProcess.Button2Click(Sender: TObject);
begin
   StartProcess('d:\','klad.xls');                            // Fails
end;

procedure TFrmStartProcess.Button3Click(Sender: TObject);
begin
   StartProcess('d:\','smimime.txt');                         // Fails
end;

解決方法は?

そのエラーの原因として考えられるのは

  1. 読み込もうとしたファイルが実行可能ファイルでない。 CreateProcess は、実行可能なファイルを提供する必要があります。もし、どんなファイルでも、そのファイルに関連するアプリケーションを開くことができるようにしたい場合は ShellExecute ではなく CreateProcess .
  2. 実行ファイルの依存関係の1つ、つまり実行ファイルにリンクされているDLLの読み込みに問題があります。最も一般的な原因は、32ビットの実行ファイルと64ビットのDLL、またはその逆の間のミスマッチです。調査するには、以下を使用します。 依存性ウォーカーの プロファイルモードを使用して、何が問題なのかを正確にチェックします。

コードの下まで読むと、問題は1番であることがわかります。