Starting and stopping IIS Express programmatically
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.
- Instead of hardcoding the iisexpress.exe location, you can fix my code to read from the registry.
- I didn't include all the arguments supported by iisexpress.exe
- I didn't do error handling. So, if the IISExpress process failed to start for some reasons (e.g. port is in used), I don't know. I think the easiest way to fix it is to monitor the StandardError stream and throw exception if I get anything from StandardError stream
Stop IIS express process based on site name
I put together this script in PowerShell:
$site = 'Webapplication' # replace this by your site name (not case sensitive)
$process = Get-CimInstance Win32_Process -Filter "Name = 'iisexpress.exe'" | ? {$_.CommandLine -like "*/site:`"$site`"*" }
if($process -ne $null)
{
Write-Host "Trying to stop $($process.CommandLine)"
Stop-Process -Id $process.ProcessId
Start-Sleep -Seconds 1 # Wait 1 second for good measure
Write-Host "Process was stopped"
} else
{
Write-Host "Website was not running"
}
- Modify the first line to replace the site name with yours. Save this
file as stopiis.ps1 on your project folder (not the solution folder). - Now, on Solution Explorer, right-click and choose properties
- On the left side, choose Build Events
Put this on 'Pre-Build event command line' so it will run before compiling:
echo powershell -File "$(ProjectDir)stopiis.ps1"
powershell -File "$(ProjectDir)stopiis.ps1"
- Note: you do not need to run Visual Studio in Administrative mode because IISExpress.exe run under your account
Stop a web site hosted with IIS Express from command line
Option-1:
If you don't have any other sites running, try
"taskkill /IM iisexpress.exe"
Note: This stops all iisexpress.exe processes
Option-2:
Write some executable utility for doing this. Following link may help you!
Starting and stopping IIS Express programmatically
Starting a ASP.net WebApp using IISExpress from the command line
When using path with IISExpress commandline it should point to root folder of your website not bin folder.
iisexpress /path:c:\myapp\
Related Topics
Mstest Cannot Find the Assembly
How to Hide Wpf Datagrid Columns Depending on a Property
Find() VS. Where().Firstordefault()
Merge Multiple Word Documents into One Open Xml
Main: Not All Code Paths Return a Value
Programmatically Encrypting a Config-File in .Net
How to Define Implicit Conversions of Enums in C#
Bind Multiple Combobox to a Single List - Issue: When I Select an Item, All Combo Boxes Change
Issue with List.Add() Only Saving the Last Added Item
Handling Multiple Requests with C# Httplistener
Can Structs Contain Fields of Reference Types
Add Custom Header in Httpwebrequest
Check If All Items Are the Same in a List
Sortedlist<>, Sorteddictionary<> and Dictionary<>
Datetime.Parse("2012-09-30T23:00:00.0000000Z") Always Converts to Datetimekind.Local
Changing the Cursor in Wpf Sometimes Works, Sometimes Doesn'T