开发者

Why doesn't my command run like I expected when I use ShellExecute?

I am trying to dump a PDF to text using a command line utility (It works with tests from dos command line) from my Delphi code.

Here is my code

if fileexists(ExtractFilePath(Application.ExeName) + 'pdftotext.exe') then
begin
  ShellExecute(H,'open', 'pdftotext.exe', PWideChar(fFileName), nil, SW_SHOWNORMAL);
  if fileExists开发者_C百科(changeFileExt(fFileName, '.txt')) then
    Lines.LoadFromFile(changeFileExt(fFileName, '.txt'))
  else
    ShowMessage('File Not found');
end;

When placing breakpoints in code and stepping through, it makes it to the

if fileExists(changeFileExt(fFileName, '.txt')) then  

line but returns false, so the Shellexecute was called but no file was ever dumped

What have I done wrong?


ShellExecute doesn't wait for the invoked program to finish running. You're probably checking for the file too soon. The file simply hasn't been created yet.

Run the program and wait for it to terminate before you check for the output file. ShellExecute doesn't return enough information for you to do that, so you should try CreateProcess instead. There are several examples of how to do that. Try this:

How can I wait for a command-line program to finish?


It turns out, that adding the fill path to the execuatble made it work just fine

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;

Edit: Some code cleanup helps big time to catch errors early on, especially when testing a proof of concept.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜