【问题标题】:How do I set the constructor string of a COM+ component from .NET?如何从 .NET 设置 COM+ 组件的构造函数字符串?
【发布时间】:2008-11-19 16:16:17
【问题描述】:

我正在尝试从 C# 应用程序以编程方式设置 COM+ 组件的构造函数字符串。我在网上找到了下面的示例代码,但是它抛出了一个异常:

        COMAdminCatalogCollection Components;
        COMAdminCatalogClass Catalog = new COMAdminCatalogClass();
        string strConstr;
        string ApplicationName = "ApplicationName"; // case sensitive
        string CompName = "MyComponent.ProgID";
        COMAdminCatalogCollectionClass Applications = (COMAdminCatalogCollectionClass)Catalog.GetCollection("Applications");
        Applications.Populate();
        // find the correct application
        foreach (COMAdminCatalogObjectClass AppObject in Applications)
        {
            if (AppObject.Name == ApplicationName)
            {
                // find matching component
                Components = (COMAdminCatalogCollectionClass)(Applications.GetCollection("Components", AppObject.Key));
                Components.Populate();
                foreach (COMAdminCatalogObjectClass CompObject in Components)
                {
                    if (CompObject.Name.ToString() == CompName)
                    {
                        CompObject.get_Value("ConstructorString").ToString();
                        CompObject.get_Value("ConstructionEnabled").ToString();
                    }
                }
            }
        }

当我运行此代码时,我在第 6 行得到以下异常:

无法将类型为“System.__ComObject”的 COM 对象转换为类类型“COMAdmin.COMAdminCatalogCollectionClass”。进入 CLR 且不支持 IProvideClassInfo 或未注册任何互操作程序集的 COM 组件将包装在 __ComObject 类型中。这种类型的实例不能转换为任何其他类;但是,只要底层 COM 组件支持对接口的 IID 的 QueryInterface 调用,它们就可以转换为接口。

知道我哪里出错了吗?或者有更简单的方法吗?

【问题讨论】:

  • 你到底想在这里实现什么?
  • 我想为 COM+ 组件设置构造函数字符串。我意识到这段代码实际上并不会设置它,但我想先尝试显示字符串,我什至还做不到。

标签: .net com+


【解决方案1】:

我找到了避免异常的方法。我可以利用 VB.NET 的可选弱类型来删除所有强制转换和几个变量声明类型,而不是在 C# 中执行此操作。生成的代码如下所示:

    Dim Components As COMAdminCatalogCollection
    Dim Catalog As New COMAdminCatalogClass()
    Dim ApplicationName As String = "ApplicationName"
    Dim CompName As String = "MyComponent.ProgID"
    Dim Applications = Catalog.GetCollection("Applications")
    Applications.Populate()
    For Each AppObject In Applications

        If (AppObject.Name = ApplicationName) Then

            Components = (Applications.GetCollection("Components", AppObject.Key))
            Components.Populate()
            For Each CompObject In Components

                If (CompObject.Name.ToString() = CompName) Then
                    CompObject.Value("ConstructorString") = "Some new value"

                    Components.SaveChanges()
                End If

            Next
        End If
    Next

这是 VB 和 C# 显着不同的一种情况,了解这些内容确实有助于您为工作选择正确的工具。

【讨论】:

    【解决方案2】:

    我确信你已经顺利通过了这个,但我目前正在开发一个需要类似功能的项目,我能够使用 .NET 和 PowerShell 提出一个解决方案来做到这一点。首先,我在 C# 中创建了一个自定义 cmdlet,如下所示:

    using COMAdmin;
    using System;
    using System.Runtime.InteropServices;
    using System.Management.Automation;
    
    namespace COMAdminModule
    {
        // Name the cmdlet
        [Cmdlet("Set", "COMConstructorString")]
        public class SetCOMConstructorSting : PSCmdlet
        {
    
            // App name Parameter
            private string comAppName;
    
            [Parameter(
                Mandatory = true,
                ValueFromPipelineByPropertyName = true,
                ValueFromPipeline = true,
                Position = 0,
                HelpMessage = "Name of COM+ Application"
                )]
    
            [Alias("App Name")]
    
    
            public string COMApp
            {
                get { return comAppName; }
                set { comAppName = value; }
            }
    
    
            // App Component name
            private string componentName;
    
            [Parameter(
                Mandatory = true,
                ValueFromPipelineByPropertyName = true,
                ValueFromPipeline = true,
                Position = 1,
                HelpMessage = "The name of the Component that will receive a new Constructor string"
                )]
    
            [Alias("Component Name")]
    
    
            public string ComponentName
            {
                get { return componentName; }
                set { componentName = value; }
            }
    
    
            // Constructor String
            private string constructorString;
    
            [Parameter(
                Mandatory = true,
                ValueFromPipelineByPropertyName = true,
                ValueFromPipeline = true,
                Position = 2,
                HelpMessage = "The new Constructor string"
                )]
    
            [Alias("Constructor String")]
    
    
            public string ConstructorString
            {
                get { return constructorString; }
                set { constructorString = value; }
            }
    
    
            // Provides a one-time, preprocessing functionality for the cmdlet
            protected override void BeginProcessing()
            {
                base.BeginProcessing();
            }
    
            // Provides a record-by-record processing functionality for the cmdlet
            protected override void ProcessRecord()
            {
                string working = "Setting the constructor string " + constructorString;
                working = " to the Component " + componentName;
                working += " for the COM App " + comAppName;
    
                WriteObject(working);
    
                setConstructorString(comAppName, componentName, constructorString);
            }
    
            // Provides a one-time, post-processing functionality for the cmdlet
            protected override void EndProcessing()
            {
                base.EndProcessing();
            }
    
    
    
    
            //Add component method
            private void setConstructorString(string comAppName, string componentName, string constructorString)
            {
                ICOMAdminCatalog2 oCatalog = null;
    
                try
                {
    
                    //Create the comAdmin object
                    oCatalog = (ICOMAdminCatalog2)Activator.CreateInstance(Type.GetTypeFromProgID("ComAdmin.COMAdminCatalog"));
    
                    //Get the comApps
                    ICatalogCollection comApps = (ICatalogCollection)oCatalog.GetCollection("Applications");
                    comApps.Populate();
    
    
                    foreach (ICatalogObject app in comApps)
                    {
    
                        //Find the comApp
                        if (app.Name.ToString().Equals(comAppName))
                        {
                            //Get the Components
                            ICatalogCollection components = (ICatalogCollection)comApps.GetCollection("Components", app.Key);
                            components.Populate();
    
    
                            foreach (ICatalogObject component in components) 
                            {
                                //Find the component
                                if (component.Name.ToString().Equals(componentName))
                                {
                                    // Set the constructor string
                                    component.set_Value("ConstructorString", constructorString);
    
                                    components.SaveChanges();
    
                                    break;
                                }
    
                            }
    
                            break; 
                        }
    
                    }
    
                }
                catch (Exception e)
                {
                    WriteObject(e.Source);
                    throw;
                }
            }
        }
    }
    

    然后将该模块导入 PowerShell 脚本并按如下方式运行:

    PS C:\Windows\system32> Import-Module "<dll path>"
    
    PS C:\Windows\system32> Set-COMConstructorString <Application Name> <Component Name> <Constructor String>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 1970-01-01
      • 2019-05-13
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      • 2019-01-18
      相关资源
      最近更新 更多