-1

I have a construct of a .NET implementation of some utility and a .WSC script that instantiates the .NET object. The goal is to eliminate the WSCscript and to instantiate and call the .NET implementation directly. But this discovered a naming problem.

The class defined in the WSC contains several methods. One of these methods is Finalize(). The function name is reserved in .NET since it is used for the life time and GC management. Therefore the WSC calls a .NET function with a different name:

<?xml version="1.0"?>
<component>
  <public>
    <method name="Finalize"/>
  </public>
  <object id="wrapper" progid="JS.Wrapper"/>

  <script language="JScript">
    <![CDATA[
      // Processes last required steps and closes all logs
      function Finalize() {
         return wrapper.Finish();
      }
      // Any other function
      function Foo() {
        wrapper.Foo();
      }
    ]]>
  </script>
</component>

The .NET class implements the Finish function:

[ComVisible(true)]
[ProgId("JS.Wrapper")]
public class MyCom
{
    // Processes last required steps and closes all logs
    public void Finish()
    {
    }

    public void Foo()
    {
    }
}

There are thousands of scripts that call all the Foo() and Bar() functions. And most of them also calls the Finalize function. Therefore it is impossible to change the function name at the COM interface.

  • How can the function Finish be made COM-Visible with the name Finalize?
  • Is there a way to implement two Finalize functions, one for .NET run-time and one as exported at the COM interface.
  • Is it possible to implement a COM interface explicitly, i.e. make a custom implementation of the COM interface?

There is an attribute ComAliasName that can be used to make an property, indexer, field, param, or return visible with a an alias. But it can't be used for a method name. How can a method made visible as an alias?

harper
  • 13,345
  • 8
  • 56
  • 105
  • You can call the C# method `finalize` all lowercase (for example) so it won't interfere with the finalizer. The underlying IDispatch implementation (that allows you to use a C# COM object from script clients) is case-insensitive anyway. Corollary question: why do you need the finalizer on .NET COM objects? – Simon Mourier Apr 04 '19 at 15:21
  • @SimonMourier Sorry, I don't understand your comment completely. What module should call a `finalize`? Under what circumstances should it do that? – harper Apr 05 '19 at 06:31
  • You could name (not call, sorry) the method `finalize` in the MyCom class instead of `Finish`. – Simon Mourier Apr 05 '19 at 06:42
  • @SimonMourier I have a different experience with the case-sensitivity of the COM-visible interface. If the calling script invokes the method `foo` and the .NET class has implemented `Foo`, an error is reported: "Object doesn't support this property or method' 0x800A01B6. If the .NET class implements a `finalize` method, how can a call of `Finalize` in the script invoke the `finalize` method. – harper Apr 05 '19 at 07:30
  • Strange. Here is myproject where it does work: https://1drv.ms/u/s!AsmmEDGvydk2lCpnt3Lop93BCA8K can you test it? – Simon Mourier Apr 05 '19 at 07:47
  • Explicitly declaring the exposed interface(s) of a [ComVisible] class is always a good idea. No problem declaring a Finalize() method, the class can simply use an explicit interface implementation to give it a different name. Code analysis still produces a mild warning about it, safe to ignore. – Hans Passant Apr 05 '19 at 08:32

1 Answers1

0

The method Finalize can be exposed by defining explicitly the COM interface.

public interface IMyCom
{
    // Processes last required steps and closes all logs
    void Finalize();
    void Foo();
}

It's important to choose the ClassInterfaceType.None in the implementing .NET class. The implementation in the .NET class should specify the interface that is implemented. With the scope prefix IMyCom the compiler can distinguish between the name of the method at the COM interface and some .NET CLR internal names. The makes it unnecessary to use a different method name and to create an alias.

[ComVisible(true)]
[ProgId("JS.Wrapper")]
[ClassInterface(ClassInterfaceType.None)]
public class MyCom : IMyCom
{
    // Explicitly specify the scope of the Finalize method.
    void IMyCom.Finalize()
    {
    }

    void IMyCom.Foo()
    {
    }
}

This approach makes it also clear that this is the implementation of a COM interface method.

harper
  • 13,345
  • 8
  • 56
  • 105