How to Chuck Norris Stop a COM+ Server Package via C#

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

 

Leave a Reply

Your email address will not be published. Required fields are marked *