Хитрость заключается не в использовании VDMEnumProcessWOW (который дает VDM), а в использовании VDMEnumTasksWOW . Функция перечисления, которую вы передаете этой функции, будет вызываться для каждой 16-битной задачи в указанном VDM.
Я не проверял это сам, но согласно документации, эта библиотека CodeProject делает именно это, если вы передаете значение перечисления PROC16. Это C ++, если вам нужна помощь в компиляции этого кода и вызове его из C #, дайте мне знать, и я приведу вам пример.
Программа, использующая эту технику: Process Master , поставляется с полным исходным кодом. Я предлагаю вам запустить его, чтобы выяснить, дает ли он необходимую вам информацию, и если да, то вы можете применить этот метод к своему собственному приложению (он не работает в Windows Vista или 7, он использует старый код VB5, по-видимому, это не так). совместимо. Должно работать на XP).
Если что-то с этими функциями идет не так, как запланировано, возможно, вы работаете в Vista, и вам может понадобиться исправление, описанное в этом вопросе StackOverflow , который указывает на загрузку исправления , которое в свою очередь описано здесь :
"Приложение, которое использует
Функция VDMEnumProcessWOW для
перечислять виртуальные DOS машины возвращаются
нет вывода или неправильный вывод на
компьютер под управлением 32-битной
версия Windows Vista "
Обновление: , хотя это кажется многообещающим, я применил патч, запустил несколько версий кода, включая Microsoft, и, хотя все они работают на XP, они молча терпят неудачу (нет ошибка или неверное возвращаемое значение) в Vista.
Рабочий код "своего рода"
Обновление: Я экспериментировал (среди прочего) со следующим кодом, который прекрасно компилируется в C # (и может быть написан проще, но я не хотел запускать риск ошибки маршала). Когда вы добавляете эти функции, вы можете вызвать Enum16BitProcesses
, который запишет имена файлов EXE-файлов 16-битных процессов в консоль.
Я не могу запустить его в Vista 32 bit. Но, возможно, другие могут попытаться скомпилировать его или найти ошибку в коде. Было бы неплохо узнать, работает ли он на других системах:
public class YourEnumerateClass
{
public static void Enum16BitProcesses()
{
// create a delegate for the callback function
ProcessTasksExDelegate procTasksDlgt =
new ProcessTasksExDelegate(YourEnumerateClass.ProcessTasksEx);
// this part is the easy way of getting NTVDM procs
foreach (var ntvdm in Process.GetProcessesByName("ntvdm"))
{
Console.WriteLine("ntvdm id = {0}", ntvdm.Id);
int apiRet = VDMEnumTaskWOWEx(ntvdm.Id, procTasksDlgt, IntPtr.Zero);
Console.WriteLine("EnumTaskWOW returns {0}", apiRet);
}
}
// declaration of API function callback
public delegate bool ProcessTasksExDelegate(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
);
// the actual function that fails on Vista so far
[DllImport("VdmDbg.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern int VDMEnumTaskWOWEx(
int processId,
ProcessTasksExDelegate TaskEnumProc,
IntPtr lparam);
// the actual callback function, on Vista never gets called
public static bool ProcessTasksEx(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
)
{
// using PtrToStringAnsi, based on Matt's comment, if it fails, try PtrToStringAuto
string filename = Marshal.PtrToStringAnsi(ptrFileName);
Console.WriteLine("Filename of WOW16 process: {0}", filename);
return false; // false continues enumeration
}
}
Обновление: Интригующее чтение от известного Мэтта Пьетрека. Помните предложение где-то ближе к концу:
"Для начинающих, программы на базе MS-DOS
кажется, всегда работают в отдельном NTVDM
сессий. Я так и не смог получить
Программа на базе MS-DOS для запуска в
тот же сеанс, что и 16-разрядный Windows-based
программа. Я не смог получить два
самостоятельно запустил MS-DOS на основе
программы для запуска в том же NTVDM
сессия. На самом деле сеансы НТВДМ
запущенные программы MS-DOS не отображаются
в перечислениях VDMEnumProcessWOW. "
Похоже, что для того, чтобы узнать, какие процессы загружены, вам нужно записать хук в NTVDM или написать слушатель, который контролирует доступ к файлу. Когда приложение, которое пытается прочитать определенный файл DOS, - это NTVDM.exe, это бинго. Возможно, вы захотите написать библиотеку DLL, которая подключена только к NTVDM.exe, но теперь мы немного опережаем себя. Короче говоря: эта маленькая поездка в НТВДМ показала «возможности», которые в конце концов стали настоящим обманом.
Есть еще один способ, но времени слишком мало, чтобы создать пример. Вы можете копаться в сегментах памяти DOS, и EXE обычно загружается в тот же сегмент. Но я не уверен, приведет ли это в конечном итоге к тому же результату и стоит ли оно усилий.