c# winapi hwnd

c# - ¿Cómo obtengo GetModuleFileName() si solo tengo un identificador de ventana(hWnd)?



winapi (5)

¿Qué es exactamente lo que estás tratando de hacer? Puede obtener la identificación del proceso del proceso que creó una ventana con GetWindowThreadProcessId () , seguido de OpenProcess () para obtener el control del proceso. Pero esto parece muy complicado, y siento que hay una manera más elegante de hacer lo que quieres hacer.

Estoy tratando de obtener el nombre del ejecutable de una ventana que está fuera de mi aplicación C # 2.0. Mi aplicación actualmente obtiene un identificador de ventana (hWnd) usando la llamada GetForegroundWindow () de "user32.dll".

Desde la excavación que he podido hacer, creo que quiero usar la función GetModuleFileNameEx () (de PSAPI) para obtener el nombre, pero GetModuleFileNameEx () requiere un control para un Proceso, no una Ventana.

¿Es posible obtener un identificador de proceso desde un identificador de ventana? (¿Debo obtener primero el manejador de la ventana?)

EDITO la primera oración para aclarar lo que intento hacer.

¡ACTUALIZAR! Aquí está el código de C # que encontré funcionó para mí. La única advertencia es ocasionalmente devuelve un archivo / ruta donde la letra de la unidad es un "?" en lugar de la letra de la unidad real (como "C"). - Aún no entiendo por qué.

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


Puede llamar a GetWindowThreadProcessId y eso le devolverá el proceso asociado a la ventana.

A partir de ahí, puede llamar a OpenProcess para abrir el proceso y obtener el control del proceso.


He estado luchando con el mismo problema durante una hora, ¿también se reemplazó la primera letra por una ? mediante el uso de GetModuleFileNameEx. Finalmente apareció esta solución usando la clase 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; }


Si está ejecutando en una plataforma de Windows de 64 bits, es posible que necesite utilizar QueryFullProcessImageName en su lugar. Esto devuelve una ruta de acceso de estilo de usuario, en comparación con GetProcessImageFileName, que devuelve una ruta de estilo del sistema que debería convertirse mediante NtQuerySymbolicLinkObject o ZwQuerySymbolicLinkObject.

Una función de ejemplo gigantesca: recomendar dividir en bits reutilizables.

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


intente esto para obtener el nombre de archivo del ejecutable:

DO#:

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

mfg