I am trying to build a small application in C# which should start/stop an IIS Express worker process. For this purpose I want to use the official "IIS Express API" which is documented on MSDN: http://msdn.microsoft.com/en-us/library/gg418415.aspx
As far as I understand, the API is based (only) on COM interfaces. To use this COM interfaces I've added a reference to the COM library in VS2010 via Add Reference -> COM -> "IIS Installed Versions Manager Interface":
So far so good, but what's next? There is an IIISExprProcessUtility
interface available which includes the the two "methods" to start/stop an IIS process. Do I have to write a class which implements this interface?
public class test : IISVersionManagerLibrary.IIISExprProcessUtility { public string ConstructCommandLine(string bstrSite, string bstrApplication, string bstrApplicationPool, string bstrConfigPath) { throw new NotImplementedException(); } public uint GetRunningProcessForSite(string bstrSite, string bstrApplication, string bstrApplicationPool, string bstrConfigPath) { throw new NotImplementedException(); } public void StopProcess(uint dwPid) { throw new NotImplementedException(); } }
As you can see, I'm not a professional developer. Can someone point me in the right direction. Any help is greatly appreciated.
Update 1: According to the suggestions I've tried the following code which unfortunately doesn't work:
Ok, it can be instantiated but I cannot see how to use this object...
IISVersionManagerLibrary.IIISExpressProcessUtility test3 = (IISVersionManagerLibrary.IIISExpressProcessUtility) Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("5A081F08-E4FA-45CC-A8EA-5C8A7B51727C"))); Exception: Retrieving the COM class factory for component with CLSID {5A081F08-E4FA-45CC-A8EA-5C8A7B51727C} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
Closing IIS Express By default Visual Studio places the IISExpress icon in your system tray at the lower right hand side of your screen, by the clock. You can right click it and choose exit. If you don't see the icon, try clicking the small arrow to view the full list of icons in the system tray.
Configure IIS express on visual studioSelect the web application project and open properties -> select the web tab -> under server's select IIS express-> Specify the project URL. Now open the project folder and . vs folder (Hidden) -> Config -> applicationhost.
I was trying to do similar thing. I concluded that the COM library provided by Microsoft is incomplete. I don't use it because the doc mentioned that "Note: This topic is pre-release documentation and is subject to change in future releases".
So, I decided to take a look at what IISExpressTray.exe is doing. It seems to be doing similar things.
I disassemble the IISExpressTray.dll and found that there is no magic in listing out all the IISexpress processes and stoping the IISexpress process.
It doesn't call that COM library. It doesn't lookup anything from registry.
So, the solution I ended up is very simple. To start an IIS express process, I just use Process.Start() and pass in all the parameters I need.
To stop an IIS express process, I copied the code from IISExpressTray.dll using reflector. I saw it simply sends a WM_QUIT message to the target IISExpress process.
Here is the class I wrote to start and stop an IIS express process. Hope this can help somebody 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 don't need to list all the existing IIS express process. If you need that, from what I saw in the reflector, what IISExpressTray.dll does is to call Process.GetProcessByName("iisexpress", ".")
To use the class I provided, here is a sample program 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 an answer to your question but I think people interesting in your question may find my work useful. Feel free to improve the codes. There are some places that you might want to enhance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With