How to use a COM object in Visual Basic 2013

I have a COM object that has numerous properties which are set prior to calling one if its methods. I have been using the following code to open/start the COM object. This code does not work inside a Try Catch block.

Is there a better way than trying to catch the error if the GetObject fails.

I would like to find a way to create the object inside the Try Catch block. I was thinking of Process.Start but I could not get it to work.

Existing Code:
Dim objWP as Object
On Error Resume Next
objWp = GetObject(, "WPProjectX.Class1")
If Err.Number = 429 Then
     objWp = CreateObject("WPProjectX.Class1")
End If
On Error GoTo 0
WIth objWP
  .Connection = "Servername, etc"
  .LotNo = "XXXXXX"
  s = .SpecSheet
end with

Open in new window

Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jacques Bourgeois (James Burger)PresidentCommented:
You can try setting a reference to the COM dll.

In the Solution Explorer, click on MyProject for your project. Go to the References tab, then Add, then the COM tab, and activate your dll that should be in there somewhere.

You can then use the more modern way of using your object:

     Dim objWP as WPProjectX.Class1
     objWp = New WPProjectX.Class1

This will be a better approach, because IntelliSense will be able to tell you about the properties, methods and parameters used to work with the class. The compiler will be able to validate what you do and catch errors that would otherwise end up being runtime errors.

Note that this not work with all COM dlls. Older ones cannot work with New and can be instiated only with GetObject or CreateObject.

You might also end up, in both techniques, with problems due to the differences between .NET and COM. Things such as the fact that the Variant data type does not exist in .NET. Some basic types have also changed, and you have to take that in consideration. As an example, what was a Long in COM is an Integer in .NET. The Long in .NET is bigger than in was and can cause problems if sent to a COM objects. Your .NET code should adapt to such situations in order to work as intended.
mpdillonAuthor Commented:
Ok. Good advice. I do have just one follow up question. How do I close that object.

More background than you probably need but I think it is relevant.

I wrote the COM object in VB6 over 10 years ago. it is an ActiveX exe. This COM is used by dozens of other programs.  My experience has been that early binding has led to me having to remove the exe from the calling application when a Property or Method is changed in the COM exe. After removing the EXE from the calling application, it has to be added back to the program. The program recompiled. Uninstalled on the user's computers and reinstalled. These changes to the COM are infrequent, 2 or 3 a year now. However with early binding it is a huge task to update all the users computers without disrupting their work. Late binding seems to eliminate most of the problems associated with changing the COM object.

In this instance it will be part of a Web Service. I will just have to remember/document that I have to tinker with the web service when the COM is changed.

That is the explanation for why I was using Late Binding. Now onto my follow up question.

The COM is used not only for this web service but was developed for all the users at this location. Initially, the COM object would not always close completely on the users computer. The user's systems memory would become completely consumed by multiple instances of this COM object. I became very sensitive to the need to close the object and get it out of memory. There were some settings in the VB6 COM project that needed to be set. "instancing - GlobalMultiUse" and "Persistable - 0 NotPeristable". And I had to add extra code to the Methods within the COM object to ensure the forms were completely closed.

So my question about disposing of the object comes from a lot of history. What is the proper way to dispose of this object. Neither Dispose nor Close are available in Intelisense.

Jacques Bourgeois (James Burger)PresidentCommented:
If I understand well, you will have a .NET web service that will use your COM ActiveX in the backbround.

As far as the COM object is concerned, although I spent the 90's working with VB6, I have not touched it for 15 years. I have never created an ActiveX exe (only dll) and have never encountered the kind of problem that you explain. So on that side of things, I am completely out of touch.

I have worked a lot with Office application from .NET however, and I can give you some hints on the .NET side.

You might be stuck with late binding. The versioning problem does not seem to be too much of a concern when dealing with COM dlls, but is often present when dealing with a COM exe. For one, Office applications are very sensitive to that. Unless they have a good control over the installation and are sure that the version of Office they use will be there for a long time, most programmers will use late binding when dealing with Office. It looks as if you might be faced with that limitation.

But maybe not. Because you are dealing with a web service, and because a web service is typically installed only on one station, simply updating the reference to a newer version of your COM application and recompiling the web service might be sufficient. You do not have to make any change on the client side. And although I am not an expert on that side of things (network administrators do it for me), I think that you can update a web service while it is in use.

There can be specific problems disposing of COM objects from .NET applications. If you already had these when everything was COM, I would bet that these might become worse from the .NET point of view. The main reason is that .NET uses memory in a very different way. It does a very good job with .NET components, it's the framework that manages the memory. In COM, each application manages its memory (although it was mostly hidden in VB6). This difference can lead to conflicts.

A Close or Dispose method does not come automatically. It needs to be coded.

At the application level, a Close method would terminates the application and is supposed to release all the objects it created. In VB6, this was done through code built into the application and generated by the compiler. For different reasons, such as circular references, it did not always work.

In .NET, the equivalent is Application.Exit. And the framework manages its own memory pool instead of leaving the applications do it as was the case in COM. The application thus does not usually have any code for the cleanup, the framework handles it. This solves most of the problems that could occur in COM. But that is only when you are dealing with .NET wall to wall. When you mix interactions between .NET, Windows resources (file handles, timers, etc.) and with COM, each does its own part in releasing the section of memory it is responsible for.

At the class level, in COM and .NET, setting a variable to Nothing or letting it "die" through an End Sub or End Function is the most usual way to go to get rid of an object an release its memory. Most of the time, the programmer of the class has nothing to do.

But In some complex situations, the programmer of the class needed to add some code.

In COM, it was done through the Terminate event to finish the cleanup, that was automatically provided with all the classes.

In .NET, this is done through a Dispose method. Close is sometimes added, but for the sake of old habits. Close typically calls Dispose, and is there only because programmers are used to close forms, files and database connections. But that Dispose method does not come automatically. It must be coded in the class, by implementing the IDisposable interface. So you will not see a Dispose or Close method in IntelliSense unless the programmers saw the need to create one.

When dealing with COM objects from .NET, calling the closing method (when available), setting the variable to Nothing or letting it go out of scope is often sufficient, as is usually the case when dealing with .NET objects. But if you already had problems releasing the memory when everything was COM, you will probably only add to that problem from .NET. That is because you have both a variable that lives under the way .NET manages its memory, and and object that lives in the COM world. There are sometimes conflicts in the way both do their work.

As an example, in Excel you might expect the application to keep running as a process after you call Quit from .NET. But not always. As an example, in my experience, the problem to occurs more often if you use a variable to reference a Worksheet instead of accessing it through the application object as in the following: App.Workbooks(1).Worksheets(5). Excel itself is good at cleaning its objects, but when you need to dispose of a Worksheet through a .NET object, things might not work as intended. The more you use variables instead of direct interaction, the more you might end up with Quit not working. You might simply refrain from using variables when possible, but doing so gives you a direct pointer to the worksheet. This gives a very sensible boost to performance over the Object.Object.Object... that needs to resolve multiple references.

When you end up with objects that stick in memory, then it is up to you to intervene and release the COM objects that were used. This can be done by using the ReleaseComObject method in .NET. This can be a lot of work in complex situations, because the objects usually need to be released in a specific order (the Worksheet object before the Workbook object before the Application object).

Expect some trials and errors on that side of things.


And back to your original question. By rereading it, GetObject jumps to my face. I haven't use that in years, so it skipped right through my thoughts when I first gave a look at your code.

If I remember well, GetObject was a way to reuse an already existing instance of an application, while CreateObject always created a new instance.

Well, some of this old stuff does not work well in .NET, so that might be why the thing does not work in a Try...Catch.

We have different ways to do that in .NET. Not sure if it could be used in your situation, but...

You declare a static (Shared in VB) variable at the class level. A static variable is shared by all the instances of the class. Initialize it once and reuse it everywhere. It will still live as long as the application in which it is declared is running. Your code could possibly go something like the following:

Shared objWP as Object

    If objWP Is Nothing then
          // objWp = CreateObject("WPProjectX.Class1")
          'or, with a early binding
          objWp = New WPProjectX.Class1()
    End If
Catch ex As COMException
   'Handle COMException
Catch ex As Exception
   'Handle unexpected exception
End Try
If Err.Number = 429 Then
     objWp = CreateObject("WPProjectX.Class1")
End If
On Error GoTo 0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mpdillonAuthor Commented:
I am very appreciative of your lengthy answer. I know it took a long time to compose. I understand very little of memory management in .net or VB6. This was most helpful.
I will try your suggestion.
Thanks again,
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.