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); } } }