質問
私たちの内部の人々がもはや使用すべきではないいくつかの古い16ビットアプリケーションの実行のためにトラップしています。これらは1985年のDOSアプリであるため、それらのトラップは簡単でした。NTVDM.exeの下で起動するプロセスをキャプチャする
今、問題は、NTVDMが実際に内部で実行しているプログラムを見つけることです。どうやら1985のプログラムの実行が許可されているはずなので、NTVDMの下に隠れている実際のEXE名を確認する必要があります。
WqlEventQuery query =
new WqlEventQuery("__InstanceCreationEvent",
new TimeSpan(0, 0, 1),
"TargetInstance isa \"Win32_Process\"");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
...
static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
ProcessInfo PI = new ProcessInfo();
PI.ProcessID = int.Parse(instance["ProcessID"].ToString());
PI.ProcessName = instance["Name"].ToString();
PI.ProcessPath = instance["ExecutablePath"].ToString();
// Here's the part I need...
PI.ActualEXE = ???;
// ... do the magic on the PI class ...
instance.Dispose();
}
インスタンス情報をキャプチャすると、コマンドラインを取得できますが、引数は" -f -i10"です。 ...コマンドラインにEXE名がありません。実際に実行されている16ビットアプリケーションのEXE名を特定するために検討する必要がある他のメソッド/プロパティはありますか?
更新: NTVDMプロセスを見つけることができる場合、どのようにして(プログラムで)実行されているEXEへの実際のパスを知ることができますか?
ありがとう。
解決
トリックは、 VDMEnumProcessWOW (これはVDMを提供します)、ただし VDMEnumTasksWOW 。この関数に渡す列挙子関数は、指定されたVDMの16ビットタスクごとに呼び出されます。
自分でチェックしていませんが、ドキュメントによると、この CodeProjectのライブラリは、PROC16列挙値を渡すと、まさにそれを行います。 C ++です。そのコードのコンパイルとC#からの呼び出しについてサポートが必要な場合はお知らせください。例を挙げます。
このテクニックを使用するプログラムは、プロセスマスターで、付属しています完全なソース。必要な情報を提供するかどうかを確認するために実行することをお勧めします。その場合、このメソッドを独自のアプリケーションに適用できます(Windows Vistaまたは7では実行されず、古いVB5コードを使用しますが、明らかにそうではありません)互換性があります。XPで実行する必要があります。
これらの機能を備えたものが計画どおりに動作しない場合は、Vistaを使用している可能性があり、この StackOverflowの質問は、ホットフィックスのダウンロード。これは、ここで説明されます:
"を使用するアプリケーション VDMEnumProcessWOW関数 仮想DOSマシンの戻り値を列挙する 上の出力がない、または誤った出力 32ビットを実行しているコンピューター Windows Vistaのバージョン"
更新: これは有望なようですが、パッチを適用し、Microsoftを含むいくつかのバージョンのコードを実行しました。それらはすべてXPで動作しますが、静かに失敗します(エラーなし、または間違った戻り値)Vistaで。
「ちょっと」作業コード
更新: 私は(とりわけ)次のコードを試しました。このコードはC#で問題なくコンパイルできます(より簡単に記述できますが、したくありませんでした)マーシャルミスのリスクがあります)。これらの関数を追加すると、 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
}
}
更新: 興味をそそる有名なMatt Pietrekが読んだ。文の終わり近くのどこかに注意してください:
"手始めに、MS-DOSベースのプログラム 常に別のNTVDMで実行されるようです セッション。私は得ることができなかった で実行するMS-DOSベースのプログラム 16ビットWindowsベースと同じセッション プログラム。また、私は2つを得ることができませんでした MS-DOSベースで独立して開始 同じNTVDMで実行するプログラム セッション。実際、NTVDMセッション 実行中のMS-DOSプログラムが表示されない VDMEnumProcessWOW列挙で。"
どのプロセスがロードされているかを調べるには、NTVDMにフックを記述するか、ファイルへのアクセスを監視するリスナーを記述する必要があるようです。特定のDOSファイルを読み取ろうとするアプリケーションがNTVDM.exeの場合、それはビンゴです。 NTVDM.exeにのみ添付されているDLLを作成することもできますが、今は少し先を行っています。短い話:これ
他のヒント
これは私のために働く:
-
Windows XPのソフトウェア制限ポリシーの説明の指示に従ってくださいローカルまたはドメインポリシーエディターを開きます。
-
ソフトウェア制限ポリシーの下->追加のルール、右クリックして[新しいハッシュルール]を選択します。
-
(たとえば)
edit.com
を参照します。セキュリティレベルが[許可しない]に設定されていることを確認します。 [OK]をクリックします。
今、
C:\> edit
システムは指定されたプログラムを実行できません。
( command.com
と cmd.exe
から同じ結果が得られます-Win XPの場合)
VDMDBG関数に関するこのリンクから、P / Invoke"を実行できる場合があります。 VDMEnumProcessWOW()&quot ;、 プロセス内のモジュールの列挙PSAPIを使用。
16ビットDOSアプリケーションに関する注意:
VDMDBG関数のいずれも動作しません 16ビットDOSアプリケーション。列挙するには DOS VDM、別のものを使用する必要があります 方法。最初に、使用できます リストを作成するVDMEnumProcessWOW() すべてのWin16 VDM、次にすべて列挙 いくつかを使用するNTVDM.exeのインスタンス 他のスキーム(PSAPIなど)。どれか 完全な列挙からNTVDM.exe Win16リストにないものは DOS VDM。作成して終了できます 16ビットDOSアプリケーション CreateProcess()および TerminateProcess()。
役立つこと...