2008-11-19 4 views
0

J'essaie de définir par programme la piqûre du constructeur d'un composant COM + à partir d'une application C#. J'ai trouvé le code exemple suivant en ligne, mais il renvoie une exception:Comment définir la chaîne de constructeur d'un composant COM + à partir de .NET?

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

Quand je lance ce code, je reçois l'exception suivante sur la ligne 6:

Impossible de jeter l'objet COM de type ' System .__ ComObject 'au type de classe' COMAdmin.COMAdminCatalogCollectionClass '. Les composants COM qui entrent dans le CLR et ne prennent pas en charge IProvideClassInfo ou qui n'ont aucun assembly interop enregistré seront enveloppés dans le type __ComObject. Les instances de ce type ne peuvent pas être converties en une autre classe; Cependant, ils peuvent être castés en interfaces tant que le composant COM sous-jacent supporte les appels QueryInterface pour l'IID de l'interface.

Une idée où je me trompe? Ou y a-t-il un moyen plus facile de le faire?

+0

Que voulez-vous exactement à atteindre ici? – Grzenio

+0

Je veux définir la chaîne de constructeur pour un composant COM +. Je me rends compte que ce code ne le définira pas, mais je voulais essayer d'afficher la chaîne en premier, et je ne peux même pas le faire. –

Répondre

2

J'ai trouvé un moyen d'éviter l'exception. Plutôt que de le faire en C#, je peux tirer parti du typage faible optionnel de VB.NET pour supprimer tous les castings et quelques types de déclarations de variables. Le code résultant ressemble à ceci:

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 

C'est une situation dans laquelle VB et C# diffèrent de manière significative, et sachant que ces choses vous aide vraiment à choisir le bon outil pour le travail.

0

Je suis sûr que vous avez bien passé cette étape, mais je travaille sur un projet qui nécessite actuellement une fonctionnalité similaire et j'ai été en mesure de trouver une solution en utilisant. NET et PowerShell pour le faire. D'abord, je créé une applet de commande personnalisée en C# comme suit:

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

Et puis importer ce module dans un script PowerShell et exécuter comme suit:

PS C:\Windows\system32> Import-Module "<dll path>" 

PS C:\Windows\system32> Set-COMConstructorString <Application Name> <Component Name> <Constructor String> 
Questions connexes