Click here to Skip to main content
15,891,184 members
Articles / Programming Languages / XML

A command line tool to deploy COM components in COM+

Rate me:
Please Sign up or sign in to vote.
4.60/5 (3 votes)
25 Jan 2008CPOL4 min read 48K   518   17  
In a mixed .NET/COM COM+ based environment, one may find a need for a command line tool to deploy COM components in COM+.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;

using COMAdmin;

namespace RegComPlus
{
    internal delegate void InstallEventHandler(object Source, string Description);

    internal class Deployer
    {
        #region members
        
        private IDictionary<string, Package> m_cPackages = null;

        #endregion

        #region properties

        private IDictionary<string, Package> Packages
        {
            get
            {
                return (m_cPackages);
            }
        }

        #endregion

        #region constructors/destructors

        public Deployer()
        {
            m_cPackages = new Dictionary<string, Package>();
        }

        ~Deployer()
        {
            m_cPackages = null;
        }

        #endregion

        #region private

        private string GetAttributeValue(XmlNode XmlNode, string Name)
        {
            return(GetAttributeValue(XmlNode, Name, null));
        }

        private string GetAttributeValue(XmlNode XmlNode, string Name, string DefaultValue)
        {
            if (null == XmlNode) throw(new ArgumentNullException());

            XmlNode cAttribute = XmlNode.Attributes.GetNamedItem(Name);
            if (null == cAttribute) return (DefaultValue);
            string sRetval = cAttribute.Value.Length > 0 ? cAttribute.Value : DefaultValue;
            cAttribute = null;

            return (sRetval);
        }

        #endregion

        #region public

        public bool LoadXml(string WorkingDirectory, string ConfigurationXml)
        {
            bool bResult = true;
            XmlDocument cXmlDocument = null;
            XmlNodeList cPackagesNodes = null;

            try
            {
                cXmlDocument = new XmlDocument();
                cXmlDocument.LoadXml(ConfigurationXml);

                cPackagesNodes = cXmlDocument.SelectNodes("//package");

                foreach (XmlNode cPackageNode in cPackagesNodes)
                {
                    string sName = GetAttributeValue(cPackageNode, "name");
                    if (null == sName) throw (new Exception("Invalid configuration, package name attribute not found.\n" + cPackageNode.InnerXml));

                    // new package
                    Package cPackage = new Package();
                    cPackage.Name = sName;
                    cPackage.IsServerApplication = StringComparer.OrdinalIgnoreCase.Equals(GetAttributeValue(cPackageNode, "isolation"), "server");
                    cPackage.IsRunWhenIdle = StringComparer.OrdinalIgnoreCase.Equals(GetAttributeValue(cPackageNode, "run_when_idle"), "true");
                    cPackage.IsQueued = StringComparer.OrdinalIgnoreCase.Equals(GetAttributeValue(cPackageNode, "queued"), "true");
                    cPackage.IsQueueListening = StringComparer.OrdinalIgnoreCase.Equals(GetAttributeValue(cPackageNode, "queue_listening"), "true");

                    // register to status changed event
                    cPackage.StatusChanged += this.PackageStatusChanged;

                    // files
                    XmlNodeList cFilesNodes = cPackageNode.SelectNodes("./files/*"); ;
                    if (null == cFilesNodes) throw (new Exception("Invalid configuration, no files defined in package.\n" + cPackageNode.InnerXml));
                    if (0 == cFilesNodes.Count) throw (new Exception("Invalid configuration, no files defined in package.\n" + cPackageNode.InnerXml));

                    int iIndex = 0;
                    cPackage.Files = new string[cFilesNodes.Count];

                    foreach (XmlNode cFileNode in cFilesNodes)
                    {
                        string sFileName = GetAttributeValue(cFileNode, "name");
                        if (null == sFileName) throw (new Exception("Invalid configuration, file name attribute not found.\n" + cPackageNode.InnerXml));

                        cPackage.Files[iIndex] = File.Exists(sFileName) ? sFileName : Path.Combine(WorkingDirectory, sFileName);
                        iIndex++;
                    }


                    // components
                    XmlNodeList cComponentsNodes = cPackageNode.SelectNodes("./components/*"); ;
                    foreach (XmlNode cComponentsNode in cComponentsNodes)
                    {
                        string sComponentName = GetAttributeValue(cComponentsNode, "name");
                        if (null == sComponentName) throw (new Exception("Invalid configuration, component name attribute not found.\n" + cPackageNode.InnerXml));

                        // new package
                        Component cComponent = new Component();
                        cComponent.Name = sComponentName;

                        cComponent.Transactions = (COMAdminTransactionOptions)int.Parse(GetAttributeValue(cComponentsNode, "transactions", "3"));
                        cComponent.Synchronization = (COMAdminSynchronizationOptions)int.Parse(GetAttributeValue(cComponentsNode, "synchronization", "2"));
                        cComponent.JIT = StringComparer.OrdinalIgnoreCase.Equals(GetAttributeValue(cComponentsNode, "jit", "true"), "true");
                        cComponent.ObjectPooling = StringComparer.OrdinalIgnoreCase.Equals(GetAttributeValue(cComponentsNode, "pooled"), "true");
                        cComponent.ConstructorString = GetAttributeValue(cComponentsNode, "constructor_string");

                        // register to status changed event
                        cComponent.StatusChanged += this.ComponentStatusChanged;

                        cPackage.Components.Add(sComponentName, cComponent);
                    }

                    // add to collection
                    this.Packages.Add(sName, cPackage);
                    // cleanup
                    cFilesNodes = null;
                    cComponentsNodes = null;
                }
            }
            catch (Exception e)
            {
                bResult = false;
                StatusChanged(this, "Error loading configuration, " + e.Message + "\n" + e.StackTrace);
            }
            finally
            {
                cXmlDocument = null;
                cPackagesNodes = null;
            }
            return (bResult);
        }

        public bool Deploy()
        {
            bool bResult = true;

            try
            {
                foreach (KeyValuePair<string, Package> cIterator in this.Packages)
                {
                    Package cPackage = cIterator.Value;

                    this.StatusChanged(this, "\nDeploying " + cPackage.Name);

                    cPackage.Shutdown();

                    cPackage.Uninstall();

                    cPackage.Install();

                    // cleanup
                    cPackage = null;
                }
            }
            catch (Exception e)
            {
                bResult = false;
                this.StatusChanged(this, "Deployment error. " + e.Message);
            }

            return (bResult);
        }

        #endregion

        #region events

        private void PackageStatusChanged(object Source, string Description)
        {
            // bubble event
            this.StatusChanged(Source, Description);
        }

        private void ComponentStatusChanged(object Source, string Description)        
        {
            // bubble event
            this.StatusChanged(Source, Description);
        }

        public event InstallEventHandler StatusChanged;

        #endregion

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United States United States
Technologist & Executive.

Specializes in .NET, COM and the gray material between them. Intimately familiar with most MS technologies.

Developing software for a living for the last 10 years, focusing on web based enterprise software as a service for the last 8.

Comments and Discussions