Delphi 7-ShellExecute命令在某些情况下不起作用

use*_*668 1 delphi shellexecute

我做了一个游戏启动器,并使用了以下命令:

 procedure TFMain.ImgBtn1Click(Sender: TObject);
     begin
      ShellExecute(TForm(Owner).Handle, nil, 'starter.exe', '-lang rus', nil, SW_SHOWNORMAL);
     end;
Run Code Online (Sandbox Code Playgroud)

以“ -lang rus”作为参数。一切正常。游戏启动,语言为俄语(如果我输入“ -lang eng”,它仍然可以正常运行,并且游戏为英语)。

starter.exe应用程序是一个名为“”文件夹内 '。当我要将启动器重新放置在此文件夹之外时,请使用以下命令:

procedure TFMain.ImgBtn1Click(Sender: TObject);
     begin
      ShellExecute(TForm(Owner).Handle, nil, 'bin\starter.exe', '-lang rus', nil, SW_SHOWNORMAL);
     end;
Run Code Online (Sandbox Code Playgroud)

但是随后游戏没有启动。实际上什么也没发生。我应该改变什么?

Dal*_*kar 5

您必须使用要启动的应用程序的完整路径。

ExtractFilePath(Application.ExeName) 将为您提供启动器exe的完整路径。

解决方案1:使用ShellExecute

procedure TFMain.ImgBtn1Click(Sender: TObject);
var 
  ExecuteResult: integer;
  Path: string;
begin
  Path := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
  ExecuteResult := ShellExecute(0, nil, PChar(Path + 'bin\starter.exe'), '-lang rus', nil, SW_SHOWNORMAL);
  if ExecuteResult <= 32 then ShowMessage('Error: ' + IntToStr(ExecuteResult));
end;
Run Code Online (Sandbox Code Playgroud)

您可以在以下位置找到错误代码列表:ShellExecute函数文档

最常见的错误代码:

  • ERROR_FILE_NOT_FOUND 0x2
  • ERROR_PATH_NOT_FOUND 0x3

解决方案2:使用ShellExecuteEx

var
  FileName, Parameters, Folder: string;
  sei: TShellExecuteInfo;
  Error: DWORD;
  OK: boolean;
begin
  Folder := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) + 'bin\';
  FileName := Folder + 'starter.exe';
  Parameters := '-lang rus';
  ZeroMemory(@sei, SizeOf(sei));
  sei.cbSize := SizeOf(sei);
  sei.lpFile := PChar(FileName);
  sei.lpParameters := PChar(Parameters);
  sei.lpDirectory := PChar(Folder);
  sei.nShow := SW_SHOWNORMAL;
  OK := ShellExecuteEx(@sei);
  if not OK then
    begin
      Error := GetLastError;
      ShowMessage('Error: ' + IntToStr(Error));
    end;
end;
Run Code Online (Sandbox Code Playgroud)

ShellExecuteEx文档

解决方案3:使用CreateProcess

function ExecuteProcess(const FileName, Params: string; Folder: string; WaitUntilTerminated, WaitUntilIdle, RunMinimized: boolean;
  var ErrorCode: integer): boolean;
var
  CmdLine: string;
  WorkingDirP: pchar;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  Result := true;
  CmdLine := '"' + FileName + '" ' + Params;
  if Folder = '' then Folder := ExcludeTrailingPathDelimiter(ExtractFilePath(FileName));
  ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
  StartupInfo.cb := SizeOf(StartupInfo);
  if RunMinimized then
    begin
      StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartupInfo.wShowWindow := SW_SHOWMINIMIZED;
    end;
  if Folder <> '' then WorkingDirP := pchar(Folder)
  else WorkingDirP := nil;
  if not CreateProcess(nil, pchar(CmdLine), nil, nil, false, 0, nil, WorkingDirP, StartupInfo, ProcessInfo) then
    begin
      Result := false;
      ErrorCode := GetLastError;
      exit;
    end;
  with ProcessInfo do
    begin
      CloseHandle(hThread);
      if WaitUntilIdle then WaitForInputIdle(hProcess, INFINITE);
      if WaitUntilTerminated then
        repeat
          Application.ProcessMessages;
        until MsgWaitForMultipleObjects(1, hProcess, false, INFINITE, QS_ALLINPUT) <> WAIT_OBJECT_0 + 1;
      CloseHandle(hProcess);
    end;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  FileName, Parameters, Folder: string;
  Error: integer;
  OK: boolean;
begin
  Folder := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) + 'bin\';
  FileName := Folder + 'starter.exe';
  Parameters := '-lang rus';
  OK := ExecuteProcess(FileName, Parameters, Folder, false, false, false, Error);
  if not OK then
    begin
      Error := GetLastError;
      ShowMessage('Error: ' + IntToStr(Error));
    end;
end;
Run Code Online (Sandbox Code Playgroud)

CreateProcess文档