Çalıştırma sürecinin tam yolunu nasıl elde edebilirim?


112

Diğer uygulamanın bazı ayarlarını değiştiren bir uygulamaya sahibim (bu, çift tıklayarak çalışan basit bir C # uygulamasıdır (kurulum gerekmez).

Ayarları değiştirdikten sonra, değiştirilen ayarları yansıtması için diğer uygulamayı yeniden başlatmam gerekiyor.

Yani bunu yapmak için, çalışan süreci durdurmalı ve süreci yeniden başlatmalıyım, Ama sorun öldürdükten sonra süreci bulamıyorum. (Nedeni, sistemin exe dosyasının nerede olduğunu bilmemesidir ..)

Çalışıyorsa, işlem veya exe çalıştırmanın yolunu bulmanın bir yolu var mı?

Manuel olarak yol vermek istemiyorum, yani çalışıyorsa yolu al, işlemi sonlandır ve yeniden başla ... Daha sonra hallederim

Yanıtlar:


157
 using System.Diagnostics;
 var process = Process.GetCurrentProcess(); // Or whatever method you are using
 string fullPath = process.MainModule.FileName;
 //fullPath has the path to exe.

Bu API ile bir yakalama vardır, eğer bu kodu 32 bit uygulamada çalıştırıyorsanız, 64 bit uygulama yollarına erişemezsiniz, bu nedenle uygulamanızı 64 bit uygulama olarak derleyip çalıştırmanız gerekir ( Proje Özellikleri → Yapı → Platform Hedefi → x64).


11
@GAPS: Eminim "süreç örneğinizi alın, ancak buradan alın."
Jeff Mercado

4
Sorun veriyor Erişim on line reddedildi string fullPath = process.Modules[0].FileName;Herhangi bir fikriniz var mı?
Sami

7
Platform Hedefini x64 olarak değiştirmek yerine Platform Hedefini Herhangi biri olarak değiştirdim ve Tercih 32 bit seçeneğinin işaretini kaldırdım
Prat

13
Benim ölçümlere göre, çağrı process.Modules[0]olup 50 kat daha yavaş çağırmaktan daha process.MainModule.
Luca Cremonesi

1
İlk modülün ana modül olduğuna dair herhangi bir garanti var mı?
Sam

112

Yapabilecekleriniz, yolları almak için WMI kullanmaktır. Bu, 32 bit veya 64 bit uygulama olmasına bakılmaksızın yolu almanıza izin verecektir. İşte bunu nasıl elde edebileceğinizi gösteren bir örnek:

// 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
    }
}

System.Management.dllMontajı referans almanız veSystem.Management ad alanını .

Programı başlatmak için kullanılan komut satırı ( CommandLine) gibi bu işlemlerden başka hangi bilgileri alabileceğiniz hakkında daha fazla bilgi için, daha fazla bilgi için Win32_Process sınıfına ve WMI .NET'e bakın.


1
cevabınız harika, ancak mevcut uygulamam küçük ... Bunu aklımda
tutuyorum

3
+1 belki bu soru için aşırı bir durumdur, ancak 32 / 64bit bağımsızlık nedeniyle, çalışan bir 32bit işlemden 64 bit işlem bilgisi almak istediğimde bu yöntem gerçekten kullanışlı oldu .
Mike Fuchs

1
Kabul edilen Cevaptan farklı olarak, bu aynı zamanda Terminal Sunucusu Ortamlarında da çalışır. İyi iş, bana çok yardımcı oldu!
MC

1
O Not Pathözelliği ayarlanır mo["ExecutablePath"]olan nullbazı süreçler için.
Sam

2
Visual Studio'nun eksik referanslardan şikayet etmesi durumunda Process.GetProcesses()ve results.Cast<>ayrıca using System.Linqyönergeyi eklemeniz gerekir .
kibitzerCZ

26

Sanırım çalışan sürecin işlem nesnesine zaten sahipsiniz (örn. GetProcessesByName () ile). Daha sonra çalıştırılabilir dosya adını kullanarak

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

2
kullanılmıyorsa: var p = Process.GetCurrentProcess (); string filename = p.MainModule.FileName;
Andreas

3
"32 bitlik işlemler 64 bitlik bir işlemin modüllerine erişemez." sınırlama ne yazık ki burada da.
Roland Pihlakas

19

Aşağıdakiler için bir çözüm:

  • Hem 32 bit hem de 64 bit işlemler
  • Yalnızca System.Diagnostics (System.Management yok)

Ben kullanılan Russell Gantman gelen çözüm ve böyle kullanabileceğiniz bir uzatma yöntemi olarak yeniden yazıldı:

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

Bu uygulama ile:

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;
    }
}

1
QueryFullProcessImageName BOOL döndürür. 0. pinvoke.net/default.aspx/kernel32.QueryFullProcessImageName
vik_78

8

Sanjeevakumar Hiremath'ın ve Jeff Mercado'nun yanıtlarını birleştirerek, 32 bitlik bir işlemde 64 bitlik bir işlemden simgeyi alırken aslında bir şekilde sorunu aşabilirsiniz.

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 "";
        }
    }
}

Bu biraz yavaş olabilir ve "geçerli" simgesi olmayan her işlemde çalışmaz.


Bu kullanım biraz iyileştirilebilir string query = "SELECT ExecutablePath, ProcessID FROM Win32_Process WHERE ProcessID = " + process.Id;... ancak bu yöntem hala oldukça yavaştır, tüm sonuçları almak ve bunları 'önbelleğe almak', eğer 1'den fazla sürecin yolunu elde ediyorsanız en iyi hız iyileştirmesi olacaktır
Thymine

8

Burada hem çalışır güvenilir bir çözümdür 32bit ve 64bit uygulamaları.

Bu referansları ekleyin:

System.Diagnostics kullanarak;

System.Management kullanarak;

Bu yöntemi projenize ekleyin:

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;
}

Şimdi bunu şu şekilde kullanın:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

İşlemin kimliğini biliyorsanız, bu yöntemin karşılık gelen ExecutePath'i döndüreceğine dikkat edin.

Ekstra, ilgilenenler için:

Process.GetProcesses() 

... size şu anda çalışan tüm işlemlerin bir dizisini verecektir ve ...

Process.GetCurrentProcess()

... size mevcut işlemle birlikte bilgileri, örneğin Kimlik vb. ve ayrıca sınırlı kontrol, örn. Öldür vb.


5

PInvoke ve aşağıdaki gibi yerel bir çağrıyı kullanabilirsiniz. Bunun 32/64 bit sınırlaması yok gibi görünüyor (en azından benim testlerimde)

İşte kod

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;
    }

1

Deneyin:

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.");
}

0
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 );  
}

@GAPS: Bu (şu anda çalıştıran) vardır Montaj yürütülmesi içindir
Sonal Satpute

Vaov! Teşekkürler! Şimdiye kadarki en iyi çözüm, çünkü FreeBSD'de bile çalışıyor.
biv

0
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();
    }

}

0

Diğerleri için, aynı yürütülebilir dosyadan başka bir işlem bulmak istiyorsanız, şunları kullanabilirsiniz:

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;
}


-3

Yürütülen bir işlemin geçerli dizinini ararken bu iş parçacığına ulaştım. .Net 1.1'de Microsoft şunları tanıttı:

Directory.GetCurrentDirectory();

İyi çalışıyor gibi görünüyor (ancak işlemin adını döndürmüyor).


Bu, yalnızca bazı durumlarda yürütülebilir dosyanın bulunduğu dizini döndürür. Örneğin, bir komut satırı açabilir, herhangi bir rastgele dizine geçebilir ve tam yolunu belirleyerek yürütülebilir dosyayı çalıştırabilirsiniz; GetCurrentDirectory () çalıştırılabilir dizini yerine çalıştırdığınız dizini döndürür. Gönderen linke : "Mevcut dizin işlemi başlatıldığı biridir orijinal dizin ayrıdır."
Dave Ruske
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.