Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change ProgID of a COM class

Tags:

c#

com

progid

I'm creating a COM component in C#. When it is installed, its ProgID is represented as its <Namespace>.<Classname>. But I want to change it to <Vendor>.<ClassName>.<VersionNumber>.

How can I do this in C#. I'm using Visual Studio 2010.

like image 407
Omer Avatar asked Jul 22 '14 09:07

Omer


2 Answers

MS claims:

ProgIds are automatically generated for a class by combining the namespace with the type name, separated by a dot.

This is not true, since in my experience ProgIds are combined from the project name and the class. Since the default namespace is the name of the project, the claim of MS seems to be true, but if you change the name of the namespace, the ProgId won’t change accordingly.

MS continues:

This can produce an invalid ProgId however, as ProgIds are limited to 39 characters and can contain no punctuation other than a period [I think: only one period]. In such case, a ProgId can be manually assigned to the class using ProgId Attribute.

So, it seems to me, that you can only change the ProgId in such a case, in normal cases setting the ProgId is useless, it will always be ProjectName.ClassName.

In the following example, I tried a ProgId of Dietrich.Math.ClassName by choosing Dietrich.Math as the project name, but without success: Dietrich.Math got changed to Dietrich_Math. As expected, the ProgId attribute is ignored by .NET and the ProgId is still set to Dietrich_Math.Arithmetic.

using System;
using System.Runtime.InteropServices;

namespace Dietrich.Math
{
  [ComVisible(true), Guid("B452A43E-7D62-4F11-907A-E2132655BF97")]
  [InterfaceType(ComInterfaceType.InterfaceIsDual)]
  public interface IArithmetic
  {
    int Add(int a, int b);
  }

  [ComVisible(true), Guid("17A76BDC-55B7-4647-9465-3D7D088FA932")]
  [ProgId("SimpleMath.Whatever")]
  [ClassInterface(ClassInterfaceType.None)]
  public class Arithmetic : IArithmetic
  {
    public int Add(int a, int b) { return a + b; }
  }
}
like image 82
Dietrich Baumgarten Avatar answered Nov 14 '22 09:11

Dietrich Baumgarten


I think user @Bond had the right idea. Unfortunately @Bond did not leave an example. Here is an example of using ProgId...

using System;
using System.Runtime.InteropServices;

namespace EncryptionCOMTool
{
    [ComVisible(visibility:true)]
    [Guid(guid: "4a69e3ce-7cf8-4985-9b1a-def7977a95e7")]
    [ProgId(progId: "EncryptionCOMTool.EncryptDecrypt")]
    [ClassInterface(classInterfaceType: ClassInterfaceType.None)]
    public class EncryptDecrypt
    {
        public EncryptDecrypt()
        {

        }

        public string Encrypt(string input)
        {
            return "some encrypted value";
        }

        public string Decrypt(string input)
        {
            return "some decrypted value";
        }
    }
}

since attribute ProgId requires a string for input, you can place anything you like there including a vendor name. For code maintenance, you may elect to keep the ProgId same as namespace.class name. To do this, but use the vendor name you would need to change the namespace of the class to include the vendor name, and for completeness also change the default namespace in the project properties too.

like image 2
barrypicker Avatar answered Nov 14 '22 07:11

barrypicker