私は同じようなことをしようとしていました。Microsoftが提供するCOMライブラリは不完全であると結論付けました。ドキュメントに「注:このトピックはプレリリースのドキュメントであり、将来のリリースで変更される可能性がある」と記載されているため、使用しません。
そこで、IISExpressTray.exeが何をしているのかを見てみることにしました。同様のことをしているようです。
IISExpressTray.dllを分解すると、すべてのIISexpressプロセスを一覧表示し、IISexpressプロセスを停止することに魔法がないことがわかりました。
そのCOMライブラリは呼び出されません。レジストリからは何も検索しません。
だから、私が最終的に得た解決策は非常に簡単です。IISエクスプレスプロセスを開始するには、Process.Start()を使用して、必要なすべてのパラメーターを渡します。
IIS Expressプロセスを停止するために、リフレクターを使用してIISExpressTray.dllからコードをコピーしました。ターゲットIISExpressプロセスにWM_QUITメッセージを送信するだけであることがわかりました。
これは、IISExpressプロセスを開始および停止するために作成したクラスです。これが他の誰かを助けることができることを願っています。
class IISExpress
{
internal class NativeMethods
{
// Methods
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr GetTopWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll", SetLastError = true)]
internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
}
public static void SendStopMessageToProcess(int PID)
{
try
{
for (IntPtr ptr = NativeMethods.GetTopWindow(IntPtr.Zero); ptr != IntPtr.Zero; ptr = NativeMethods.GetWindow(ptr, 2))
{
uint num;
NativeMethods.GetWindowThreadProcessId(ptr, out num);
if (PID == num)
{
HandleRef hWnd = new HandleRef(null, ptr);
NativeMethods.PostMessage(hWnd, 0x12, IntPtr.Zero, IntPtr.Zero);
return;
}
}
}
catch (ArgumentException)
{
}
}
const string IIS_EXPRESS = @"C:\Program Files\IIS Express\iisexpress.exe";
const string CONFIG = "config";
const string SITE = "site";
const string APP_POOL = "apppool";
Process process;
IISExpress(string config, string site, string apppool)
{
Config = config;
Site = site;
AppPool = apppool;
StringBuilder arguments = new StringBuilder();
if (!string.IsNullOrEmpty(Config))
arguments.AppendFormat("/{0}:{1} ", CONFIG, Config);
if (!string.IsNullOrEmpty(Site))
arguments.AppendFormat("/{0}:{1} ", SITE, Site);
if (!string.IsNullOrEmpty(AppPool))
arguments.AppendFormat("/{0}:{1} ", APP_POOL, AppPool);
process = Process.Start(new ProcessStartInfo()
{
FileName = IIS_EXPRESS,
Arguments = arguments.ToString(),
RedirectStandardOutput = true,
UseShellExecute = false
});
}
public string Config { get; protected set; }
public string Site { get; protected set; }
public string AppPool { get; protected set; }
public static IISExpress Start(string config, string site, string apppool)
{
return new IISExpress(config, site, apppool);
}
public void Stop()
{
SendStopMessageToProcess(process.Id);
process.Close();
}
}
既存のIISエクスプレスプロセスをすべてリストする必要はありません。それが必要な場合は、リフレクターで見たものから、IISExpressTray.dllが行うことは呼び出すことですProcess.GetProcessByName("iisexpress", ".")
私が提供したクラスを使用するために、これは私がそれをテストするために使用したサンプルプログラムです。
class Program
{
static void Main(string[] args)
{
Console.Out.WriteLine("Launching IIS Express...");
IISExpress iis1 = IISExpress.Start(
@"C:\Users\Administrator\Documents\IISExpress\config\applicationhost.config",
@"WebSite1(1)",
@"Clr4IntegratedAppPool");
IISExpress iis2 = IISExpress.Start(
@"C:\Users\Administrator\Documents\IISExpress\config\applicationhost2.config",
@"WebSite1(1)",
@"Clr4IntegratedAppPool");
Console.Out.WriteLine("Press ENTER to kill");
Console.In.ReadLine();
iis1.Stop();
iis2.Stop();
}
}
これはあなたの質問に対する答えではないかもしれませんが、あなたの質問に興味を持っている人々は私の仕事が役に立つと思うかもしれません。コードを自由に改善してください。あなたが強化したいと思うかもしれないいくつかの場所があります。
- iisexpress.exeの場所をハードコーディングする代わりに、レジストリから読み取るようにコードを修正できます。
- iisexpress.exeでサポートされているすべての引数を含めませんでした
- エラー処理はしませんでした。したがって、IISExpressプロセスが何らかの理由で開始できなかった場合(たとえば、ポートが使用されている場合)、わかりません。これを修正する最も簡単な方法は、StandardErrorストリームを監視し、StandardErrorストリームから何かを取得した場合に例外をスローすることだと思います。