Problems with releasing COM-Objects

Scott

Member
Joined
Dec 22, 2004
Messages
5
HI

I have a program where I use the following code to login.

Dim objLogin As ACDB.Login
Dim objRuntimeSession As ACDB.RuntimeSession

objLogin = New ACDB.Login()
objLogin.Login("", "")
objLogin.ValidateUser("Module.ABC")
objRuntimeSession = objLogin.RuntimeSession

After the last command, the number of the available licenses is decremented by 1.
But when I terminate my program, it lasts about 40 minutes until the license is available again.
But in VB6 the license is available immediately after terminating the program, when I use the same methods to login.
A special method to logoff does not exist.
I tried to release the objects with Marshal.ReleaseComObject(objLogin) and
Marshal.ReleaseComObject(objRuntimeSession).
The reference counter of the 2 RCWs is then 0, but it doesnt change anything.

Can anyone help me ?

Thanks
 
This can be tricky/stubborn stuff. I find that the Marshal.ReleaseComObject() command to be tricky at best. It doent do any good unless you use it for absolutely every COM Object that you use and its very easy to slip up and miss one.

I find that its easier to code normally and then if you have a COM Object or Resource, say called "MyCOMObject", then it might look like this:
Code:
MyCOMObject.Close  Or .Quit or whatever is required.
MyCOMObject = Nothing
CG.Collect
If really a stubborn case, you can try this:
Code:
MyCOMObject.Close  Or .Quit or whatever is required.
MyCOMObject = Nothing
CG.Collect
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
Good luck, I have my fingers crossed for you..!
 
My COM object doesnt have a .Close or .Quit method.
I tried :

Code:
MyCOMObject = Nothing
CG.Collect
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
but with the same result.
Im wondering why the objects arent released in .Net when I terminate the program because in VB6 they are.
 
Well it sounds like you are doing everything right. You are calling Marshal.ReleaseComObject() on both relevant objects and getting a confirmation that the reference count = 0. Yet it fails... :(

It doesnt look to be the case, but are either of these Methods actually functions returning an Object?:
Code:
objLogin.Login("", "")
objLogin.ValidateUser("Module.ABC")
Im sure not, but I had to ask... if either does return an object, then that would cause a hang (believe it or not). Well, youve tried everything it seems the only thing I can think of is to throw everything at it at once:
Code:
    Sub MySub()
        Dim objLogin As ACDB.Login
        Dim objRuntimeSession As ACDB.RuntimeSession

        objLogin = New ACDB.Login
        objLogin.Login("", "")
        objLogin.ValidateUser("Module.ABC")
        objRuntimeSession = objLogin.RuntimeSession

        Marshal.ReleaseComObject(objRuntimeSession)
        Marshal.ReleaseComObject(objLogin)

        objRuntimeSession = Nothing
        objLogin = Nothing

        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub
If this fails, then the only other idea I have is to make use of the Process.GetProcessByName() method and then call Process.Kill.

Very ugly, but this may be the only way if we cant get it to release via normal COM Interop commands...
 
I have now tried this:

Code:
  Private Sub LogIn()
        Dim objLogin As ACDB.Login
        Dim objRuntimeSession As ACDB.RuntimeSession
        objLogin = New ACDB.Login()
        objLogin.Login("", "")
        objLogin.ValidateUser("Module.Finish")
        objRuntimeSession = objLogin.RuntimeSession

        Dim proc As Process = proc.GetCurrentProcess
        Marshal.ReleaseComObject(objRuntimeSession)
        Marshal.ReleaseComObject(objLogin)
        objRuntimeSession = Nothing
        objLogin = Nothing
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.WaitForPendingFinalizers()
        proc.Kill()
 End Sub
The 2 methods dont return an object.
Code:
Public Sub Login(Optional ByVal strRes1 As String = "", Optional ByVal strRes2 As String = "")

Public Sub ValidateUser(ByVal strUniqueID As String)
I had the idea to write a DLL in VB6 with a function Login which contains the code to login and returns the RuntimeSession object and a method Logout in which I set everything to Nothing but it doesnt work too.

I have also tried Application.Exit and Environment.Exit.
It seems that the objects are only released when the code is written with VB6 and the application is terminated because even in VB6 when I set everything to Nothing, it doesnt change anything. Perhaps the developers didnt consider the possibility that someone could use .Net because I contacted the support and they also seem rather helpless. But I cant use VB6 because I dont have a valid license. :confused:
 
Ok, I slightly mis-understood... So this object is preventing your own App from closing down?? That is pretty amazing, as well as distressing. :(

Im stunned that neither Process.Kill nor Application.Exit allowed your routine to exit. Can you kill it "manually" from the Task Manager?? Or does it simply hang for eth 40 mins you were talking about (or until you reboot)?

I think Im running out of ideas though...
 
Last edited by a moderator:
I dont think you mis-understood me, perhaps my last post was a bit confusing.
I have no problem to close down my App, I used Application.Exit and Environment.Exit only because I thought when I close down the App in this way the objects would perhaps be released and the license would be available again so that another workstation can use it.
Perhaps I reference a COM object that accidentally does not release yet another COM object properly. So when I release a COM object, it continues to stay in memory because it doesnt release the second COM object.

Thanks for the help
 
Last edited by a moderator:
It sounds like to me that the company that makes this needs to make a .LogOff() method. Maybe you should suggest it? It shouldnt be very hard for them -- basically whatever they have in their Class_Terminate() Event would need to be put within this .LogOff method, that way it could be called explicitly, directly.

Im sorry couldnt do better... :(
 
Last edited by a moderator:
Back
Top