Window Handle (HWND) 만있는 경우 어떻게 GetModuleFileName ()을 얻습니까?

StackOverflow https://stackoverflow.com/questions/277085

  •  07-07-2019
  •  | 
  •  

문제

C# 2.0 응용 프로그램 외부에있는 창의 실행 파일의 이름을 얻으려고합니다. 내 앱은 현재 "user32.dll"에서 getforegroundwindow () 호출을 사용하여 창 핸들 (HWND)을 가져옵니다.

내가 할 수 있었던 파기에서, 나는 getModuleFilenameex () 함수 (psapi에서)를 사용하여 이름을 얻고 싶다고 생각하지만 getModuleFilenameex ()는 창이 아닌 프로세스에 대한 핸들이 필요합니다.

창 손잡이에서 프로세스 핸들을 얻을 수 있습니까? (창의 실 손잡이를 먼저 가져와야합니까?)

내가하려는 일을 더 명확하게하기 위해 첫 번째 문장을 편집했습니다.

업데이트! 내가 찾은 C# 코드는 다음과 같습니다. 유일한 경고는입니다 가끔 드라이브 문자가 "?"인 파일/경로를 반환합니다. 실제 드라이브 문자 대신 (예 : "C"). - 아직 이유를 알아 내지 못했습니다.

[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());
}
도움이 되었습니까?

해결책

전화해도됩니다 getWindowthreadProcessId 그리고 그것은 당신에게 창과 관련된 과정을 반환 할 것입니다.

그것으로부터, 당신은 전화 할 수 있습니다 개방 처리 프로세스를 열고 프로세스를 처리합니다.

다른 팁

한 시간 동안 같은 문제로 어려움을 겪고 있었고 첫 번째 편지를 ? getModuleFilenameex를 사용하여. Finaly는이 솔루션을 사용하여 생각해 냈습니다 System.Diagnostics.Process 수업.

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

Windows 64 비트 플랫폼에서 실행중인 경우 대신 QueryFullProcessimagename을 사용해야 할 수도 있습니다. 이것은 ntquerysymboliclinkobject 또는 zwquerysymboliclinkobject를 사용하여 변환 해야하는 시스템 스타일 경로를 반환하는 getProcessImageFilename과 비교하여 사용자 스타일 경로를 반환합니다.

하나의 매머드 예제 기능 - 다시 사용 가능한 비트로 분해하는 것이 좋습니다.

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

정확히 당신이하려고하는 것은 무엇입니까? 창을 만든 프로세스의 프로세스 ID를 얻을 수 있습니다. getwindowthreadprocessid (), 그 뒤에 OpenProcess () 프로세스 손잡이를 얻으려면. 그러나 이것은 매우 Kludgy처럼 보이며, 나는 당신이하고 싶은 일을하는 더 우아한 방법이 있다고 생각합니다.

실행 파일의 파일 이름을 얻으려면 다음을 시도하십시오.

씨#:

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

MFG

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top