c# अगर मुझे केवल विंडो हैंडल(एचडब्ल्यूएनड) है तो मैं GetModuleFileName() कैसे प्राप्त करूं?




winapi hwnd (4)

मैं एक विंडो के निष्पादन योग्य का नाम प्राप्त करने की कोशिश कर रहा हूं जो मेरे सी # 2.0 अनुप्रयोग के बाहर है मेरा ऐप वर्तमान में "user32.dll" से GetForegroundWindow () कॉल का उपयोग करते हुए विंडो हैंडल (एचडब्ल्यूएनडी) प्राप्त करता है

खुदाई से जो मैं कर सकता था, मुझे लगता है कि मुझे नाम प्राप्त करने के लिए GetModuleFileNameEx () फ़ंक्शन (PSAPI से) का उपयोग करना है, लेकिन GetModuleFileNameEx () को एक प्रक्रिया के लिए संभाल की आवश्यकता है, विंडो नहीं।

क्या किसी विंडो के हैंडल से कोई प्रक्रिया संभाल लेना संभव है? (क्या मुझे पहले खिड़की के धागे को संभालने की आवश्यकता है?)

यह स्पष्ट करने के लिए कि मैं क्या करने की कोशिश कर रहा हूं, पहले वाक्य को संपादित किया।

अद्यतन करें! यहाँ सी # कोड है जो मैंने मेरे लिए काम किया है एकमात्र चेतावनी कभी-कभी यह फ़ाइल / पथ देता है जहां ड्राइव अक्षर "?" वास्तविक ड्राइव अक्षर (जैसे "सी") के बजाय - अभी तक क्यों नहीं पता लगा है

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);

[DllImport("psapi.dll")]
static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

private string GetWindowModuleFileName(IntPtr hWnd)
{
    uint processId = 0;
    const int nChars = 1024;
    StringBuilder filename = new StringBuilder(nChars);
    GetWindowThreadProcessId(hWnd, out processId);
    IntPtr hProcess = OpenProcess(1040, 0, processId);
    GetModuleFileNameEx(hProcess,IntPtr.Zero,filename,nChars);
    CloseHandle(hProcess);
    return (filename.ToString());
}

एक घंटे के लिए एक ही समस्या से जूझ रहा है, क्या पहले अक्षर को प्रतिस्थापित किया गया ? GetModuleFileNameEx का उपयोग करके फ़िनली इस समाधान के साथ सिस्टमडायग्नोस्टिक्सप्रोसेस क्लास का उपयोग कर आई थी।

[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

void GetProcessPathFromWindowHandle(IntPtr hwnd)
{
   uint pid = 0;
   Win32.GetWindowThreadProcessId(hwnd, out pid);
   Process p = Process.GetProcessById((int)pid);
   return p.MainModule.FileName;
}

यदि आप एक विंडो 64 बिट प्लेटफॉर्म पर चल रहे हैं, तो आपको इसके बजाय QueryFrocrocessImageName का उपयोग करना पड़ सकता है। यह GetProcessImageFileName की तुलना में एक उपयोगकर्ता शैली पथ देता है, जो कि सिस्टम शैली पथ देता है जिसे NtQuerySymbolicLinkObject या ZwQuerySymbolicLinkObject का उपयोग करके परिवर्तित करना होगा।

एक विशाल उदाहरण फ़ंक्शन - फिर से उपयोग करने योग्य बिट्स को तोड़ने की सलाह देते हैं।

typedef DWORD (__stdcall *PfnQueryFullProcessImageName)(HANDLE hProcess, DWORD dwFlags, LPTSTR lpImageFileName, PDWORD nSize);
typedef DWORD (__stdcall *PfnGetModuleFileNameEx)(HANDLE hProcess, HMODULE hModule, LPTSTR lpImageFileName, DWORD nSize);

std::wstring GetExeName( HWND hWnd ){
// Convert from Window to Process ID
DWORD dwProcessID = 0;
::GetWindowThreadProcessId(hWnd, &dwProcessID);

// Get a handle to the process from the Process ID
HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);

// Get the process name
if (NULL != hProcess) {
    TCHAR szEXEName[MAX_PATH*2] = {L'\0'};
    DWORD nExeName = sizeof(szEXEName)/sizeof(TCHAR);

    //  the QueryFullProcessImageNameW does not exist on W2K
    HINSTANCE hKernal32dll = LoadLibrary(L"kernel32.dll");
    PfnQueryFullProcessImageName pfnQueryFullProcessImageName = NULL;
    if(hKernal32dll != NULL) {
        pfnQueryFullProcessImageName = (PfnQueryFullProcessImageName)GetProcAddress(hKernal32dll, "QueryFullProcessImageNameW");
        if (pfnQueryFullProcessImageName != NULL) 
            pfnQueryFullProcessImageName(hProcess, 0, szEXEName, &nExeName);
        ::FreeLibrary(hKernal32dll);
    } 

    // The following was not working from 32 querying of 64 bit processes
    // Use as backup for when function above is not available 
    if( pfnQueryFullProcessImageName == NULL ){ 
        HINSTANCE hPsapidll = LoadLibrary(L"Psapi.dll");
        PfnGetModuleFileNameEx pfnGetModuleFileNameEx = (PfnGetModuleFileNameEx)GetProcAddress(hPsapidll, "GetModuleFileNameExW");
        if( pfnGetModuleFileNameEx != NULL )    
            pfnGetModuleFileNameEx(hProcess, NULL, szEXEName, sizeof(szEXEName)/sizeof(TCHAR));
        ::FreeLibrary(hPsapidll);
    }

    ::CloseHandle(hProcess);

    return( szEXEName );
} 
return std::wstring();
}

निष्पादन योग्य के फ़ाइल नाम प्राप्त करने के लिए कोशिश करें:

सी#:

string file = System.Windows.Forms.Application.ExecutablePath;

MFG


आप GetWindowThreadProcessId को कॉल कर सकते हैं और इससे आपको विंडो से जुड़े प्रक्रिया वापस आ जाएगी।

उस से, आप प्रक्रिया को खोलने के लिए ओपनप्रक्रिया को कॉल कर सकते हैं और प्रक्रिया को संभाल कर सकते हैं।