Eezygzy 0 Posted July 31, 2023 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? Share this post Link to post
Remy Lebeau 1401 Posted July 31, 2023 (edited) 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 July 31, 2023 by Remy Lebeau 1 Share this post Link to post
David Heffernan 2346 Posted July 31, 2023 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
Eezygzy 0 Posted August 1, 2023 Thank you very much it works perfectly now. Share this post Link to post
Shrinavat 16 Posted August 3, 2023 @Remy Lebeau Could you please explain what is the point of using UniqueString (sCommand)? 1 Share this post Link to post
David Heffernan 2346 Posted August 3, 2023 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. 1 Share this post Link to post
Remy Lebeau 1401 Posted August 3, 2023 (edited) 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 August 3, 2023 by Remy Lebeau 1 Share this post Link to post