[c#] How to get the full path of running process?

I am having an application that is changing some settings of another application (it is a simple C# application that run by double clicking (no setup required)).

After changing the settings I need to restart the other application so that it reflects the changed settings.

So to do, I have to kill the running process and start the process again, But the problem is after killing I am not able to find the process. (Reason is system do not know where the exe file is..)

Is there any way to find out the path of running process or exe, if it is running?

I do not want to give path manually, i.e. if it is running get the path, kill the process and start again else .... I will handle later

This question is related to c#

The answer is


By combining Sanjeevakumar Hiremath's and Jeff Mercado's answers you can actually in a way get around the problem when retrieving the icon from a 64-bit process in a 32-bit process.

using System;
using System.Management;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int processID = 6680;   // Change for the process you would like to use
            Process process = Process.GetProcessById(processID);
            string path = ProcessExecutablePath(process);
        }

        static private string ProcessExecutablePath(Process process)
        {
            try
            {
                return process.MainModule.FileName;
            }
            catch
            {
                string query = "SELECT ExecutablePath, ProcessID FROM Win32_Process";
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

                foreach (ManagementObject item in searcher.Get())
                {
                    object id = item["ProcessID"];
                    object path = item["ExecutablePath"];

                    if (path != null && id.ToString() == process.Id.ToString())
                    {
                        return path.ToString();
                    }
                }
            }

            return "";
        }
    }
}

This may be a bit slow and doesn't work on every process which lacks a "valid" icon.


I got to this thread while looking for the current directory of an executing process. In .net 1.1 Microsoft introduced:

Directory.GetCurrentDirectory();

Seems to work well (but doesn't return the name of the process itself).


For others, if you want to find another process of the same executable, you can use:

public bool tryFindAnotherInstance(out Process process) {
    Process thisProcess = Process.GetCurrentProcess();
    string thisFilename = thisProcess.MainModule.FileName;
    int thisPId = thisProcess.Id;
    foreach (Process p in Process.GetProcesses())
    {
        try
        {
            if (p.MainModule.FileName == thisFilename && thisPId != p.Id)
            {
                process = p;
                return true;
            }
        }
        catch (Exception)
        {

        }
    }
    process = default;
    return false;
}

private void Test_Click(object sender, System.EventArgs e){
   string path;
   path = System.IO.Path.GetDirectoryName( 
      System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
    Console.WriiteLine( path );  
}

What you can do is use WMI to get the paths. This will allow you to get the path regardless it's a 32-bit or 64-bit application. Here's an example demonstrating how you can get it:

// include the namespace
using System.Management;

var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process";
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
using (var results = searcher.Get())
{
    var query = from p in Process.GetProcesses()
                join mo in results.Cast<ManagementObject>()
                on p.Id equals (int)(uint)mo["ProcessId"]
                select new
                {
                    Process = p,
                    Path = (string)mo["ExecutablePath"],
                    CommandLine = (string)mo["CommandLine"],
                };
    foreach (var item in query)
    {
        // Do what you want with the Process, Path, and CommandLine
    }
}

Note that you'll have to reference the System.Management.dll assembly and use the System.Management namespace.

For more info on what other information you can grab out of these processes such as the command line used to start the program (CommandLine), see the Win32_Process class and WMI .NET for for more information.


using System;
using System.Diagnostics;

class Program
{
    public static void printAllprocesses()
    {
        Process[] processlist = Process.GetProcesses();

        foreach (Process process in processlist)
        {
            try
            {
                String fileName = process.MainModule.FileName;
                String processName = process.ProcessName;

                Console.WriteLine("processName : {0},  fileName : {1}", processName, fileName);
            }catch(Exception e)
            {
                /* You will get access denied exception for system processes, We are skiping the system processes here */
            }

        }
    }

    static void Main()
    {
        printAllprocesses();
    }

}

Try:

using System.Diagnostics;

ProcessModuleCollection modules = Process.GetCurrentProcess().Modules;
string processpathfilename;
string processmodulename;
if (modules.Count > 0) {
    processpathfilename = modules[0].FileName;
    processmodulename= modules[0].ModuleName;
} else {
    throw new ExecutionEngineException("Something critical occurred with the running process.");
}

You can use pInvoke and a native call such as the following. This doesn't seem to have the 32 / 64 bit limitation (at least in my testing)

Here is the code

using System.Runtime.InteropServices;

    [DllImport("Kernel32.dll")]
    static extern uint QueryFullProcessImageName(IntPtr hProcess, uint flags, StringBuilder text, out uint size);

    //Get the path to a process
    //proc = the process desired
    private string GetPathToApp (Process proc)
    {
        string pathToExe = string.Empty;

        if (null != proc)
        {
            uint nChars = 256;
            StringBuilder Buff = new StringBuilder((int)nChars);

            uint success = QueryFullProcessImageName(proc.Handle, 0, Buff, out nChars);

            if (0 != success)
            {
                pathToExe = Buff.ToString();
            }
            else
            {
                int error = Marshal.GetLastWin32Error();
                pathToExe = ("Error = " + error + " when calling GetProcessImageFileName");
            }
        }

        return pathToExe;
    }

The Process class has a member StartInfo that you should check out:


A solution for:

  • Both 32-bit AND 64-bit processes
  • System.Diagnostics only (no System.Management)

I used the solution from Russell Gantman and rewritten it as an extension method you can use like this:

var process = Process.GetProcessesByName("explorer").First();
string path = process.GetMainModuleFileName();
// C:\Windows\explorer.exe

With this implementation:

internal static class Extensions {
    [DllImport("Kernel32.dll")]
    private static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] uint dwFlags, [Out] StringBuilder lpExeName, [In, Out] ref uint lpdwSize);

    public static string GetMainModuleFileName(this Process process, int buffer = 1024) {
        var fileNameBuilder = new StringBuilder(buffer);
        uint bufferLength = (uint)fileNameBuilder.Capacity + 1;
        return QueryFullProcessImageName(process.Handle, 0, fileNameBuilder, ref bufferLength) ?
            fileNameBuilder.ToString() :
            null;
    }
}

Here is a reliable solution that works with both 32bit and 64bit applications.

Add these references:

using System.Diagnostics;

using System.Management;

Add this method to your project:

public static string GetProcessPath(int processId)
{
    string MethodResult = "";
    try
    {
        string Query = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;

        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(Query))
        {
            using (ManagementObjectCollection moc = mos.Get())
            {
                string ExecutablePath = (from mo in moc.Cast<ManagementObject>() select mo["ExecutablePath"]).First().ToString();

                MethodResult = ExecutablePath;

            }

        }

    }
    catch //(Exception ex)
    {
        //ex.HandleException();
    }
    return MethodResult;
}

Now use it like so:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

Notice that if you know the id of the process, then this method will return the corresponding ExecutePath.

Extra, for those interested:

Process.GetProcesses() 

...will give you an array of all the currently running processes, and...

Process.GetCurrentProcess()

...will give you the current process, along with their information e.g. Id, etc. and also limited control e.g. Kill, etc.*


I guess you already have the process object of the running process (e.g. by GetProcessesByName()). You can then get the executable file name by using

Process p;
string filename = p.MainModule.FileName;