I tried to do this. I came to the conclusion that the COM library provided by Microsoft is incomplete. I do not use it because the document mentions that "Note: this section is a preliminary version of the documentation and is subject to change in future releases."
So, I decided to see what IISExpressTray.exe does. He seems to be doing similar things.
I parsed IISExpressTray.dll and found that there is no magic in listing all IISexpress processes and stopping the IISexpress process.
It does not call this COM library. It does not look for anything from the registry.
So the solution that I have finished is very simple. To start the IIS express process, I just use Process.Start () and pass all the parameters I need.
To stop the IIS express delivery process, I copied the code from IISExpressTray.dll using a reflector. I saw that it just sends a WM_QUIT message to the target IISExpress process.
Here is a class I wrote to start and stop the IIS express process. Hope this helps someone else.
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(); } }
I do not need to list the entire existing IIS process. If you need it, what I saw in the reflector, what IISExpressTray.dll does is call Process.GetProcessByName("iisexpress", ".")
To use the class I provided, here is an example program that I used to test it.
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(); } }
This may not be the answer to your question, but I think that people who are interesting in your question may find my work useful. Feel free to upgrade the codes. There are some places you can improve.
- Instead of hard coding the location of iisexpress.exe, you can fix my code to read from the registry.
- I did not include all the arguments supported by iisexpress.exe
- I did not handle error handling. So, if the IISExpress process did not start for some reason (for example, the port is used), I do not know. I think the easiest way to fix this is to control the StandardError stream and throw an exception if I get anything from the StandardError stream.