Frage

Ich versuche, den Namen der ausführbaren Datei eines Fensters zu erhalten, die außerhalb meiner C # 2.0-Anwendung ist. Meine App zur Zeit bekommt ein Fenster-Handle (hWnd) mit dem GetForegroundWindow () -Aufruf von "user32.dll".

Aus dem Graben, die ich habe in der Lage zu tun, ich glaube, ich will die GetModuleFileNameEx () Funktion verwenden (von PSAPI) den Namen zu erhalten, aber GetModuleFileNameEx () erfordert einen Griff an einen Prozess, kein Fenster.

Ist es möglich, einen Prozess handelt von einem Fenstergriff zu bekommen? (Muss ich zuerst den Faden Handle des Fensters bekommen?)

Den ersten Satz EDITED, um es deutlicher zu machen, was ich zu tun werde versuchen.

UPDATE! Hier ist der C # -Code, die ich für mich gearbeitet gefunden. Die einzige Einschränkung ist gelegentlich es gibt eine Datei / Pfad, in dem die Laufwerksbuchstaben ist ein „?“ anstelle des tatsächlichen Laufwerksbuchstaben (wie „C“). -. Haben Sie nicht, warum noch heraus

[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());
}
War es hilfreich?

Lösung

können Sie rufen GetWindowThreadProcessId und dass kehren Sie den Vorgang mit dem Fenster verbunden ist.

Von diesem können Sie rufen Sie Open den Prozess zu öffnen und nutzen Sie den Griff in den Prozess einzubeziehen.

Andere Tipps

mit dem gleichen Problem für eine Stunde zu kämpfen jetzt, bekam auch den ersten von einem ? ersetzt Brief von GetModuleFileNameEx verwenden. Finaly kam mit dieser Lösung auf mit der System.Diagnostics.Process Klasse.

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

Wenn Sie auf einem Windows-64-Bit-Plattform ausgeführt wird, müssen Sie QueryFullProcessImageName stattdessen verwenden. Dies gibt einen Pfad Benutzer Stil, zu GetProcessImageFileName verglichen, die einen System Stil Pfad zurückgibt, die unter Verwendung von NtQuerySymbolicLinkObject oder ZwQuerySymbolicLinkObject umgewandelt werden müßte.

Ein Mammut-Beispielfunktion -. Empfehlen in wieder verwendbaren Bits Zerschlagung

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

Was genau ist es, dass Sie zu tun versuchen? Sie können die Prozess-ID des Verfahrens erhalten, die ein Fenster mit Open () den Prozess Griff zu bekommen. Aber das scheint sehr kludgy, und ich fühle mich, als gäbe es eine elegantere Möglichkeit zu tun, was Sie tun möchten.

versuchen, diese die Dateinamen der ausführbaren Datei zu erhalten:

C #:

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

mfg

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top