Jump to content
Eezygzy

.exe File not outputting

Recommended Posts

I am trying to run an exe file in command prompt with the syntax '"C:\PDF\pdftotext.exe" "C:\PDF\ABC.PDF"'. When I run it manually it creates a file called ABC.txt in the same folder that the PDF is in. I am trying to get it to do that in Delphi but when I make it run there are no errors and it does not output anything. I tried both of the syntaxes in the picture below and none of them work. Could someone help me?

Screenshot 2023-07-31 204946.png

Share this post


Link to post

Why are you using ShellExecute() to run pdftotext.exe indirectly via cmd.exe, instead of using CreateProcess() to run pdftotext.exe directly?  Try something more like this:

procedure TForm1.Button1Click(Sender: TObject);
var
  sCommand: string;
  si: TStartupInfo;
  pi: TProcessInformation;
begin

  sCommand := '"C:\PDF\pdftotext.exe" "C:\PDF\ABC.PDF"';
  UniqueString(sCommand);
  
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := SH_HIDE;

  if CreateProcess(nil, PChar(sCommand), nil, nil, False, CREATE_NO_WINDOW, nil, nil, si, pi) then
  begin
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
  end;

end;

 

Edited by Remy Lebeau
  • Haha 1

Share this post


Link to post

Why are you asking the shell to create a cmd process which in turn creates another process. Use CreateProcess and miss out the cmd middle man. 

Share this post


Link to post

It's because the second arg must refer to writeable memory and UniqueString ensures that. A websearch on CreateProcess and UniqueString will yield many discussions of the issue. 

  • Thanks 1

Share this post


Link to post

To elaborate, only the Unicode version of CreateProcess() requires the 2nd parameter to point at writable memory, as it may have to internally normalize/alter the Unicode string.  This is documented behavior.

 

In this example, sCommand is pointing at a string literal (ie, its RefCnt is -1), so the compiler won't allocate a block of writable memory for sCommand unless it is modified (ie, copy-on-write semantics), which this code doesn't do.  So the UniqueString() is used to ensure that sCommand is pointing at a unique and writable string in memory (ie, its RefCnt is 1).

 

If you use string variables to build up sCommand, then the UniqueString() won't be needed since the resulting string will be unique and writable, eg:

var
  sProgram, sFilename, sCommand: string;

sProgram := 'C:\PDF\pdftotext.exe';
sFilename := 'C:\PDF\ABC.PDF';
sCommand := '"' + sProgram + '" "' + sFilename + '"';
// or: sCommand := Format('"%s" "%s"', [sProgram, sFilename]);
// etc...

 

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×