如何从 C# (.net 2) 重新启动(回收)IIS 应用程序池?
如果您发布示例代码,不胜感激?
我们开始吧:
HttpRuntime.UnloadAppDomain();
如果您使用的是 IIS7,那么当它停止时这将执行此操作。 我假设您可以调整重新启动而无需显示。
// Gets the application pool collection from the server.
[ModuleServiceMethod(PassThrough = true)]
public ArrayList GetApplicationPoolCollection()
{
// Use an ArrayList to transfer objects to the client.
ArrayList arrayOfApplicationBags = new ArrayList();
ServerManager serverManager = new ServerManager();
ApplicationPoolCollection applicationPoolCollection = serverManager.ApplicationPools;
foreach (ApplicationPool applicationPool in applicationPoolCollection)
{
PropertyBag applicationPoolBag = new PropertyBag();
applicationPoolBag[ServerManagerDemoGlobals.ApplicationPoolArray] = applicationPool;
arrayOfApplicationBags.Add(applicationPoolBag);
// If the applicationPool is stopped, restart it.
if (applicationPool.State == ObjectState.Stopped)
{
applicationPool.Start();
}
}
// CommitChanges to persist the changes to the ApplicationHost.config.
serverManager.CommitChanges();
return arrayOfApplicationBags;
}
如果您使用的是 IIS6 我不太确定,但您可以尝试获取 web.config 并编辑修改日期或其他内容。 对 web.config 进行编辑后,应用程序将重新启动。
以下方法经过测试适用于 IIS7 和 IIS8
第 1 步:添加对 Microsoft.Web.Administration.dll 的引用。该文件可以在路径 C:\Windows\System32\inetsrv\ 中找到,或将其安装为 NuGet 包 https://www.nuget.org/packages/Microsoft.Web.Administration/
第2步:添加以下代码
using Microsoft.Web.Administration;
使用空条件运算符
new ServerManager().ApplicationPools["Your_App_Pool_Name"]?.Recycle();
或
使用if条件检查是否为null
var yourAppPool=new ServerManager().ApplicationPools["Your_App_Pool_Name"];
if(yourAppPool!=null)
yourAppPool.Recycle();
下面的代码适用于 IIS6。未在 IIS7 中测试。
using System.DirectoryServices;
...
void Recycle(string appPool)
{
string appPoolPath = "IIS://localhost/W3SVC/AppPools/" + appPool;
using (DirectoryEntry appPoolEntry = new DirectoryEntry(appPoolPath))
{
appPoolEntry.Invoke("Recycle", null);
appPoolEntry.Close();
}
}
您也可以将“回收”更改为“开始”或“停止”。
我的代码采用了稍微不同的路线来回收应用程序池。 有几点需要注意,与其他人提供的不同:
1)我使用了 using 语句来确保正确处理 ServerManager 对象。
2)我正在等待应用程序池完成启动,然后再停止它,这样我们就不会在尝试停止应用程序时遇到任何问题。 同样,我正在等待应用程序池完成停止,然后再尝试启动它。
3)我强制该方法接受实际的服务器名称,而不是回退到本地服务器,因为我认为您可能应该知道您正在针对哪个服务器运行它。
4)我决定启动/停止应用程序而不是回收它,这样我就可以确保我们不会意外启动因其他原因而停止的应用程序池,并避免尝试回收已经存在的问题。已停止应用程序池。
public static void RecycleApplicationPool(string serverName, string appPoolName)
{
if (!string.IsNullOrEmpty(serverName) && !string.IsNullOrEmpty(appPoolName))
{
try
{
using (ServerManager manager = ServerManager.OpenRemote(serverName))
{
ApplicationPool appPool = manager.ApplicationPools.FirstOrDefault(ap => ap.Name == appPoolName);
//Don't bother trying to recycle if we don't have an app pool
if (appPool != null)
{
//Get the current state of the app pool
bool appPoolRunning = appPool.State == ObjectState.Started || appPool.State == ObjectState.Starting;
bool appPoolStopped = appPool.State == ObjectState.Stopped || appPool.State == ObjectState.Stopping;
//The app pool is running, so stop it first.
if (appPoolRunning)
{
//Wait for the app to finish before trying to stop
while (appPool.State == ObjectState.Starting) { System.Threading.Thread.Sleep(1000); }
//Stop the app if it isn't already stopped
if (appPool.State != ObjectState.Stopped)
{
appPool.Stop();
}
appPoolStopped = true;
}
//Only try restart the app pool if it was running in the first place, because there may be a reason it was not started.
if (appPoolStopped && appPoolRunning)
{
//Wait for the app to finish before trying to start
while (appPool.State == ObjectState.Stopping) { System.Threading.Thread.Sleep(1000); }
//Start the app
appPool.Start();
}
}
else
{
throw new Exception(string.Format("An Application Pool does not exist with the name {0}.{1}", serverName, appPoolName));
}
}
}
catch (Exception ex)
{
throw new Exception(string.Format("Unable to restart the application pools for {0}.{1}", serverName, appPoolName), ex.InnerException);
}
}
}
回收在 IIS6 上工作的代码:
/// <summary>
/// Get a list of available Application Pools
/// </summary>
/// <returns></returns>
public static List<string> HentAppPools() {
List<string> list = new List<string>();
DirectoryEntry W3SVC = new DirectoryEntry("IIS://LocalHost/w3svc", "", "");
foreach (DirectoryEntry Site in W3SVC.Children) {
if (Site.Name == "AppPools") {
foreach (DirectoryEntry child in Site.Children) {
list.Add(child.Name);
}
}
}
return list;
}
/// <summary>
/// Recycle an application pool
/// </summary>
/// <param name="IIsApplicationPool"></param>
public static void RecycleAppPool(string IIsApplicationPool) {
ManagementScope scope = new ManagementScope(@"\\localhost\root\MicrosoftIISv2");
scope.Connect();
ManagementObject appPool = new ManagementObject(scope, new ManagementPath("IIsApplicationPool.Name='W3SVC/AppPools/" + IIsApplicationPool + "'"), null);
appPool.InvokeMethod("Recycle", null, null);
}
有时候我觉得简单就是最好的。虽然我建议人们以某种巧妙的方式调整实际路径,以便在其他环境中以更广泛的方式工作 - 我的解决方案看起来像:
ExecuteDosCommand(@"c:\Windows\System32\inetsrv\appcmd recycle apppool " + appPool);
在 C# 中,运行 DOS 命令即可实现此目的。上述许多解决方案不适用于各种设置和/或需要打开 Windows 上的功能(取决于设置)。
这段代码对我有用。只需调用它即可重新加载应用程序。
System.Web.HttpRuntime.UnloadAppDomain()
如果您只想回收当前计算机上的所有应用程序池,这里有一个简单的解决方案。我必须“以管理员身份运行”才能正常工作。
using (var serverManager = new ServerManager())
{
foreach (var appPool in serverManager.ApplicationPools)
{
appPool.Recycle();
}
}
另一种选择:
System.Web.Hosting.HostingEnvironment.InitiateShutdown();
似乎比
UploadAppDomain
更好,后者在前者等待东西完成其工作时“终止”应用程序。
感谢所有的建议。我找到了一个简单的方法。只需在 web.config 中附加或修剪文本即可。希望这有帮助。
var webConfigFilePath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "web.config");
var fileText = File.ReadAllText(webConfigFilePath);
if (fileText.EndsWith(Environment.NewLine))
{
File.WriteAllText(webConfigFilePath, fileText.Trim());
}
else
{
using StreamWriter sw = File.AppendText(webConfigFilePath);
sw.WriteLine("");
}