使用 ShellExecute 从 Delphi 执行任务
Task Execution from Delphi using ShellExecute
几天来,我一直在尝试弄清楚如何使用 ShellExecute 在 Delphi 中执行具有指定任务的 ExeFile。下面是我的最新代码,给出了我的错误 "The specified file was not found":
procedure TfrmGTX.btnQuickBooksSyncClick(Sender: TObject);
var
ExecuteResult : integer;
Path : string;
begin
Path := IncludeTrailingPathDelimiter(ExtractFilePath('MyApp.exe'));
ExecuteResult := ShellExecute(0, nil, PChar(Path + 'cd C:\Program Files
(x86)\Folder1\Folder2\MyApp.exe a_Sales /Connect'), nil, nil,
SW_SHOWNORMAL);
case ExecuteResult of
0 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
operating system is out of memory or resources.');
2 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
specified file was not found.');
3 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
specified path was not found.');
5 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Windows 95
only: The operating system denied access to the specified
file.');
8 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Windows 95
only: There was not enough memory to complete the operation.');
10 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Wrong
Windows version.');
11 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The .EXE
file is invalid (non-Win32 .EXE or error in .EXE image).');
12 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Application
was designed for a different operating system.');
13 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Application
was designed for MS-DOS 4.0.');
15 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Attempt to
load a real-mode program.');
16 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Attempt to
load a second instance of an application with non-readonly data
segments.');
19 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Attempt to
load a compressed application file.');
20 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Dynamic-
link library (DLL) file failure.');
26 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': A sharing
violation occurred.');
27 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
filename association is incomplete or invalid.');
28 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The DDE
transaction could not be completed because the request timed
out.');
29 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The DDE
transaction failed.');
30 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The DDE
transaction could not be completed because other DDE
transactions were being processed.');
31 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': There is no
application associated with the given filename extension.');
32 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Windows 95
only: The specified dynamic-link library was not found.');
else ShowMessage('Unknown Error.');
end;
end;
我确定这里遗漏了一个小故障。任何帮助请...
非常感谢!
更新:删除了这部分。
解决方案:我删除了IncludeTrailingPathDelimiter 和ExtractFilePath,使用了ShellExecuteEx,并更正了参数。就是这样,能够解决问题。
procedure TfrmGTX.btnQBSyncClick(Sender: TObject);
var
FileName, Parameters, Folder, Directory: string;
sei: TShellExecuteInfo;
Error: DWORD;
OK: boolean;
begin
Folder := 'C:\Program Files (x86)\Folder1\Folder2\';
FileName := Folder + 'MyApp';
Parameters := 'MyTask';
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;
case Error of
0 : ShowMessage('Error ' + IntToStr(Error) + ': The operating system is out of memory or resources.');
2 : ShowMessage('Error ' + IntToStr(Error) + ': The specified file was not found.');
3 : ShowMessage('Error ' + IntToStr(Error) + ': The specified path was not found.');
5 : ShowMessage('Error ' + IntToStr(Error) + ': Windows 95 only: The operating system denied access to the specified file.');
8 : ShowMessage('Error ' + IntToStr(Error) + ': Windows 95 only: There was not enough memory to complete the operation.');
10 : ShowMessage('Error ' + IntToStr(Error) + ': Wrong Windows version.');
11 : ShowMessage('Error ' + IntToStr(Error) + ': The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).');
12 : ShowMessage('Error ' + IntToStr(Error) + ': Application was designed for a different operating system.');
13 : ShowMessage('Error ' + IntToStr(Error) + ': Application was designed for MS-DOS 4.0.');
15 : ShowMessage('Error ' + IntToStr(Error) + ': Attempt to load a real-mode program.');
16 : ShowMessage('Error ' + IntToStr(Error) + ': Attempt to load a second instance of an application with non-readonly data segments.');
19 : ShowMessage('Error ' + IntToStr(Error) + ': Attempt to load a compressed application file.');
20 : ShowMessage('Error ' + IntToStr(Error) + ': Dynamic-link library (DLL) file failure.');
26 : ShowMessage('Error ' + IntToStr(Error) + ': A sharing violation occurred.');
27 : ShowMessage('Error ' + IntToStr(Error) + ': The filename association is incomplete or invalid.');
28 : ShowMessage('Error ' + IntToStr(Error) + ': The DDE transaction could not be completed because the request timed out.');
29 : ShowMessage('Error ' + IntToStr(Error) + ': The DDE transaction failed.');
30 : ShowMessage('Error ' + IntToStr(Error) + ': The DDE transaction could not be completed because other DDE transactions were being processed.');
31 : ShowMessage('Error ' + IntToStr(Error) + ': There is no application associated with the given filename extension.');
32 : ShowMessage('Error ' + IntToStr(Error) + ': Windows 95 only: The specified dynamic-link library was not found.');
else ShowMessage('Unknown Error.');
end;
end;
end;
您的 ShellExecute
内容无效。如果必须更改目录,请先使用 CHDIR
命令。
此外,您应该将参数作为参数传递给 ShellExecute
调用。
这是有效的
ExecuteResult := ShellExecute(0, 'open', PChar('C:\Program Files (x86)\Intuit\QuickBooks Enterprise Solutions 18.0\qbw32.exe'), pchar('a_Sales /Connect'), nil, SW_SHOWNORMAL);
我创建了 3 个不同的函数并根据需要使用它们:
function ExecWithShellExecute(AName, CLine: string; run_mode: string; var iErr: int64): boolean;
begin
if run_mode = '' then
run_mode := 'open';
iErr := ShellExecute(Handle, PWideChar(run_mode), PWideChar(AName), PWideChar(CLine),
PWideChar(ExtractFilePath(AName)), SW_HIDE);
Result := iErr > 32;
end;
function ExecWithShell(AName, CLine: string; run_mode: string;
var hProcess: DWord; var iErr: int64): boolean;
var
ShExecInfo: TShellExecuteInfo;
begin
Result := False;
hProcess := 0;
ZeroMemory(@ShExecInfo, SizeOf(ShExecInfo));
ShExecInfo.cbSize := sizeof(ShExecInfo);
ShExecInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
if run_mode = '' then
ShExecInfo.lpVerb := nil
else
ShExecInfo.lpVerb := PWideChar(run_mode);
ShExecInfo.lpFile := PWideChar(AName);
ShExecInfo.lpParameters := PWideChar(CLine);
ShExecInfo.lpDirectory := PWideChar(ExtractFilePath(AName));
ShExecInfo.nShow := SW_HIDE;
ShExecInfo.hInstApp := 0;
if ShellExecuteEx(@ShExecInfo) then
begin
hProcess := ShExecInfo.hProcess;
Result := hProcess > 0;
end else
iErr := GetLastError;
end;
function ExecWithCmdLine(AName, CLine: string;
var pInfo: TProcessInformation; var iErr: int64): boolean;
var
sInfo: TStartupInfo;
AppName, AppWDir, CmdLine: string;
begin
AppName := AName; //Full path & name of Your App.
AppWDir := ExtractFileDir(AppName);
CmdLine := ' ' + CLine;
ZeroMemory(@pInfo, SizeOf(pInfo));
ZeroMemory(@sInfo, sizeof(TStartupInfo));
sInfo.cb := sizeof(TStartupInfo);
sInfo.dwFlags := STARTF_FORCEONFEEDBACK or STARTF_FORCEOFFFEEDBACK;
Result := CreateProcess(PWideChar(AppName), PWideChar(CmdLine), nil, nil, False,
CREATE_DEFAULT_ERROR_MODE or
CREATE_NEW_PROCESS_GROUP or
NORMAL_PRIORITY_CLASS or
CREATE_NO_WINDOW,
nil, PWideChar(AppWDir), sInfo, pInfo);
if not Result then
iErr := GetLastError;
end;
几天来,我一直在尝试弄清楚如何使用 ShellExecute 在 Delphi 中执行具有指定任务的 ExeFile。下面是我的最新代码,给出了我的错误 "The specified file was not found":
procedure TfrmGTX.btnQuickBooksSyncClick(Sender: TObject);
var
ExecuteResult : integer;
Path : string;
begin
Path := IncludeTrailingPathDelimiter(ExtractFilePath('MyApp.exe'));
ExecuteResult := ShellExecute(0, nil, PChar(Path + 'cd C:\Program Files
(x86)\Folder1\Folder2\MyApp.exe a_Sales /Connect'), nil, nil,
SW_SHOWNORMAL);
case ExecuteResult of
0 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
operating system is out of memory or resources.');
2 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
specified file was not found.');
3 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
specified path was not found.');
5 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Windows 95
only: The operating system denied access to the specified
file.');
8 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Windows 95
only: There was not enough memory to complete the operation.');
10 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Wrong
Windows version.');
11 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The .EXE
file is invalid (non-Win32 .EXE or error in .EXE image).');
12 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Application
was designed for a different operating system.');
13 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Application
was designed for MS-DOS 4.0.');
15 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Attempt to
load a real-mode program.');
16 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Attempt to
load a second instance of an application with non-readonly data
segments.');
19 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Attempt to
load a compressed application file.');
20 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Dynamic-
link library (DLL) file failure.');
26 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': A sharing
violation occurred.');
27 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The
filename association is incomplete or invalid.');
28 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The DDE
transaction could not be completed because the request timed
out.');
29 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The DDE
transaction failed.');
30 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': The DDE
transaction could not be completed because other DDE
transactions were being processed.');
31 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': There is no
application associated with the given filename extension.');
32 : ShowMessage('Error ' + IntToStr(ExecuteResult) + ': Windows 95
only: The specified dynamic-link library was not found.');
else ShowMessage('Unknown Error.');
end;
end;
我确定这里遗漏了一个小故障。任何帮助请...
非常感谢!
更新:删除了这部分。
解决方案:我删除了IncludeTrailingPathDelimiter 和ExtractFilePath,使用了ShellExecuteEx,并更正了参数。就是这样,能够解决问题。
procedure TfrmGTX.btnQBSyncClick(Sender: TObject);
var
FileName, Parameters, Folder, Directory: string;
sei: TShellExecuteInfo;
Error: DWORD;
OK: boolean;
begin
Folder := 'C:\Program Files (x86)\Folder1\Folder2\';
FileName := Folder + 'MyApp';
Parameters := 'MyTask';
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;
case Error of
0 : ShowMessage('Error ' + IntToStr(Error) + ': The operating system is out of memory or resources.');
2 : ShowMessage('Error ' + IntToStr(Error) + ': The specified file was not found.');
3 : ShowMessage('Error ' + IntToStr(Error) + ': The specified path was not found.');
5 : ShowMessage('Error ' + IntToStr(Error) + ': Windows 95 only: The operating system denied access to the specified file.');
8 : ShowMessage('Error ' + IntToStr(Error) + ': Windows 95 only: There was not enough memory to complete the operation.');
10 : ShowMessage('Error ' + IntToStr(Error) + ': Wrong Windows version.');
11 : ShowMessage('Error ' + IntToStr(Error) + ': The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).');
12 : ShowMessage('Error ' + IntToStr(Error) + ': Application was designed for a different operating system.');
13 : ShowMessage('Error ' + IntToStr(Error) + ': Application was designed for MS-DOS 4.0.');
15 : ShowMessage('Error ' + IntToStr(Error) + ': Attempt to load a real-mode program.');
16 : ShowMessage('Error ' + IntToStr(Error) + ': Attempt to load a second instance of an application with non-readonly data segments.');
19 : ShowMessage('Error ' + IntToStr(Error) + ': Attempt to load a compressed application file.');
20 : ShowMessage('Error ' + IntToStr(Error) + ': Dynamic-link library (DLL) file failure.');
26 : ShowMessage('Error ' + IntToStr(Error) + ': A sharing violation occurred.');
27 : ShowMessage('Error ' + IntToStr(Error) + ': The filename association is incomplete or invalid.');
28 : ShowMessage('Error ' + IntToStr(Error) + ': The DDE transaction could not be completed because the request timed out.');
29 : ShowMessage('Error ' + IntToStr(Error) + ': The DDE transaction failed.');
30 : ShowMessage('Error ' + IntToStr(Error) + ': The DDE transaction could not be completed because other DDE transactions were being processed.');
31 : ShowMessage('Error ' + IntToStr(Error) + ': There is no application associated with the given filename extension.');
32 : ShowMessage('Error ' + IntToStr(Error) + ': Windows 95 only: The specified dynamic-link library was not found.');
else ShowMessage('Unknown Error.');
end;
end;
end;
您的 ShellExecute
内容无效。如果必须更改目录,请先使用 CHDIR
命令。
此外,您应该将参数作为参数传递给 ShellExecute
调用。
这是有效的
ExecuteResult := ShellExecute(0, 'open', PChar('C:\Program Files (x86)\Intuit\QuickBooks Enterprise Solutions 18.0\qbw32.exe'), pchar('a_Sales /Connect'), nil, SW_SHOWNORMAL);
我创建了 3 个不同的函数并根据需要使用它们:
function ExecWithShellExecute(AName, CLine: string; run_mode: string; var iErr: int64): boolean;
begin
if run_mode = '' then
run_mode := 'open';
iErr := ShellExecute(Handle, PWideChar(run_mode), PWideChar(AName), PWideChar(CLine),
PWideChar(ExtractFilePath(AName)), SW_HIDE);
Result := iErr > 32;
end;
function ExecWithShell(AName, CLine: string; run_mode: string;
var hProcess: DWord; var iErr: int64): boolean;
var
ShExecInfo: TShellExecuteInfo;
begin
Result := False;
hProcess := 0;
ZeroMemory(@ShExecInfo, SizeOf(ShExecInfo));
ShExecInfo.cbSize := sizeof(ShExecInfo);
ShExecInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
if run_mode = '' then
ShExecInfo.lpVerb := nil
else
ShExecInfo.lpVerb := PWideChar(run_mode);
ShExecInfo.lpFile := PWideChar(AName);
ShExecInfo.lpParameters := PWideChar(CLine);
ShExecInfo.lpDirectory := PWideChar(ExtractFilePath(AName));
ShExecInfo.nShow := SW_HIDE;
ShExecInfo.hInstApp := 0;
if ShellExecuteEx(@ShExecInfo) then
begin
hProcess := ShExecInfo.hProcess;
Result := hProcess > 0;
end else
iErr := GetLastError;
end;
function ExecWithCmdLine(AName, CLine: string;
var pInfo: TProcessInformation; var iErr: int64): boolean;
var
sInfo: TStartupInfo;
AppName, AppWDir, CmdLine: string;
begin
AppName := AName; //Full path & name of Your App.
AppWDir := ExtractFileDir(AppName);
CmdLine := ' ' + CLine;
ZeroMemory(@pInfo, SizeOf(pInfo));
ZeroMemory(@sInfo, sizeof(TStartupInfo));
sInfo.cb := sizeof(TStartupInfo);
sInfo.dwFlags := STARTF_FORCEONFEEDBACK or STARTF_FORCEOFFFEEDBACK;
Result := CreateProcess(PWideChar(AppName), PWideChar(CmdLine), nil, nil, False,
CREATE_DEFAULT_ERROR_MODE or
CREATE_NEW_PROCESS_GROUP or
NORMAL_PRIORITY_CLASS or
CREATE_NO_WINDOW,
nil, PWideChar(AppWDir), sInfo, pInfo);
if not Result then
iErr := GetLastError;
end;