Как мне GetModuleFileName (), если у меня есть только дескриптор окна (hWnd)?
Я пытаюсь получить имя исполняемого файла окна, которое находится вне моего приложения C# 2.0. В настоящее время мое приложение получает дескриптор окна (hWnd) с помощью вызова GetForegroundWindow() из "user32.файл DLL."
из копания, которое я смог сделать, я думаю, что хочу использовать функцию 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());
}
5 ответов
можно назвать GetWindowThreadProcessId и это вернет вам процесс, связанный с окном.
из этого вы можете назвать для открытия процесса открыть процесс и получить дескриптор процесса.
боролся с той же проблемой в течение часа, также получил первую букву, замененную ? С помощью GetModuleFileNameEx. Finaly придумал это решение, используя
Если вы работаете на 64-разрядной платформе windows, может потребоваться использовать QueryFullProcessImageName вместо. Это возвращает путь пользовательского стиля по сравнению с 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''};
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();
}
Что именно вы пытаетесь сделать? Вы можете получить идентификатор процесса процесса, который создал окно с GetWindowThreadProcessId (), следовал по OpenProcess () чтобы получить дескриптор процесса. Но это кажется очень сложным, и я чувствую, что есть более элегантный способ сделать то, что вы хотите сделать.
попробуйте это, чтобы получить имя исполняемого файла :
C#:
string file = System.Windows.Forms.Application.ExecutablePath;
mfg