0

I generate a ProcessStartInfo by referencing a filename-only executable, without giving the absolute path. I expect the operating system to resolve the concrete location by using the PATH environment variable.

However, on some installations, the PATH variable is not set correctly and upon starting the Process by calling Process.Start() it will throw a

System.ComponentModel.Win32Exception

The system cannot find the file specified

Are there programmatic options to check if the Process.Start will work beforehand?

I tried to use File.Exists(fileName), but this does only work for files located in the applications working directory.

In the command prompt you could use the following call to determine if it will work:

//example where a file is found
C:\>where calc.exe 
C:\Windows\System32\calc.exe

//example where a file is not found
C:\>where foo.exe
INFO: Could not find files for the given pattern(s).

Is there something alike in .net to determine beforehand if the file path can be resolved so that Process.Start() will not throw?

Marwie
  • 3,177
  • 3
  • 28
  • 49
  • It sounds like you already found the answer. Just call "where". – gunr2171 Nov 01 '21 at 16:00
  • 2
    And how would you handle the situation? Could you not just catch the exception and do the same in the catch block? – Klaus Gütter Nov 01 '21 at 16:03
  • Read the output first before trying to start a process? – Trevor Nov 01 '21 at 16:10
  • 2
    Strictly speaking that's impossible: the file can be found on check stage, but be deleted just before `Process.Start` tries to execute it. That's why try to execute the file and analyze the exception thrown if you've caught it. – Dmitry Bychenko Nov 01 '21 at 16:11
  • I'm guessing that catching the exception (though slow) isn't much slower than spinning up a new process (`C:\Windows\System32\where.exe`). What's wrong with catching the exception? – Flydog57 Nov 01 '21 at 16:12
  • If possible I like to check beforehand, since it is OS specific to [handle such exceptions](https://stackoverflow.com/questions/40829838/handle-win32exception-thrown-by-process-start) - I have to consider it for linux and windows systems alike. The concrete file is related to a preinstalled third party application it is rather unlikely that it will get deleted right in between the check and the call. Of course we also handle any sort of exception after the call, but this is a very generic error handling. The idea is to hint the user to a missing path entry before the error occurs. – Marwie Nov 01 '21 at 16:36
  • 3
    Does this help? https://stackoverflow.com/questions/3855956/check-if-an-executable-exists-in-the-windows-path/3856090#3856090 – Igor Nov 01 '21 at 18:07

1 Answers1

1

Like other commenters I propose to try{} and handle any problems in a catch(){}.

But I had a hard time figuring out how to identify the file-not-found error, because Process.Start() will only return a rather unspecific Win32Exception when the required executable is not found. So something like catch (FileNotFoundException ex) is not possible.

Here is, what I finally came up with:

try
{
    Process proc = new Process();
    proc.StartInfo.FileName = "...";
    proc.Start();
    proc.WaitForExit();
}
// check into Win32Exceptions and their error codes!
catch (Win32Exception winEx)  
{
    if (winEx.NativeErrorCode == 2 || winEx.NativeErrorCode == 3) {
        // 2 => "The system cannot find the FILE specified."
        // 3 => "The system cannot find the PATH specified."
        throw new Exception($"Executable not found in path");
    }
    else
    {
        // unknown Win32Exception, re-throw to show the raw error msg
        throw;
    }
}

For a list of Win32Exception.NativeErrorCodes see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d?redirectedfrom=MSDN

Jpsy
  • 20,077
  • 7
  • 118
  • 115