- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在执行一些我们的内部人员不应再使用的旧 16 位应用程序。它们是 1985 年的 DOS 应用程序,因此很容易捕获它们……捕获在 NTVDM.exe 下启动的任何进程
现在,问题是找出 NTVDM 实际运行的是哪个程序。显然有几个 1985 程序应该被允许运行,所以我需要查看隐藏在 NTVDM 下的实际 EXE 名称。
WqlEventQuery 查询 =
新的 WqlEventQuery("__InstanceCreationEvent",
新的时间跨度(0、0、1),
"TargetInstance isa\"Win32_Process\"");
ManagementEventWatcher 观察者 = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
观察者.Start();
...
static void watcher_EventArrived(对象发送者,EventArrivedEventArgs e)
{
ManagementBaseObject 实例 = (ManagementBaseObject)e.NewEvent["TargetInstance"];
ProcessInfo PI = new ProcessInfo();
PI.ProcessID = int.Parse(实例["ProcessID"].ToString());
PI.ProcessName = instance["名称"].ToString();
PI.ProcessPath = instance["ExecutablePath"].ToString();
//这是我需要的部分...
PI.ActualEXE = ???;
//... 在 PI 类上施展魔法 ...
instance.Dispose();
}
当我捕获实例信息时,我可以得到命令行,但是参数是“-f -i10”......命令行上没有EXE名称。我是否应该查看任何其他方法/属性来确定实际运行的 16 位应用程序的 EXE 名称?
更新:让我细化一下问题:如果我能找到 NTVDM 进程,我如何以编程方式知道在其下执行的 EXE 的实际路径?
谢谢。
最佳答案
诀窍是不要使用 VDMEnumProcessWOW (它给出了 VDM),但要使用 VDMEnumTasksWOW .您传递给此函数的枚举器函数将为指定 VDM 中的每个 16 位任务调用。
我自己没有查过,但是根据文档,这个library of CodeProject如果您传入 PROC16 枚举值,则可以做到这一点。它是 C++,如果您需要帮助编译该代码并从 C# 调用它,请告诉我,我会给您举个例子。
使用此技术的程序是 Process Master ,它带有完整的源代码。我建议你运行它看看它是否提供了你需要的信息,如果是的话,你可以将此方法应用于你自己的应用程序(它不能在 Windows Vista 或 7 上运行,它使用旧的 VB5 代码,显然它不是兼容。它应该在 XP 上运行)。
如果这些功能没有按计划进行,您可能使用的是 Vista 并且可能需要此 StackOverflow question 中描述的修补程序, 指向 downloading a hotfix ,这又是described here :
"An application that uses theVDMEnumProcessWOW function toenumerate virtual DOS machines returnsno output or incorrect output on acomputer that is running a 32-bitversion of Windows Vista"
更新:虽然这看起来很有希望,但我应用了补丁,运行了多个版本的代码,包括 Microsoft 的,虽然它们都可以在 XP 上运行,但它们无声地失败了(没有错误,或错误的返回值)在 Vista 上。
更新: 我尝试了(除其他外)以下代码,它在 C# 中编译良好(并且可以编写得更简单,但我不想冒编码(marshal)错误的风险)。当你添加这些函数时,你可以调用Enum16BitProcesses
,它会将16位进程的EXE文件的文件名写入控制台。
我无法在 Vista 32 位上运行它。但也许其他人可以尝试编译它,或者找到代码中的错误。很高兴知道它是否适用于其他系统:
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
}
}
更新: Intriguing read由著名的 Matt Pietrek 创作。注意接近尾声的句子:
"For starters, MS-DOS-based programsseem to always run in separate NTVDMsessions. I was never able to get anMS-DOS-based program to run in thesame session as a 16-bit Windows-basedprogram. Nor was I able to get twoindependently started MS-DOS-basedprograms to run in the same NTVDMsession. In fact, NTVDM sessionsrunning MS-DOS programs don't show upin VDMEnumProcessWOW enumerations."
看来,要找出加载了哪些进程,您需要在 NTVDM 中编写一个 Hook 或编写一个监听器来监视对文件的访问。当试图读取某个 DOS 文件的应用程序是 NTVDM.exe 时,它就成功了。您可能想要编写仅附加到 NTVDM.exe 的 DLL,但现在我们有点超前了。长话短说:这次进入 NTVDM 的小旅程显示了最终出现真正恶作剧的“可能性”。
还有另一种方法,但是时间太短无法创建示例。您可以在 DOS 内存段中查找,EXE 通常加载在同一段中。但我不确定这最终是否会导致相同的结果以及是否值得付出努力。
关于c# - 在 NTVDM 下运行的 16 位应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1649827/
我尝试启用 windows NTVDM 功能以在我的 windows 8 虚拟机上运行 16 位应用程序。 我知道如何通过 windows 控制面板启用 NTVDM。 但我不知道如何使用命令(wmic
我正在执行一些我们的内部人员不应再使用的旧 16 位应用程序。它们是 1985 年的 DOS 应用程序,因此很容易捕获它们……捕获在 NTVDM.exe 下启动的任何进程 现在,问题是找出 NTVDM
在创建合并排序程序时,我在使用指针而不是数组时遇到错误。以下代码运行正确: void main() { clrscr(); int n,i,A[100]; cout>n;
我在ArithmeticExpressionCompiler 中交叉编译了一个32 位模拟时钟。使用 GNU 汇编程序从 Linux 到 DOS。当在 QEMU 或 VirtualBox(比 NTVD
我在ArithmeticExpressionCompiler 中交叉编译了一个32 位模拟时钟。使用 GNU 汇编程序从 Linux 到 DOS。当在 QEMU 或 VirtualBox(比 NTVD
我是一名优秀的程序员,十分优秀!