চলমান প্রক্রিয়াটির পুরো পথ কীভাবে পাবেন?


112

আমার কাছে এমন একটি অ্যাপ্লিকেশন রয়েছে যা অন্যান্য অ্যাপ্লিকেশনের কিছু সেটিংস পরিবর্তন করছে (এটি একটি সাধারণ সি # অ্যাপ্লিকেশন যা ডাবল ক্লিক করে চলমান (কোনও সেটআপের প্রয়োজন নেই))।

সেটিংস পরিবর্তন করার পরে আমাকে অন্য অ্যাপ্লিকেশনটি পুনরায় চালু করতে হবে যাতে এটি পরিবর্তিত সেটিংস প্রতিফলিত করে।

কাজটি করার জন্য, আমাকে চলমান প্রক্রিয়াটি মেরে আবার প্রক্রিয়া শুরু করতে হবে, তবে সমস্যা হত্যার পরে আমি প্রক্রিয়াটি খুঁজে পাচ্ছি না। (কারণ সিস্টেমটি জানেন না যে এক্সিল ফাইলটি কোথায় ..)

চলমান প্রক্রিয়া বা এক্সিটির পথটি খুঁজে পাওয়ার কোনও উপায় আছে, যদি এটি চলছে?

আমি ম্যানুয়ালি পাথ দিতে চাই না, অর্থাত্ যদি এটি চলতে থাকে তবে পাথটি পাওয়া, প্রসেসটি মেরে আবার শুরু করুন .... আমি পরে পরিচালনা করব

উত্তর:


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-বিট অ্যাপ্লিকেশন হিসাবে সংকলন করে চালাতে হবে ( প্রকল্পের সম্পত্তি → বিল্ড → প্ল্যাটফর্ম লক্ষ্য get x64)।


11
@ জিএপিএস: আমি নিশ্চিত যে তার অর্থ, "আপনার প্রক্রিয়া উদাহরণটি পাবেন তবে আপনি এটি এখানে পেয়েছেন।"
— জেফ মার্কাডো

4
এটি সমস্যা দেয় লাইনে অ্যাক্সেস অস্বীকার করা হয়েছে string fullPath = process.Modules[0].FileName;কোনও ধারণা দয়া করে?
— সামি

7
প্ল্যাটফর্ম টার্গেটটি x64 এ পরিবর্তনের পরিবর্তে, আমি প্ল্যাটফর্মের লক্ষ্যটিকে যে কোনওটিতে পরিবর্তন করেছি এবং 32 টি বিট বিকল্পটি পছন্দ করে না ফেলেছি
— প্রট

13
আমার পরিমাপ অনুসারে, কল process.Modules[0]করা কল করার চেয়ে 50 গুণ ধীরprocess.MainModule ।
— লুকা ক্রেমোনসি

1
প্রথম মডিউলটিই মূল মডিউল যে কোনও গ্যারান্টি আছে?
— স্যাম

112

আপনি যা করতে পারেন তা হ'ল পথগুলি পাওয়ার জন্য ডাব্লুএমআই ব্যবহার করুন। এটি আপনাকে 32-বিট বা 64-বিট অ্যাপ্লিকেশন নির্বিশেষে পাথ পেতে দেয় to আপনি এটি কীভাবে পেতে পারেন তা প্রদর্শনের জন্য এখানে একটি উদাহরণ রয়েছে:

// 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পারেন সে সম্পর্কে আরও তথ্যের জন্য, আরও তথ্যের জন্য উইন 32_প্রসেস ক্লাস এবং ডাব্লুএমআই। নেট দেখুন।


1
আপনার উত্তর সন্ত্রস্ত, কিন্তু আমার সময় বর্তমান অ্যাপ্লিকেশান ছোট এক ... আমি এই কথাটি মনে রাখবেন
— PawanS

3
+1 টি এই প্রশ্নের জন্য সম্ভবত এটি একটি Overkill, কিন্তু 32 / 64bit স্বাধীনতা কারণে এই পদ্ধতি সত্যিই উপকারে আসে যখন আমি পেতে চেয়েছিলেন একটি চলমান 32bit প্রক্রিয়া থেকে 64bit প্রক্রিয়ার তথ্য ।
— মাইক ফুচস

1
গৃহীত উত্তরের বিপরীতে, এটি টার্মিনাল সার্ভার এনভায়রোমেন্টগুলিতেও কাজ করে। ভাল কাজ, আমাকে অনেক সাহায্য!
— এমসি

1
লক্ষ্য করুন Pathসম্পত্তি থেকে সেট mo["ExecutablePath"]করা হয় nullকিছু প্রসেসের জন্য।
— স্যাম

2
যদি ভিজ্যুয়াল স্টুডিওতে রেফারেন্সগুলি হারিয়ে যাওয়ার বিষয়ে অভিযোগ করে Process.GetProcesses()এবং results.Cast<>আপনার using System.Linqনির্দেশিকাও যুক্ত করা দরকার ।
— কিবিৎজার সিজেড

26

আমি অনুমান করি আপনার ইতিমধ্যে চলমান প্রক্রিয়াটির প্রক্রিয়া অবজেক্টটি রয়েছে (যেমন গেটপ্রসেসসাইওয়াইনেম () দ্বারা)। তারপরে আপনি ব্যবহার করে সম্পাদনযোগ্য ফাইলের নাম পেতে পারেন

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

2
যদি ব্যবহার না করা হয়: var p = প্রক্রিয়া.গেটকন্ট্রন্টপ্রসেস (); স্ট্রিং ফাইলের নাম = p.MainModule.FileName;
— Andreas

3
"একটি 32 বিট প্রক্রিয়া 64 বিট প্রক্রিয়াটির মডিউলগুলিতে অ্যাক্সেস করতে পারে না।" দুর্ভাগ্যক্রমে এখানেও সীমাবদ্ধতা রয়েছে।
— রোল্যান্ড পিহলাকাস

18

এর জন্য একটি সমাধান:

  • 32-বিট এবং 64-বিট উভয় প্রক্রিয়া
  • কেবলমাত্র সিস্টেম.এর ডায়াগনস্টিক্স (কোনও সিস্টেম। পরিচালন নেই)

আমি রাসেল গ্যান্টম্যানের কাছ থেকে সমাধানটি ব্যবহার করেছি এবং আপনি এটির মতো ব্যবহার করতে পারেন এমন এক্সটেনশন পদ্ধতি হিসাবে এটি পুনরায় লিখেছিলেন:

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
কোয়েরিফুলপ্রসেসআইজেজনেম 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 "";
        }
    }
}

এটি কিছুটা ধীর হতে পারে এবং প্রতিটি প্রক্রিয়াতে কাজ করে না যার "বৈধ" আইকন নেই cks


এর সাহায্যে এই ব্যবহারটি কিছুটা উন্নত হতে পারে string query = "SELECT ExecutablePath, ProcessID FROM Win32_Process WHERE ProcessID = " + process.Id;... তবে এই পদ্ধতিটি এখনও বেশ ধীরে, সমস্ত ফলাফল পেয়ে এবং 'ক্যাশে' করা সেরা গতির উন্নতি হবে, যদি আপনি 1 টিরও বেশি প্রক্রিয়ার পথ অর্জন করেন
— থাইমাইন

8

এখানে একটি নির্ভরযোগ্য সমাধান যা 32 বিট এবং 64 বিট অ্যাপ্লিকেশন উভয়ের সাথেই কাজ করে ।

এই উল্লেখগুলি যুক্ত করুন:

System.Diagnostics ব্যবহার করে;

System.Management ব্যবহার করে;

আপনার প্রকল্পে এই পদ্ধতিটি যুক্ত করুন:

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

লক্ষ করুন যে আপনি যদি প্রক্রিয়াটির আইডি জানেন তবে এই পদ্ধতিটি সংশ্লিষ্ট এক্সিকিউটপথটি ফিরিয়ে দেবে।

অতিরিক্ত, আগ্রহীদের জন্য:

Process.GetProcesses() 

... আপনাকে বর্তমানে চলমান সমস্ত প্রক্রিয়াগুলির একটি অ্যারে দেবে এবং ...

Process.GetCurrentProcess()

... তাদের বর্তমান তথ্য যেমন আইডি ইত্যাদি এবং আপনার সীমাবদ্ধ নিয়ন্ত্রণ যেমন কিল, ইত্যাদি প্রদান করবে you


4

আপনি নীচের মতো পিনভোক এবং একটি নেটিভ কল ব্যবহার করতে পারেন। এটি 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 );  
}

@ জিএপিএস: এটি কার্যনির্বাহী সমাবেশের জন্য (যা বর্তমানে চলছে)
— সোনাল সাতপুট

কি দারুন! ধন্যবাদ! সর্বকালের সেরা সমাধান, কারণ এমনকি ফ্রিবিএসডি-তেও কাজ করে।
— 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
যথাযথভাবে। এটি "এই প্রক্রিয়াটি কীভাবে শুরু হয়েছিল" তার চেয়ে "প্রক্রিয়াটি কীভাবে শুরু করবেন" rather
— রবার্ট সিনোরাদজকি

-3

একটি নির্বাহী প্রক্রিয়ার বর্তমান ডিরেক্টরি অনুসন্ধান করার সময় আমি এই থ্রেডে পৌঁছেছি। .NET 1.1 মাইক্রোসফ্ট চালু করেছে:

Directory.GetCurrentDirectory();

ভাল কাজ করার মতো মনে হচ্ছে (তবে প্রক্রিয়াটির নামটি নিজেই ফেরায় না)।


এটি কেবলমাত্র কিছু পরিস্থিতিতে এক্সিকিউটেবলের মধ্যে অবস্থিত ডিরেক্টরিটি ফিরিয়ে দেবে। উদাহরণস্বরূপ, আপনি একটি কমান্ড লাইন খুলতে পারেন, যে কোনও র্যান্ডম ডিরেক্টরিতে পরিবর্তন করতে পারেন এবং এটির জন্য একটি পুরো পথ নির্দিষ্ট করে এক্সিকিউটেবল চালাতে পারেন; গেটক্র্যান্ট ডিরেক্টরী () এক্সিকিউটেবলের ডিরেক্টরি না করে আপনি যে ডিরেক্টরিটি সম্পাদন করেছেন তা ফিরিয়ে দেবে। লিঙ্ক থেকে : "বর্তমান ডিরেক্টরিটি মূল ডিরেক্টরি থেকে পৃথক, যা প্রক্রিয়াটি শুরু হয়েছিল সেখান থেকেই এটি একটি।"
— ডেভ রুস্কে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.