Window Handle (HWND) 만있는 경우 어떻게 GetModuleFileName ()을 얻습니까?
문제
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