C# 如何确定哪个IIS Express实例正在使用端口?
我想以编程方式终止正在运行的占用特定端口的IIS实例,但似乎无法确定哪个IIS实例正在使用特定端口 netstat.exe只是显示进程具有PID 4,但这是系统进程。“netsh http show urlacl”根本不显示占用的端口 IIS Express托盘程序不知怎么知道这一点。当我尝试在端口被占用的情况下启动另一个IIS Express实例时,会出现以下错误:C# 如何确定哪个IIS Express实例正在使用端口?,c#,iis,iis-express,C#,Iis,Iis Express,我想以编程方式终止正在运行的占用特定端口的IIS实例,但似乎无法确定哪个IIS实例正在使用特定端口 netstat.exe只是显示进程具有PID 4,但这是系统进程。“netsh http show urlacl”根本不显示占用的端口 IIS Express托盘程序不知怎么知道这一点。当我尝试在端口被占用的情况下启动另一个IIS Express实例时,会出现以下错误: 进程“IIS Express”(进程ID“10632”)已在使用端口“40000” 有人知道我如何获取这些信息吗?您可以运行下面
进程“IIS Express”(进程ID“10632”)已在使用端口“40000”
有人知道我如何获取这些信息吗?您可以运行下面的命令来获取可执行文件及其PID的信息
netstat -a -n -o -b | find "iisexpress.exe"
PID似乎是4(系统),因为实际侦听套接字位于名为的服务下 我查看了iisexpresstray.exe用来提供所有正在运行的IISExpress应用程序列表的内容。谢天谢地,它是易于反编译的托管.NET代码(全部在iisexpresstray.dll中) 它似乎至少有三种不同的方式来获取进程的端口号:
/port
(我们知道这是不可靠的)netsh http show servicestate view=requestq
并解析输出IisExpressHelper
类,都声明为internal
(尽管我认为有工具可以生成包装器或复制程序集并公布所有内容)
我选择使用Microsoft.Web.dll。它位于我的GAC中,但由于某些原因,它没有出现在Visual Studio中可添加为引用的程序集列表中,因此我只是从我的GAC中复制了该文件。拥有Microsoft.Web.dll后,只需使用以下代码:
using (var runtimeStatusClient = new RuntimeStatusClient())
{
var workerProcess = runtimeStatusClient.GetWorkerProcess(process.Id);
// Apparently an IISExpress process can run multiple sites/applications?
var apps = workerProcess.RegisteredUrlsInfo.Select(r => r.Split('|')).Select(u => new { SiteName = u[0], PhysicalPath = u[1], Url = u[2] });
// If we just assume one app
return new Uri(apps.FirstOrDefault().Url).Port;
}
您还可以调用RuntimeClient.getAllWorkerProcess
仅检索实际的工作进程
我也查看了registeredurlinfo(在Microsoft.Web.dll中),发现它使用了两个COM接口
IRsca2_核心
(F90F62AB-EE00-4E4F-8EA6-3805B6B25CDD
)IRsca2\u工作流程
(B1341209-7F09-4ECD-AE5F-3EE40D921870
)ServerManager
我在@makhdumi的回答中:
用法:
static public bool TryGetCurrentProcessRegisteredHttpPort(out List<int> ports, out Exception ex)
{
NetshInvoker netsh = new NetshInvoker();
return netsh.TryGetHttpPortUseByProcessId(Process.GetCurrentProcess().Id, out ports, out ex);
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace YourCompanyName.Server.ServerCommon.Utility
{
/// <summary>
/// Invoke netsh.exe and extract information from its output.
/// Source: @crokusek, https://stackoverflow.com/questions/32196188
/// @GETah, https://stackoverflow.com/a/8274758/538763
/// </summary>
public class NetshInvoker
{
const string NetshHttpShowServiceStateViewRequestqArgs = "http show servicestate view=requestq";
public NetshInvoker()
{
}
/// <summary>
/// Call netsh.exe to determine the http port number used by a given windowsPid (e.g. an IIS Express process)
/// </summary>
/// <param name="windowsPid">For example an IIS Express process</param>
/// <param name="port"></param>
/// <param name="ex"></param>
/// <returns></returns>
public bool TryGetHttpPortUseByProcessId(Int32 windowsPid, out List<Int32> ports, out Exception ex)
{
ports = null;
try
{
if (!TryQueryProcessIdRegisteredUrls(out Dictionary<Int32, List<string>> pidToUrlMap, out ex))
return false;
if (!pidToUrlMap.TryGetValue(windowsPid, out List<string> urls))
{
throw new Exception(String.Format("Unable to locate windowsPid {0} in '{1}' output.",
windowsPid, "netsh " + NetshHttpShowServiceStateViewRequestqArgs));
}
if (!urls.Any())
{
throw new Exception(String.Format("WindowsPid {0} did not reference any URLs in '{1}' output.",
windowsPid, "netsh " + NetshHttpShowServiceStateViewRequestqArgs));
}
ports = urls
.Select(u => new Uri(u).Port)
.ToList();
return true;
}
catch (Exception ex_)
{
ex = ex_;
return false;
}
}
private bool TryQueryProcessIdRegisteredUrls(out Dictionary<Int32, List<string>> pidToUrlMap, out Exception ex)
{
if (!TryExecNetsh(NetshHttpShowServiceStateViewRequestqArgs, out string output, out ex))
{
pidToUrlMap = null;
return false;
}
bool gotRequestQueueName = false;
bool gotPidStart = false;
int currentPid = 0;
bool gotUrlStart = false;
pidToUrlMap = new Dictionary<int, List<string>>();
foreach (string line in output.Split('\n').Select(s => s.Trim()))
{
if (!gotRequestQueueName)
{
gotRequestQueueName = line.StartsWith("Request queue name:");
}
else if (!gotPidStart)
{
gotPidStart = line.StartsWith("Process IDs:");
}
else if (currentPid == 0)
{
Int32.TryParse(line, out currentPid); // just get the first Pid, ignore others.
}
else if (!gotUrlStart)
{
gotUrlStart = line.StartsWith("Registered URLs:");
}
else if (line.ToLowerInvariant().StartsWith("http"))
{
if (!pidToUrlMap.TryGetValue(currentPid, out List<string> urls))
pidToUrlMap[currentPid] = urls = new List<string>();
urls.Add(line);
}
else // reset
{
gotRequestQueueName = false;
gotPidStart = false;
currentPid = 0;
gotUrlStart = false;
}
}
return true;
}
private bool TryExecNetsh(string args, out string output, out Exception exception)
{
output = null;
exception = null;
try
{
// From @GETah, https://stackoverflow.com/a/8274758/538763
Process p = new Process();
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
output = p.StandardOutput.ReadToEnd();
return true;
}
catch (Exception ex)
{
exception = ex;
return false;
}
}
}
}
静态公共bool TryGetCurrentProcessRegisteredHttpPort(输出列表端口,输出异常ex)
{
NetshInvoker netsh=新的NetshInvoker();
返回netsh.TryGetHttpPortUseByProcessId(Process.GetCurrentProcess().Id,out端口,out ex);
}
实施:
static public bool TryGetCurrentProcessRegisteredHttpPort(out List<int> ports, out Exception ex)
{
NetshInvoker netsh = new NetshInvoker();
return netsh.TryGetHttpPortUseByProcessId(Process.GetCurrentProcess().Id, out ports, out ex);
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace YourCompanyName.Server.ServerCommon.Utility
{
/// <summary>
/// Invoke netsh.exe and extract information from its output.
/// Source: @crokusek, https://stackoverflow.com/questions/32196188
/// @GETah, https://stackoverflow.com/a/8274758/538763
/// </summary>
public class NetshInvoker
{
const string NetshHttpShowServiceStateViewRequestqArgs = "http show servicestate view=requestq";
public NetshInvoker()
{
}
/// <summary>
/// Call netsh.exe to determine the http port number used by a given windowsPid (e.g. an IIS Express process)
/// </summary>
/// <param name="windowsPid">For example an IIS Express process</param>
/// <param name="port"></param>
/// <param name="ex"></param>
/// <returns></returns>
public bool TryGetHttpPortUseByProcessId(Int32 windowsPid, out List<Int32> ports, out Exception ex)
{
ports = null;
try
{
if (!TryQueryProcessIdRegisteredUrls(out Dictionary<Int32, List<string>> pidToUrlMap, out ex))
return false;
if (!pidToUrlMap.TryGetValue(windowsPid, out List<string> urls))
{
throw new Exception(String.Format("Unable to locate windowsPid {0} in '{1}' output.",
windowsPid, "netsh " + NetshHttpShowServiceStateViewRequestqArgs));
}
if (!urls.Any())
{
throw new Exception(String.Format("WindowsPid {0} did not reference any URLs in '{1}' output.",
windowsPid, "netsh " + NetshHttpShowServiceStateViewRequestqArgs));
}
ports = urls
.Select(u => new Uri(u).Port)
.ToList();
return true;
}
catch (Exception ex_)
{
ex = ex_;
return false;
}
}
private bool TryQueryProcessIdRegisteredUrls(out Dictionary<Int32, List<string>> pidToUrlMap, out Exception ex)
{
if (!TryExecNetsh(NetshHttpShowServiceStateViewRequestqArgs, out string output, out ex))
{
pidToUrlMap = null;
return false;
}
bool gotRequestQueueName = false;
bool gotPidStart = false;
int currentPid = 0;
bool gotUrlStart = false;
pidToUrlMap = new Dictionary<int, List<string>>();
foreach (string line in output.Split('\n').Select(s => s.Trim()))
{
if (!gotRequestQueueName)
{
gotRequestQueueName = line.StartsWith("Request queue name:");
}
else if (!gotPidStart)
{
gotPidStart = line.StartsWith("Process IDs:");
}
else if (currentPid == 0)
{
Int32.TryParse(line, out currentPid); // just get the first Pid, ignore others.
}
else if (!gotUrlStart)
{
gotUrlStart = line.StartsWith("Registered URLs:");
}
else if (line.ToLowerInvariant().StartsWith("http"))
{
if (!pidToUrlMap.TryGetValue(currentPid, out List<string> urls))
pidToUrlMap[currentPid] = urls = new List<string>();
urls.Add(line);
}
else // reset
{
gotRequestQueueName = false;
gotPidStart = false;
currentPid = 0;
gotUrlStart = false;
}
}
return true;
}
private bool TryExecNetsh(string args, out string output, out Exception exception)
{
output = null;
exception = null;
try
{
// From @GETah, https://stackoverflow.com/a/8274758/538763
Process p = new Process();
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
output = p.StandardOutput.ReadToEnd();
return true;
}
catch (Exception ex)
{
exception = ex;
return false;
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
命名空间YourCompanyName.Server.ServerCommon.Utility
{
///
///调用netsh.exe并从其输出中提取信息。
///资料来源:@crokusek,https://stackoverflow.com/questions/32196188
///@GETah,https://stackoverflow.com/a/8274758/538763
///
公共类NetshInvoker
{
常量字符串NetshHttpShowServiceStateViewRequestqArgs=“http show servicestate view=requestq”;
公共NetshInvoker()
{
}
///
///调用netsh.exe以确定给定windowsPid(例如IIS Express进程)使用的http端口号
///
///例如,IIS Express进程
///
///
///
public bool TryGetHttpPortUseByProcessId(Int32 windowsPid,输出列表端口,输出异常ex)
{
端口=空;
尝试
{
if(!TryQueryProcessIdRegisteredUrls(输出字典pidToUrlMap,输出ex))
返回false;
如果(!pidToUrlMap.TryGetValue(windowsPid,输出列表URL))
{
抛出新异常(String.Format(“无法在“{1}”输出中找到windowsPid{0}”,
windowsPid,“netsh”+netshhtpShowServiceStateViewRequestQargs);
}
如果(!url.Any())
{
抛出新异常(String.Format(“WindowsPid{0}未引用“{1}”输出中的任何URL。”,
windowsPid,“netsh”+netshhtpShowServiceStateViewRequestQargs);
}
端口=URL
.Select(u=>newURI(u.Port)
.ToList();
返回true;
}
捕获(例外情况除外)
{
ex=ex;
返回false;
}
}
私有bool TryQueryProcessIdRegisteredUrls(out Dictionary pidToUrlMap,out Exception ex)
{
if(!TryExecNetsh(NetshHttpShowServiceStateViewRequestqArgs,out字符串输出,out ex))
{
pidToUrlMap=null;
返回false;
}
bool gotRequestQueueName=false;
bool-gotPidStart=false;
int currentPid=0;
bool gotUrlStart=false;
pidToUrlMap=新字典();
foreach(output.Split('\n')中的字符串行。选择(s=>s.Trim())
{
如果(!gotRequestQueueName)
{
gotRequestQueueName=line.StartsWith(“请求队列名称:”);
}
否则如果(!gotPidStart)
{
gotPidStart=line.StartsWith(“过程