Как я могу получить путь к DOS запущенного процесса в C # / Win32? - PullRequest
0 голосов
/ 09 сентября 2010

Чтобы подвести итог, мне нужно сделать следующее:

12345 (hWnd) -> "C: \ setup.exe"

Сейчас я использую GetProcessImageFileName, чтобы получить путь к устройству ядра дескриптора процесса.Я извлекаю дескриптор, используя OpenProcess, передавая ему PID.PID (который мне также нужен) извлекается с помощью GetWindowThreadProcessId.

Однако это приводит меня к строке типа:

\ Device \Harddisk1 \ setup.exe

На этом этапе я перечисляю все диски в системе, используя DriveInfo.GetDrives(), а затем вызываю QueryDosDevice.Наконец, я могу сделать магию манипуляции со строками, и " boom ", у меня есть свой путь.


Хорошо, мои проблемы:
  1. Этот процесс не работает на сетевых дисках.
  2. Все, что мне действительно нужно, это QueryFullProcessImageName на XP

Должен быть лучший способ сделать это.Пожалуйста, просветите меня, о боги WIN32API!

Ответы [ 2 ]

2 голосов
/ 09 сентября 2010

Очевидный вопрос заключается в том, почему вы не просто используете QueryFullProcessImageName, если вы этого хотите?Вам нужна совместимость с более старыми версиями Windows?

Ближайшим эквивалентом QueryFullProcessImageName, доступным в XP, является, вероятно, GetModuleFileNameEx.Я бы, вероятно, обнаружил, доступен ли QueryFullProcessImageName, и использовал бы его, если это возможно, в противном случае вернитесь к GetModuleFileNameEx.

Редактировать: Хотя GetModuleFileNameEx не на 100% надежен при получении имени исполняемого файладля каждого возможного процесса он работает, по крайней мере, довольно существенную часть времени.Вот небольшой фрагмент тестового кода, который я собрал:

#include <windows.h>
#include <psapi.h>
#include <iterator>
#include <iostream>
#include <string>
#include <map>

std::string getfilename(DWORD pid) { 
    HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
    static int winver;
    char path[256]= {0};
    DWORD size = sizeof(path);

    if (winver==0) 
        winver = GetVersion() & 0xf; 

#if WINVER >= 0x600
    if (winver >= 6)    
        QueryFullProcessImageName(process, 0, path, &size);
    else
#endif
    if (!GetModuleFileNameEx(process, NULL, path, sizeof(path)))
        strcpy(path, "Unknown");
    return std::string(path);
}

typedef std::map<DWORD, std::string> win_map;

namespace std { 
    ostream &operator<<(ostream &os, win_map::value_type const &v) { 
        return os << v.first << ": " << v.second;
    }
}

BOOL CALLBACK show_info(HWND window, LPARAM lParam) {
    win_map &exes = *(win_map *)lParam;

    DWORD pid;
    GetWindowThreadProcessId(window, &pid);
    exes[pid] = getfilename(pid);
    return true;
}

int main() {
    win_map exes;
    EnumWindows(show_info, (LPARAM)&exes);
    std::copy(exes.begin(), exes.end(), std::ostream_iterator<win_map::value_type>(std::cout, "\n"));
    return 0;
}

Результаты быстрого теста несколько интересны.Скомпилированная как 32-битный код, версия, использующая QueryFullProcessImageName, нашла 33 процесса с окнами верхнего уровня и нашла имена для 31 из этих исполняемых файлов.Версия, использующая GetModuleFileNameEx, также нашла 33 процесса, но нашла имена только для 21 исполняемого файла.Однако, если я скомпилирую его как 64-битный код, либо версия найдет имена файлов для 31 из 33 исполняемых файлов (и те же самые два не будут выполнены).Учитывая частоту, с которой вы видите XP / x64, это, вероятно, не имеет большого значения, но я все же нашел это интересным.

В любом случае, даже наименее способная версия (32-битная / GMFNE) нашла имена для ~2/3 rds файлов.Хотя это, конечно, не то, на что вы надеетесь, но лучше, чем ничего.

1 голос
/ 14 сентября 2010

Должна быть возможность получить путь к файлу для запущенных процессов, так как это делает Process Explorer Sysinternals.Конечно, Process Explorer использует NtQueryInformationProcess , который не поддерживается.(С другой стороны, поскольку вы специально ориентируетесь на XP и будете использовать QueryFullProcessImageName в Vista и более поздних версиях, опасения, что API станет недоступным в будущей версии Windows, вероятно, не представляют проблемы.) В CodeProject есть статья о том, как использовать NtQueryInformationProcess.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...