Harden IISExpress shutdown code (#7004)

This commit is contained in:
Pavel Krymets 2019-01-25 09:19:51 -08:00 committed by GitHub
parent 21f80b2051
commit ebb7f3ade3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 32 additions and 8 deletions

View File

@ -9,6 +9,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@ -443,33 +444,56 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
private class WindowsNativeMethods
{
[DllImport("user32.dll")]
internal static extern IntPtr GetTopWindow(IntPtr hWnd);
[DllImport("user32.dll")]
internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
internal delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
internal static extern bool EnumWindows(EnumWindowProc callback, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,int nMaxCount);
}
private void SendStopMessageToProcess(int pid)
{
Logger.LogInformation($"Sending shutdown request to {pid}");
for (var ptr = WindowsNativeMethods.GetTopWindow(IntPtr.Zero); ptr != IntPtr.Zero; ptr = WindowsNativeMethods.GetWindow(ptr, 2))
{
var found = false;
WindowsNativeMethods.EnumWindows((ptr, param) => {
WindowsNativeMethods.GetWindowThreadProcessId(ptr, out var windowProcessId);
if (pid == windowProcessId)
{
// 256 is the max length
var className = new StringBuilder(256);
if (WindowsNativeMethods.GetClassName(ptr, className, className.Capacity) == 0)
{
throw new InvalidOperationException($"Unable to get window class name: {Marshal.GetLastWin32Error()}");
}
if (!string.Equals(className.ToString(), "IISEXPRESS", StringComparison.OrdinalIgnoreCase))
{
// skip windows without IISEXPRESS class
return true;
}
var hWnd = new HandleRef(null, ptr);
if (!WindowsNativeMethods.PostMessage(hWnd, 0x12, IntPtr.Zero, IntPtr.Zero))
{
throw new InvalidOperationException($"Unable to PostMessage to process {pid}. LastError: {Marshal.GetLastWin32Error()}");
}
return;
found = true;
return false;
}
return true;
}, IntPtr.Zero);
if (!found)
{
throw new InvalidOperationException($"Unable to find main window for process {pid}");
}
throw new InvalidOperationException($"Unable to find main window for process {pid}");
}
private void GracefullyShutdownProcess(Process hostProcess)