Recent

Author Topic: [SOLVED] TProcess execution fails with error code 2 (ERROR_FILE_NOT_FOUND)  (Read 2183 times)

artem101

  • Full Member
  • ***
  • Posts: 120
Hello.

My program has ability to execute any user provided command after certain action. I use TProcess class for this task. The problem is that every COPY, DEL and maybe some other commands always fails with error code 2 (ERROR_FILE_NOT_FOUND).

Code: Pascal  [Select][+][-]
  1. procedure RunCmdInbackground(ACmd: String);
  2. var
  3.   proc: TProcess;
  4. begin
  5.   proc := TProcess.Create(nil);
  6.   try
  7.     proc.CommandLine := ACmd;
  8.     proc.Execute;
  9.   finally
  10.     proc.Free;
  11.   end;
  12. end;

Example 1:
Code: Pascal  [Select][+][-]
  1. RunCmdInbackground('copy "c:\tmp\file.txt" "c:\tmp\file_copy.txt"');
Quote
EProcess: Failed to execute copy "c:\tmp\file.txt" "c:\tmp\file_copy.txt" : 2

Example 2:
Code: Pascal  [Select][+][-]
  1. RunCmdInbackground('del "c:\tmp\file.txt"');
Quote
EProcess: Failed to execute del "c:\tmp\file.txt" : 2

Both examples succesfully run in console.

However next example sucessfully works:
Code: Pascal  [Select][+][-]
  1. RunCmdInbackground('notepad "c:\tmp\file.txt"');

What is wrong?

Tested on Windows 7 64-bit with Lazarus 2.2.4 32-bit.
« Last Edit: January 01, 2024, 10:57:13 am by artem101 »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: TProcess execution fails with error code 2 (ERROR_FILE_NOT_FOUND)
« Reply #1 on: December 28, 2023, 09:19:41 pm »
Those programs "copy"  an "del"  can't be found. There is no such EXE or COM in the path.

To fix that run over cmd /c

Tested example

Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2.  
  3. uses process;
  4.  
  5. var s : string;
  6. begin
  7.   runcommand('cmd.exe',['/c','copy ..\genxtest.pp ..\genxtest2.pp'],s);
  8. end.

It is generally considered robust to not rely on the working directory in GUI Programs, because e.g. file open dialogs might change it. Try to craft such commands with whole paths.

Of course there are perfectly fine ways of doing this using

https://www.freepascal.org/docs-html/rtl/sysutils/deletefile.html

and

https://lazarus-ccr.sourceforge.io/docs/lazutils/fileutil/copyfile.html

without executing shell commands Much faster too.

artem101

  • Full Member
  • ***
  • Posts: 120
Re: TProcess execution fails with error code 2 (ERROR_FILE_NOT_FOUND)
« Reply #2 on: December 29, 2023, 09:09:56 am »
To fix that run over cmd /c

Thanks. I modified my code as you suggest and it works.

Code: Pascal  [Select][+][-]
  1.   proc := TProcess.Create(nil);
  2.   try
  3.     proc.Executable:='cmd.exe';
  4.     proc.Parameters.Add('/c');
  5.     proc.Parameters.Add(ACmd);
  6.     proc.Execute;
  7.   finally
  8.     proc.Free;
  9.   end;  
  10.  

However I discovered that command execution fails if file path contains non-ascii symbols.

Also a small problem that in GUI application terminal window displays for a second. Is it possible to make it completely invisible?

Of course there are perfectly fine ways of doing this using

https://www.freepascal.org/docs-html/rtl/sysutils/deletefile.html

and

https://lazarus-ccr.sourceforge.io/docs/lazutils/fileutil/copyfile.html

without executing shell commands Much faster too.

Yes, I know. Copy and delete commands are given just as an example. In general may be executed any custom command. Therefore I use execution in the shell.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: TProcess execution fails with error code 2 (ERROR_FILE_NOT_FOUND)
« Reply #3 on: December 29, 2023, 01:18:49 pm »
For unicode it is easiest to change the whole application to utf8 in project->project options -> application and then enabling " use manifest resource"  and "Ansi code page is utf-8".

This does require Windows 10+ though (strictly speaking the earliest Windows 10s wouldn't even work, but they will be very rare).

You can also enable "long path awareness" here to avoid trouble with paths longer than 260 chars.

As for the windows, runcommand has variants with options and by passing ponoconsole , you can hide the window.

Code: Pascal  [Select][+][-]
  1. runcommand('cmd.exe',['/c','copy ..\genxtest.pp ..\genxtest2.pp'],s,[pnoconsole]);  // does not allocate a full console. Ok for most programs
  2.  

or
Code: Pascal  [Select][+][-]
  1. runcommand('cmd.exe',['/c','copy ..\genxtest.pp ..\genxtest2.pp'],s,[],[swohide]); // does allocate, but hides the window. Better for programs that e.g. uses color or cursor position in the console.
  2.  
« Last Edit: January 01, 2024, 02:46:19 pm by marcov »

NickyTi

  • New Member
  • *
  • Posts: 12
Re: TProcess execution fails with error code 2 (ERROR_FILE_NOT_FOUND)
« Reply #4 on: December 29, 2023, 10:08:07 pm »
Quote
Also a small problem that in GUI application terminal window displays for a second. Is it possible to make it completely invisible?

Code: Pascal  [Select][+][-]
  1. proc := TProcess.Create(nil);
  2. try
  3.   proc.Executable:='cmd.exe';
  4.   proc.Parameters.Add('/c');
  5.   proc.Parameters.Add(ACmd);
  6.   proc.Options := [poNoConsole]; // try this !!!
  7.   proc.Execute;
  8. finally
  9.   proc.Free;
  10. end;  
  11.  

artem101

  • Full Member
  • ***
  • Posts: 120
poNoConsole works. Thanks.

 

TinyPortal © 2005-2018