दौड़ने की प्रक्रिया का पूरा रास्ता कैसे प्राप्त करें?


112

मेरे पास एक एप्लिकेशन है जो अन्य एप्लिकेशन की कुछ सेटिंग्स बदल रहा है (यह एक साधारण सी # एप्लिकेशन है जो डबल क्लिक करके चलाया जाता है (कोई सेटअप आवश्यक नहीं है))।

सेटिंग्स बदलने के बाद मुझे दूसरे एप्लिकेशन को पुनरारंभ करने की आवश्यकता है ताकि यह परिवर्तित सेटिंग्स को प्रतिबिंबित करे।

इसलिए करने के लिए, मुझे दौड़ने की प्रक्रिया को मारना होगा और प्रक्रिया को फिर से शुरू करना होगा, लेकिन समस्या यह है कि मारने के बाद मैं इस प्रक्रिया को खोजने में सक्षम नहीं हूं। (कारण प्रणाली पता नहीं है कि exe फ़ाइल कहाँ है ..)

क्या रनिंग प्रोसेस या एक्सई का रास्ता पता करने का कोई तरीका है, अगर वह चल रहा है?

मैं मैन्युअल रूप से पथ देना नहीं चाहता, अर्थात यदि यह रास्ता मिल रहा है, तो असफल को मारें और फिर से शुरू करें .... मैं बाद में संभालूंगा

जवाबों:


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.

इस एपीआई के साथ एक पकड़ है, यदि आप 32 बिट एप्लिकेशन में इस कोड को चला रहे हैं, तो आप 64-बिट एप्लिकेशन पथ तक नहीं पहुंच पाएंगे, इसलिए आपको 64-बिट एप्लिकेशन के रूप में ऐप को संकलित और चलाना होगा ( प्रोजेक्ट गुण → बिल्ड → प्लेटफ़ॉर्म लक्ष्य → x64)।


11
@GAPS: मुझे यकीन है कि उनका मतलब है, "अपनी प्रक्रिया का उदाहरण प्राप्त करें, हालांकि आप इसे यहाँ प्राप्त करते हैं।"
जेफ मर्काडो

4
यह समस्या देता है प्रवेश लाइन पर अस्वीकार कर दिया गया है string fullPath = process.Modules[0].FileName;कोई विचार कृपया?
सामी

7
प्लेटफ़ॉर्म लक्ष्य को x64 में बदलने के बजाय, मैंने प्लेटफ़ॉर्म लक्ष्य को किसी में भी बदल दिया और Prefer 32 बिट विकल्प को अनचेक किया
Prat

13
मेरे माप के अनुसार, बुला process.Modules[0]है 50 बार धीमी बुला से process.MainModule
लूका क्रेमोनी

1
क्या कोई गारंटी है कि पहला मॉड्यूल मुख्य मॉड्यूल है?
सैम

112

पथ प्राप्त करने के लिए आप WMI का उपयोग कर सकते हैं। यह आपको 32-बिट या 64-बिट एप्लिकेशन की परवाह किए बिना पथ प्राप्त करने की अनुमति देगा। यहाँ एक उदाहरण दिखाया गया है कि आप इसे कैसे प्राप्त कर सकते हैं:

// 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.dllविधानसभा का संदर्भ देना होगा और System.Managementनाम स्थान का उपयोग करना होगा ।

अधिक जानकारी के लिए आप इन प्रक्रियाओं से बाहर क्या कर सकते हैं जैसे कि प्रोग्राम शुरू करने के लिए उपयोग की जाने वाली कमांड लाइन ( CommandLine), अधिक जानकारी के लिए Win32_Process वर्ग और WMI .NET देखें।


1
आपका उत्तर भयानक है, लेकिन मेरा वर्तमान ऐप छोटा है ... मैं इसे ध्यान में रखता हूं
पवन

3
+1 शायद इस सवाल के लिए यह एक ओवरकिल है, लेकिन 32/64 बिट इंडिपेंडेंस के कारण, यह विधि वास्तव में बहुत आसान थी जब मैं एक रनिंग 32 बिट प्रक्रिया से 64 बिट की प्रक्रिया की जानकारी प्राप्त करना चाहता था ।
माइक फुच्स

1
स्वीकृत उत्तर के विपरीत, यह टर्मिनल सर्वर एनवायरमेंट में भी काम करता है। अच्छी नौकरी, मेरी बहुत मदद की!
एमसी

1
ध्यान दें कि Pathसंपत्ति से सेट mo["ExecutablePath"]है nullकुछ प्रक्रियाओं के लिए।
सैम

2
यदि दृश्य स्टूडियो गुम संदर्भों के बारे में शिकायत करता है Process.GetProcesses()और results.Cast<>आपको using System.Linqनिर्देश भी जोड़ने की आवश्यकता है ।
kibitzerCZ

26

मुझे लगता है कि आपके पास पहले से ही चल रही प्रक्रिया का ऑब्जेक्ट है (जैसे GetProcessesByName () द्वारा)। तब आप उपयोग करके निष्पादन योग्य फ़ाइल नाम प्राप्त कर सकते हैं

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

2
यदि उपयोग नहीं किया जाता है: var p = Process.GetCurrentProcess (); string filename = p.MainModule.FileName;
एंड्रियास

3
"एक 32 बिट प्रक्रिया 64 बिट प्रक्रिया के मॉड्यूल का उपयोग नहीं कर सकती है।" मर्यादा दुर्भाग्य से यहां भी है।
रोलैंड पिहलकास

18

इसके लिए एक समाधान:

  • दोनों 32-बिट और 64-बिट प्रक्रिया
  • System.Diagnostics केवल (कोई System। प्रबंधन)

मैंने रसेल गैन्टमैन से समाधान का उपयोग किया और इसे एक विस्तार विधि के रूप में फिर से लिखा जिसे आप इस तरह से उपयोग कर सकते हैं:

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

इस कार्यान्वयन के साथ:

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 देता है। हम 0. से इसकी तुलना की जरूरत नहीं है pinvoke.net/default.aspx/kernel32.QueryFullProcessImageName
vik_78

8

संजीवकुमार हिरेमथ और जेफ मर्काडो के उत्तरों के संयोजन से आप 32-बिट प्रक्रिया में 64-बिट प्रक्रिया से आइकन को पुनः प्राप्त करते समय वास्तव में समस्या के आसपास पहुंच सकते हैं।

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

यह थोड़ा धीमा हो सकता है और हर प्रक्रिया पर काम नहीं करता है जिसमें "वैध" आइकन का अभाव है।


इस उपयोग के साथ थोड़ा सुधार किया जा सकता है string query = "SELECT ExecutablePath, ProcessID FROM Win32_Process WHERE ProcessID = " + process.Id;... लेकिन यह विधि अभी भी काफी धीमी है, सभी परिणाम प्राप्त करना और उन्हें 'कैशिंग' करना सबसे अच्छा गति सुधार होगा, यदि आपको 1 से अधिक प्रक्रिया का मार्ग मिल रहा है
थाइमिन

8

यहां एक विश्वसनीय समाधान है जो 32 बिट और 64 बिट दोनों अनुप्रयोगों के साथ काम करता है ।

इन संदर्भों को जोड़ें:

System.Diagnostics का उपयोग करना;

सिस्टम का उपयोग कर रहा है।

इस विधि को अपनी परियोजना में जोड़ें:

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

अब इसे ऐसे उपयोग करें:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

ध्यान दें कि यदि आप प्रक्रिया की आईडी जानते हैं, तो यह विधि संबंधित ExecutePath को वापस कर देगी।

अतिरिक्त, रुचि रखने वालों के लिए:

Process.GetProcesses() 

... आप वर्तमान में चल रही सभी प्रक्रियाओं की एक सरणी दे देंगे, और ...

Process.GetCurrentProcess()

... आपको वर्तमान प्रक्रिया, उनकी जानकारी जैसे Id, इत्यादि दे देंगे और सीमित नियंत्रण जैसे कि Kill, आदि * भी दे देंगे।


4

आप निम्नलिखित जैसे pInvoke और एक देशी कॉल का उपयोग कर सकते हैं। ऐसा लगता नहीं है कि 32/64 बिट सीमा (कम से कम मेरे परीक्षण में)

यहाँ कोड है

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

प्रयत्न:

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

@ जीएपीएस: यह एक्सक्लूसिव असेंबली (जो वर्तमान में चल रही है) के लिए है
सोनल सतपुते

वाह! धन्यवाद! सबसे अच्छा समाधान कभी, क्योंकि FreeBSD पर भी काम करता है।
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

दूसरों के लिए, यदि आप एक ही निष्पादन योग्य की दूसरी प्रक्रिया खोजना चाहते हैं, तो आप इसका उपयोग कर सकते हैं:

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

Processवर्ग एक सदस्य है StartInfoकि आप बाहर की जाँच करनी चाहिए:


3
यह केवल उन स्थानीय प्रक्रियाओं पर लागू होता है जो Process.Start()मौजूदा प्रक्रियाओं का उपयोग करते हुए शुरू की गई थीं , न कि इसका उपयोग ।
जेफ मर्काडो

1
बिल्कुल सही। यह "प्रक्रिया कैसे शुरू करें" के बजाय "यह प्रक्रिया कैसे शुरू हुई"।
रॉबर्ट सिनोरडज़की

-3

एक निष्पादन प्रक्रिया की वर्तमान निर्देशिका की तलाश करते हुए मुझे यह धागा मिला। में .net 1.1 Microsoft ने पेश किया:

Directory.GetCurrentDirectory();

अच्छी तरह से काम करने लगता है (लेकिन प्रक्रिया का नाम वापस नहीं करता है)।


यह केवल उस निर्देशिका को वापस करेगा जो निष्पादन योग्य कुछ परिस्थितियों में स्थित है। उदाहरण के लिए, आप कमांड लाइन खोल सकते हैं, किसी भी यादृच्छिक निर्देशिका को बदल सकते हैं, और इसे पूरा रास्ता निर्दिष्ट करके निष्पादन योग्य चला सकते हैं; GetCurrentDirectory () निष्पादन योग्य निर्देशिका के बजाय आपके द्वारा निष्पादित निर्देशिका को वापस लौटा देगा। से लिंक : "वर्तमान निर्देशिका मूल निर्देशिका है, जो एक है जहाँ से प्रक्रिया शुरू किया गया था है से अलग है।"
डेव रस्के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.