Delphi 为什么';当我使用ShellExecute时,我的命令是否会像我预期的那样运行?
我试图从我的Delphi代码中使用命令行实用程序(它与dos命令行中的测试一起工作)将PDF转储为文本 这是我的密码Delphi 为什么';当我使用ShellExecute时,我的命令是否会像我预期的那样运行?,delphi,winapi,command-line,delphi-2010,shellexecute,Delphi,Winapi,Command Line,Delphi 2010,Shellexecute,我试图从我的Delphi代码中使用命令行实用程序(它与dos命令行中的测试一起工作)将PDF转储为文本 这是我的密码 if fileexists(ExtractFilePath(Application.ExeName) + 'pdftotext.exe') then begin ShellExecute(H,'open', 'pdftotext.exe', PWideChar(fFileName), nil, SW_SHOWNORMAL); if fileExists(changeFil
if fileexists(ExtractFilePath(Application.ExeName) + 'pdftotext.exe') then
begin
ShellExecute(H,'open', 'pdftotext.exe', PWideChar(fFileName), nil, SW_SHOWNORMAL);
if fileExists(changeFileExt(fFileName, '.txt')) then
Lines.LoadFromFile(changeFileExt(fFileName, '.txt'))
else
ShowMessage('File Not found');
end;
在代码中放置断点并单步执行时,它会使
if fileExists(changeFileExt(fFileName, '.txt')) then
行,但返回false,因此调用了Shellexecute,但从未转储任何文件
我做错了什么?ShellExecute不会等待调用的程序完成运行。你可能检查文件太快了。文件还没有创建 在检查输出文件之前,运行程序并等待其终止
ShellExecute
没有返回足够的信息,因此您应该尝试CreateProcess
。有几个例子可以说明如何做到这一点。试试这个:
事实证明,将填充路径添加到可执行文件使其工作正常
uses
Forms, ShellAPI, SysConst, SysUtils;
procedure Pdf2Text(const fFileName: string; const Lines: TStrings);
var
H: HWND;
PdfToTextPathName: string;
ReturnValue: Integer;
TxtFileName: string;
begin
H := 0;
PdfToTextPathName := ExtractFilePath(Application.ExeName) + 'pdftotext.exe'; // full path
if FileExists(PdfToTextPathName) then
begin
ReturnValue := ShellExecute(0,'open', PWideChar(PdfToTextPathName), PWideChar(fFileName), nil, SW_SHOWNORMAL);
if ReturnValue <= 32 then
RaiseLastOsError();
// note: the code below this line will crash when pdftotext.exe does not finish soon enough; you should actually wait for pdftotext.exe completion
TxtFileName := ChangeFileExt(fFileName, '.txt');
if FileExists(TxtFileName) then
Lines.LoadFromFile(TxtFileName)
else
raise EFileNotFoundException.CreateRes(@SFileNotFound);
end;
end;
使用
表单、ShellAPI、SysConst、SysUtils;
过程Pdf2Text(常量fFileName:string;常量行:TStrings);
变量
H:HWND;
PdfToTextPathName:字符串;
返回值:整数;
TxtFileName:字符串;
开始
H:=0;
PdfToTextPathName:=ExtractFilePath(Application.ExeName)+'pdftotext.exe';//全路径
如果文件存在(PdfToTextPathName),则
开始
ReturnValue:=shell执行(0,'open',PWideChar(PdfToTextPathName),PWideChar(fFileName),nil,SW_SHOWNORMAL);
如果你很抱歉,那末一刻是不需要的。我正在剪切和粘贴其他地方的代码。fFileName是在过程中定义的字符串变量,出于您自己的考虑,您还应该正确格式化代码(首先,使用一致的缩进)。而且,为了最终用户的利益,“未找到文件”是一条可怕的错误消息(“未找到文件”也是如此)。谢谢,但这是目前的实验性编码,远不是可交付的(如果愿意,请进行测试)。showMessage是我用来测试文件是否被发现的可能的@Shane副本:如果Rob的假设是正确的,你也可以使用Windows资源管理器来测试文件是否真的被创建了。+1。似乎就是这样。(但是OP可以通过使用Windows资源管理器自己很容易地意识到这个问题…)或者使用ShellExecuteEX(),它提供了新进程的进程id,因此您可以使用WaitForSingleObject()@Andreas-您总是那么关键吗?你真的相信每个人都和你一样聪明,他们应该能够解决这些问题吗?如果是这样的话,就没有理由建这个网站了,现在就有了。好好生活!这里要吸取的教训是:永远不要忽略API函数的返回值。如果您以前检查过结果,您可能会看到它返回Error\u File\u Not\u Found
,这将提示您找出为什么ShellExecute
找不到您要求它执行的文件。另一个教训:不要假设当前工作目录是您认为的目录。Shane,你以为操作系统会知道pdftotext.exe在哪里。如果没有完全限定的路径,操作系统将使用path
环境变量查找程序,其中包括当前程序的工作目录。通常,这将是当前EXE所在的目录,但这可能会改变。如果你知道所需的程序应该在哪里,然后像你的回答那样明确地询问该位置。事实上,我没有发布整行内容,这是呼叫的处理部分。我用零替换了它,它可以运行ShellExecute(0,'open',PWideChar(ExtractFilePath(Application.ExeName)+'pdftotext.exe'),PWideChar(fFileName),nil,SW_SHOWNORMAL);