ActiveX communication - vb6

I'm developing an ActiveX EXE that exposes an specific class to a third-party software. This third-party software instanciates an object of this class and uses its methods.
Strangely, this third-party software destroys its object of my exposed class as soon as it calls an specific method, but I have no idea why this happens.
The only clue I have is that this method is the only one that returns a value. All the other ones are simple 'subs' that do not return any value, and when they are called nothing wrong happens.
I'm using VB6.
Do you guys have any idea of why it's happening?

Your object gets "destroyed" when the last reference to it is deleted. Thats normal COM behavior. Or is your object dying unexcepted and the third-party app is getting an activex error?
Some more questions:
I don't know what you mean with "data server"?
Do you have access to the source code of the third-party app?
Are you sure, the third-party app holds a reference to your object?
Is your objects Class_Terminate Method called?
EDIT:
OK, when Class_Terminate is getting called its obvious, that the third-party app has dropped its reference to your object.

As Jan stated in COM it is normal, that your object is terminated if no one is referencing it. If you would like to do some kind of caching (e.g. keep the DB connection open), you can use a global variable defined in a bas-module.
basGlobal.bas
Global AGlobalVariable As Object
Connector.cls
Public Function GetFoo() As Object
If AGlobalVariable Is Nothing then
Set AGlobalVariable = ...
End If
Set GetFoo = AGlobalVariable
End Function

Related

Using CSOM in VBS [duplicate]

I've compiled C# code into a DLL, but have little experience with them. My C# code contains a class HelloWorld with a static method Print(). I'd like to use this DLL in VBScript to call the method Print(). I know this is base, but I'm using this as a test for a larger scale project that will be compiled to DLL in the end. What's the declare look like for that and how would the method call look?
Important: Both methods will work only if the DLL exposes a COM interface.
If your dll is registered with the system, use CreateObject with it's ProgID.
Set myObject = CreateObject("MyReallyCoolObject.HelloWorld")
myObject.Print
If your object is not registered on the system, use GetObject with a path to the file containing your object. Make sure your object exposes the proper interface. (The second parameter is optional. Here you can provide a class name if your object exposes more than one.)
Set myObject = GetObject("C:\some\path\helloworld.dll", "appname.HelloWorld")
myObject.Print
I think you might be looking for Registration-Free COM. This SO answer regarding the Microsoft.Windows.ActCtx should help specifically for VBScript.
Keep in mind that COM doesn't support static methods, so you'll have to make your Print method into an instance method.
How to call a .NET DLL from a VBScript

Xamarin Forms - calling a shared code method from the platform project

I have read the two other questions on SO regarding this and I wanted to know if there is a good solution for that now / best practice.
Long story short, we use an SDK which is written natively and we've wrapped it so that it works on Xamarin.Android and Xamarin.iOS. It has asynchronous callback methods. I need to call a method in the shared code when a callback is received in the Android project for instance.
There's a lot of info for doing the opposite - using DependencyService. How about in my scenario? Does anyone have experience with an app like this and what's the best approach to keep code clean and do this using MVVM?
The options I know are:
Using a static App instance - this is what we currently do.
MessagingCenter
Anything else?
Actually I've never seen anyone recommend usage of MessagingCenter for anything else than communication between ViewModels so I am not sure it is recommended here. Also, I need to know the sender object type so I need a reference to the class in the platform specific project.
I would recommend you to use messagingCenter to pass data or call method between shared project and platform project. You can just send a new object instead of the class in the platform specific project.
Also, have a look at using eventhandler as I mentioned in this answer may help someone who want to call from the shared project into the platform specific one.
BTW, I mean you can even pass an object as TSender if it is not necessary to use:
MessagingCenter.Send<Object>(new object(), "Hi");
MessagingCenter.Subscribe<Object>(new object(), "Hi", (sender) =>
{
// Do something whenever the "Hi" message is received
});

MS Access: Way to maintain persistent session across multiple Form Events?

Hopefully this is a simple question, though the solution may not be. In MS Access, is it possible to instantiate a VBA class in the application or database scope?
What I want to do is persist a WinHttp instance with the same lifetime as the application or database so that as various Form Event handlers call a web service, they can do so using a persistent session object.
If not, it seems like I'll always need to grab and persist the session state, particularly the JSESSIONID, before the current instance goes out of scope and then quietly put it back on the next instantiation. This is coming up because I really can't afford the authentication overhead on the client or the server.
What would be the recommended way to maintain a physical or virtual persistent session across multiple Form Events?
Yes, this certainly is possible. Just dim it in a module outside of any sub or function (without the New keyword)
Public winHttpObj As Object
Public Sub CreateWinHttpObj
Set winHttpObj = CreateObject("WinHttp.WinHttpRequest.5.1")
End Sub
You can refer to it from the same module, or from any other module by using the ModuleName.Variablename notation
If it's desirable is a whole different question.

How to implement global VB6 error handler?

The global VB6 error handler product referred to in the following link claims to "install a small callback hook into the VBE6 debugger":
http://www.everythingaccess.com/simplyvba/globalerrorhandler/howitworks.htm
I would like to implement this product myself because I would like more control over what it is doing. How is the above product likely to be achieving what it does?
The product you are looking at is a COM component. From the documentation that is available on the web site, it sounds like the COM component implements particular component classes. The first thing to do, if you already have the product, would be to fire up SysInternals procmon, run regsvr32 on the DLL, and figure out what component classes are implemented from the registry entries that are created. Once you know this, MSDN may be able to tell you what interfaces correspond to those component classes.
Microsoft developed a framework called Active Scripting that allows you to host a script engine and inject debugging capabilities. If one assumes that VB6 produces an exe that ties into that framework, you might be able to do:
Create a COM component that implements IApplicationDebugger
Implement IApplicationDebugger::onHandleBreakPoint to be able to respond to errors in the VB code
Read MSDN KB Q222966 to find out how to call back to VB from onHandleBreakPoint
It looks like the product injects the ErrEx class using IActiveScript::AddNamedItem. To provide the same behaviour, Implement IActiveScriptSite::GetItemInfo on the same COM component to return a pointer to an instance of (and the associated TypeInfo for) a COM component that implements the same interface as ErrEx. In your implementation of ErrEx.EnableGlobalErrorHandler you would do the following:
CoCreateInstance inproc Process Debug Manager
Cast reference to IRemoteDebugApplication
Register an instance of your IApplicationDebugger component using IRemoteDebugApplication::ConnectDebugger
I glossed over calling IActiveScript::AddNamedItem because I have no idea how you get a pointer to IActiveScript from a running process. Also, I don't know if creating a new instance of the Process Debug Manager will work, or if you somehow have to hook into an existing instance.
I apologize for the confusing explanation, missing information, and glossing over large parts of the process, but this is going waaay back...
You will want to read the Active Scripting APIs article at MSDN.

When does OnEndPage method run for object created indirectly by ASP (classic) page

I'm trying to debug an issue which may be due to a delay in running some cleaup code that's in an OnEndPage method.
I have a LoginPage class (in VB6) which is normally created directly by an ASP page. But in another case, an ASP page creates another VB object, which then does approximately this
Set oLoginPage = Server.CreateObject("LoginPage")
Call oLoginPage.DoLogout;
Set oLoginPage = Nothing
Some crucial cleanup is done in the OnEndPage method of LoginPage class, and it looks like this happens asynchronously, and with enough of a lag to cause problems.
Can anyone confirm that OnEndPage runs asynchronously, and might lag a bit? I've not been able to find any mention of this in documentation, just that objects are garbage collected "as soon as the reference count goes to zero." But that doesn't seem to be what's happening in my code.
This is a VB6 application called by an ASP page. It needs to run on multiple versions of IIS from 5.0 upwards.
Thanks.
O.K., it's simpler than I thought. Apparently the OnEndPage method is run by ASP after all the rest of the stuff on the page is finished. This applies even to VB objects created indirectly (that is, created by VB objects that were created by the ASP page), as long as they are created using Server.CreateObject().

Resources