Delphi 为什么';当我使用ShellExecute时,我的命令是否会像我预期的那样运行?

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

我试图从我的Delphi代码中使用命令行实用程序(它与dos命令行中的测试一起工作)将PDF转储为文本

这是我的密码

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