0

I know similar questions have been asked before but all the answers have been partial, for example suggesting I use AssocQueryString which I am doing. However I'm still failing to find some exe. For example the code below fails to find outlook.exe or firefox.exe - Typing outlook.exe into Windows Explorer address bar finds these almost instantley.

In the code below the exe fileName can be any local location on the users machine, it may or may not be on the users search path.

How can I improve this to find the files? (this is called from a 32 bit exe)

// for example, get actual full path to outlook.exe
string fullPath = FindPath("outlook.exe");

public static string FindPath(string fileName)
{
    uint length = UnsafeMethods.MAX_PATH;
    StringBuilder path = new StringBuilder((int)length);

    if (Path.GetDirectoryName(fileName) == string.Empty)
    {
        if (UnsafeMethods.AssocQueryString(UnsafeMethods.AssocF.OpenByExeName, UnsafeMethods.AssocStr.Executable, fileName, null, path, ref length) != 0)
        {
            IntPtr filePart = IntPtr.Zero;
            IntPtr wow64Value = IntPtr.Zero;

            // try 64 bit path
            UnsafeMethods.Wow64DisableWow64FsRedirection(ref wow64Value);
            bool success = UnsafeMethods.SearchPath(null, fileName, null, path.Capacity, path, ref filePart) > 0;
            UnsafeMethods.Wow64RevertWow64FsRedirection(wow64Value);

            if (!success)
            {
                // try 32 bit path
                success = UnsafeMethods.SearchPath(null, fileName, null, path.Capacity, path, ref filePart) > 0;
            }
        }

        return path.ToString();
    }
    else
    {
        return fileName;
    }
}
Michael T
  • 619
  • 6
  • 19
  • 1
    What is the `UnsafeMethods` class? – Rufus L Mar 19 '19 at 01:50
  • It defines std Win32 api calls – Michael T Mar 19 '19 at 01:52
  • Well if you are after the exe location of a process that is _currently running_ you can use the `Process` and `ProcessModule` class and check out `MainModule` ; `ProcessModule.FileName`. This approach is **very fast**. https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processmodule?view=netframework-4.7.2. (just change the example to _open existing_ rather than spawn Outlook –  Mar 19 '19 at 02:05
  • This question lacks the basic details of what you are actually trying to do, what the classes you are using are, what questions you have used. I mean this is a guess fest – TheGeneral Mar 19 '19 at 02:09
  • "Find path to a given exe" - I'm not looking for the running process. For a given exe filename I want to find the full path - what is not clear about that? – Michael T Mar 19 '19 at 02:13
  • 2
    @MichaelT But you are showing code that walks through associations and not [through all files](https://stackoverflow.com/a/929418/477420) (or thought [PATH](https://stackoverflow.com/questions/3855956/check-if-an-executable-exists-in-the-windows-path)) - so clearly you are not looking for "any exe to path" mapping but something more specific... What is it? – Alexei Levenkov Mar 19 '19 at 02:22
  • 2
    Look i don't mean to be rude, and i really am just trying to get your question answered. *"Find path to a given exe"* there is no given exe, there is only a string, the wording is questionable to start off with, then you start the question by talking about other posts we we have no idea about, you are using wrapped p/invoked win api methods and we cant see if you are massaging them, you are saying its not working, but you are not telling us the path of the ones its not finding. there is a lot more to this story we cant see... its completely unclear what you are asking – TheGeneral Mar 19 '19 at 02:22
  • Try to update your Question @MichaelT where is your `exe` here? – Vijunav Vastivch Mar 19 '19 at 02:24
  • `AssocQueryStringA` searches for and retrieves a file or protocol association-related string from the registry, not for files. And it has different argument signature. – Max Mar 19 '19 at 02:24
  • To find a file (any, not necessarily an exe) you either shall use `Directory.Enumerate*` methods with recursion, OR, if you want use indexing like Explorer does, then use Windows Search API: https://learn.microsoft.com/en-us/windows/desktop/search/-search-developers-guide-entry-page – Max Mar 19 '19 at 02:29
  • 1
    @AlexeiLevenkov According to this https://learn.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-findexecutablea#remarks it should find the path or am I missing something? – Michael T Mar 19 '19 at 03:12

1 Answers1

1

It seems there are many places to look to find the path to an exe. While the original code above works, it is not an exhaustive search and you also need to look in the registry key SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\ and also check the SpecialFolders Windows, System and SystemX86 (https://learn.microsoft.com/en-us/dotnet/api/system.environment.specialfolder?view=netframework-4.7.2)

Michael T
  • 619
  • 6
  • 19