using COMAdmin;
using System;
using System.Diagnostics;
using System.Management;
using System.Threading;
namespace ComAdminShutDown
{
public class ComAdminManager
{
/// <summary>
/// This method shuts down a COM+ package server.
/// </summary>
/// <param name="applicationNames">list of package names to shutdown</param>
/// <param name="timeoutspan">How much time we allow the COM+ package to run after stop</param>
/// <returns></returns>
public static bool ShutDown(string[] applicationNames, int timeoutspan=1,string serverName="localhost")
{
COMAdminCatalog catalog = new COMAdminCatalog();
catalog.Connect(serverName);
ICatalogCollection catalogApplications = catalog.GetCollection("Applications");
catalogApplications.Populate();
for (int i = 0; i < applicationNames.Length; ++i)
{
string aplicationName = applicationNames[i];
foreach (ICatalogObject catalogObject in catalogApplications)
{
string packageGuid = catalogObject.Key;
//Application Exists in COM+ Catalog
if (catalogObject.Name == aplicationName)
{
(bool,int) isPackageRunning = InstanceIsRunning(catalog, packageGuid);
if (isPackageRunning.Item1)
{
Console.WriteLine("The package {0} is running.", aplicationName);
catalogObject.Value["RecycleExpirationTimeout"] = timeoutspan;
catalogApplications.SaveChanges();
catalog.ShutdownApplication(catalogObject.Name);
catalogObject.Value["IsEnabled"] = 0;
catalogApplications.SaveChanges();
int count = 0;
bool needsFatality = true;
do
{
isPackageRunning = InstanceIsRunning(catalog, packageGuid);
if (isPackageRunning.Item1)
{
Thread.Sleep(timeoutspan*1000/5);
}
else
{
needsFatality = false;
break;
}
count++;
} while (count < 5);
if (needsFatality)
{
if (serverName == "locahost")
{
//Kill pid only works on localhost
KillProcess(isPackageRunning.Item2, serverName);
}
else
{
// WMI
WMIKillProcess(isPackageRunning.Item2, serverName);
}
}
}
}
}
}
return true;
}
private static void WMIKillProcess(int item2, string serverName)
{
var connectoptions = new ConnectionOptions();
var endpoint= @"\\" + serverName + @"\root\cimv2";
ManagementScope scope = new ManagementScope(endpoint, connectoptions);
var queryStr = "select * from Win32_process where pid = '" + item2 + "'";
var query = new SelectQuery(queryStr);
using (var searcher = new ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
}
}
}
private static void KillProcess(int pid,string serverName)
{
Process[] process = Process.GetProcesses(serverName);
foreach (Process prs in process)
{
if (prs.Id == pid)
{
try
{
prs.Kill();
prs.WaitForExit(0);
break;
}
catch (NotSupportedException)
{
//Already dying
}
catch (InvalidOperationException)
{
//Already dying
}
}
}
}
private static (bool,int) InstanceIsRunning(COMAdminCatalog catalog, string packageId)
{
COMAdminCatalogCollection applicationInstances = catalog.GetCollection("ApplicationInstances");
int pid = 0;
applicationInstances.Populate();
foreach (COMAdminCatalogObject applicationInstance in applicationInstances)
{
if (applicationInstance.Value["Application"] == packageId)
{
pid =(int)applicationInstance.Value["ProcessID"];
return (true, pid);
}
}
return (false, 0);
}
}
}