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

时间:2014-12-02 12:53:58

标签: delphi shellexecute

我制作了一个游戏启动器,我使用了这个命令:

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

' -lang rus'作为参数。一切正常。游戏启动和语言是俄语(如果我把' -lang eng'它仍然正常,游戏是英语)。

starter.exe 应用程序位于名为'' bin ''的文件夹中。当我想将启动器重新定位在此文件夹之外时,我使用以下命令:

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

但是游戏还没有发布。实际上没有任何反应。 我应该改变什么?

2 个答案:

答案 0 :(得分:5)

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

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

解决方案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;

您可以在ShellExecute function documentation

找到错误代码列表

最常见的错误代码:

  • 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;

ShellExecuteEx documentation

解决方案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;

CreateProcess documentation

答案 1 :(得分:2)

您应该使用完全限定(绝对)路径。例如,如果您知道路径是

C:\Program Files (x86)\My Company\My Game\bin\starter.exe

你应该传递那个字符串。当然,您应该从不对这样的字符串进行硬编码,因为它可能在不同的系统上有所不同。如果您的应用程序是一般应用程序启动器,您将获得用户的路径。如果您的应用程序启动了您自己公司的游戏,您必须找到一种聪明的方式来传达路径。

您的问题并不清楚,但如果bin\starter.exe与您的应用程序的路径相关,则可以使用

ExtractFilePath(Application.ExeName) + 'bin\starter.exe'

顺便说一下,你可以通过查看ShellExecute的返回值自己想出这一切。当然,您已经仔细阅读了ShellExecute documentation,因此您知道返回值是什么。因此,您很容易识别ERROR_FILE_NOT_FOUND,并意识到您需要一个完全合格的路径。