views:

101

answers:

2

If I run a process with ShellExecute (or in .net with System.Diagnostics.Process.Start()) the filename process to start doesn't need to be a full path.

If I want to start notepad, I can use

Process.Start("notepad.exe");

instead of

Process.Start(@"c:\windows\system32\notepad.exe");

because the direcotry c:\windows\system32 folder is part of the PATH environment variable.

how can I check if a file exists on the PATH without executing the process and without parsing the PATH variable?

System.IO.File.Exists("notepad.exe"); // returns false
(new System.IO.FileInfo("notepad.exe")).Exists; // returns false

but I need something like this:

System.IO.File.ExistsOnPath("notepad.exe"); // should return true

and

System.IO.File.GetFullPath("notepad.exe"); // (like unix which cmd) should return
                                           // c:\windows\system32\notepad.exe

Is there a predefined class to do this task available in the BCL?

+5  A: 

I think there's nothing built-in, but you could do something like this:

public static bool ExistsOnPath(string fileName)
{
    if (GetFullPath(fileName) != null)
        return true;
    return false;
}

public static string GetFullPath(string fileName)
{
    if (File.Exists(fileName))
        return Path.GetFullPath(fileName);

    var values = Environment.GetEnvironmentVariable("PATH");
    foreach (var path in values.Split(';'))
    {
        var fullPath = Path.Combine(path, fileName);
        if (File.Exists(fullPath))
            return fullPath;
    }
    return null;
}
digEmAll
If you are going to do this, I suggest turning these into Extension Methods...http://msdn.microsoft.com/en-us/library/bb383977.aspx
Aaron
@Aaron: Are you sure you would see `GetFullPath` as extension method for `string` ? It would sound odd to me... Maybe could have sense for `FileInfo`...
digEmAll
@digEmAll Yes it would be strange when using a string. However I think it would make sense to wrap the above functionality from both methods into a single extension method titled ExistsOnPath which hangs off FileInfo as you mentioned.
Aaron
@Aaron: For several reasons (e.g. why I have to pass through FileInfo if I only need a string...), I still prefer them as static methods, perhaps wrapped in Utilities static class, but I understand that could be arguable... Anyway, for the questioner, is easy to trasform the above code in Extension method ;)
digEmAll
@digEmAll...yep, no wrong answer here...
Aaron
+4  A: 

This is risky, there's a lot more to it than just searching the directories in the PATH. Try this:

 Process.Start("wordpad.exe");

The executable is stored in c:\Program Files\Windows NT\Accessories on my machine, that directory is not on the path. The HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths key plays a role in finding executables. I'm fairly sure there are additional land-mines like this around, directory virtualization in 64-bit versions of Windows could trip you up for example.

To make this more reliable, I think you need to pinvoke AssocQueryString(). Not sure, never had the need. The better approach is certainly to not have to ask the question.

Hans Passant
the application that I want to query registers itself to the path (mysqldump.exe). If not, or if not installed, I want to disable the option to use mysqlbackup from a windows forms application. I just don't want to hard code the path to the file.
SchlaWiener
It is *very* rare these days for installers to modify the PATH. Especially for a utility, check that first. I would just use a setting with Application scope and default to "" here.
Hans Passant