-1

所以我正在尝试使用 delphi 和 ShellExecuteEx 进行存档,我的代码是:

 Result := False;
  DecodeDate(now,y,m,d);
  NumeFisier := dir+'\Export_'+IntToStr(y)+'.'+IntToStr(m)+'.'+IntToStr(d)+'.zip';
  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 := nil;
    exInfo.lpFile  := PAnsiChar('C:\Windows\System32\cmd.exe');
   exInfo.lpParameters := PAnsiChar('C:\Program Files\7-Zip\7z.exe ' +'a ' + NumeFisier + ' ' + dir);
    nShow := SW_SHOWNORMAL;
   end;
   if ShellExecuteEx(@exInfo) then
    Ph := exInfo.hProcess
    else
     begin
     ShowMessage(SysErrorMessage(GetLastError));
     Result := true;
     exit;
    end;
   while WaitForSingleObject(exInfo.hProcess, 50) <> WAIT_OBJECT_0 do
     Application.ProcessMessages;
   CloseHandle(Ph);

  Result := true;

出于某种原因,这只会打开命令提示符而不执行存档。我怎样才能让它执行 7z.exe 文件。

我尝试使用 ShellExecute 并且效果很好,但是我必须检查该过程是否完成,所以我坚持使用 ShellExecuteEx

4

1 回答 1

3

没有必要参与cmd.exe。那是命令解释器。您想执行不同的可执行文件,请直接执行。

您不想使用ShellExecuteEx它,因为它的通用性比您需要的要多得多。这里ShellExecuteEx所做的就是调用CreateProcess. 你应该直接这样做,避免中间人。更重要的是,调用CreateProcess可以让您轻松隐藏控制台窗口。通过CREATE_NO_WINDOW以实现这一目标。

最后,还有比你的代码更好的等待方法。使用MsgWaitForMultipleObjects允许您避免轮询。并将此代码放入线程中可以避免调用Application.ProcessMessages.

procedure WaitUntilSignaled(Handle: THandle; ProcessMessages: Boolean);
var
  retval: DWORD;
begin
  if ProcessMessages then begin
    Application.ProcessMessages;//in case there are messages already in the queue
    while True do begin
      retval := MsgWaitForMultipleObjects(1, Handle, False, INFINITE, QS_ALLEVENTS);
      case retval of
      WAIT_OBJECT_0,WAIT_ABANDONED_0:
        break;
      WAIT_OBJECT_0+1:
        Application.ProcessMessages;
      WAIT_FAILED:
        RaiseLastOSError;
      end;
    end;
  end else begin
    Win32Check(WaitForSingleObject(Handle, INFINITE)<>WAIT_FAILED);
  end;
end;

procedure ExecuteProcess(
  const ExecutablePath: string;
  const Arguments: string;
  const CurrentDirectory: string;
  const Wait: Boolean;
  const CreationFlags: DWORD
);
var
  si: TStartupInfo;
  pi: TProcessInformation;
  MyCurrentDirectory: PChar;
begin
  ZeroMemory(@si, SizeOf(si));
  si.cb := SizeOf(si);

  if CurrentDirectory <> '' then begin
    MyCurrentDirectory := PChar(CurrentDirectory);
  end else begin
    MyCurrentDirectory := nil;
  end;

  Win32Check(CreateProcess(
    nil,
    PChar('"' + ExecutablePath + '" ' + Arguments),
    nil,
    nil,
    False,
    CreationFlags,
    nil,
    MyCurrentDirectory,
    si,
    pi
  ));
  try
    if Wait then begin
      WaitUntilSignaled(pi.hProcess, True);
    end;
  finally
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  end;
end;
于 2014-12-18T08:16:28.160 回答