MQL4 DLL Using Nugent and VB.net - vb.net

I'm putting together a dll for use with MQL4 using nugent and vb.net and it's going pretty good so far.
In my dll I am setting a flag when a condition is met so that I don't have to keep checking each time the function is called. This works fine but what I realize it that the flag is remaining set and in memory even if I remove the EA that created the dll from the chart.
The flag is declared within a function in the module as static.
If I close the terminal and then open it again the flag has gone and the process starts again.
How can I remove the dll from memory and release it's resources (the static variable) on removal of the EA?
I'm thinking it should maybe call a function in the deinit but I can't find any VB.net examples of a dll 'killing' itself.
Any ideas would be much appreciated.
Steve
Update: I just had a thought. Maybe the dll is not supposed to end on removal of the EA from the chart? Could it be like that by design? If so I can just set the flag to false manually I guess.
But wouldn't that mean that if I add the EA to the chart again there will be another instance of the dll?
If anybody has a definitive answer though that would be great.

DLLs to be used in MQL4 expose functions that can extend the functionality offered by MT4. From what i understand about DLLs, they DO NOT offer data retention. Like, in your case, when you call a function of the DLL in your MT4 code, the data is retained for the duration of that call. When you restart the EA, the data is gone and everything is back to default values.
Hope this helps.

Related

Invalid floating point operation while loading dll

I got a problem recently that when I added a code to a lib, which is used by a dll, the dll cannot be loaded. I get an exception "Floating point invalid operation at xxx". When I comment out the code it works. The code added is just straight forward like creating a TADOQuery object, add the sql statment and the parameters, then do an open, check value etc. Nothing suspicious. Now when I uncomment the code and comment another chuck of code in the unit elsewhere, it starts to work. So obviously the newly added code was just tripping the issue caused elsewhere.
Now this error happens when LoadLibrary() call is invoked. There is no attach code. The DllMain, just has a return 1. When this happens the assembly code is always at FSTP tbyte ptr doing a System::Variant::Clear().
Anyone has come across such issues? Any tips on how to debug is also appreciated.
PS: It could also be Embarcadero's compiler issue. I recently figured out that the assembly generated for a combination of assignment and comparison is incorrect. The only suspicion here is the lib that the dll uses is large. When I do a clean and build of the lib, the total lines shows 5.7m. Maybe there is some setting for large libs?
IDE-XE4, c++ builder
OS-Win 7
Thanks,
Mathew Joy
C++Builder and Delphi have different default FPU settings than, say, MSVC and the DLLs written in it.
It probably goes like this: After DllMain, certain exceptions are masked to be hidden. But before the first floating point operation in C++Builder code occurs, that exception is unmasked and the exception occurs.
This is a known problem with C++Builder/Delphi floating point and DLLs.

Testing for DLL references in VBA

First, apologies for the generic title - if anyone can suggest a better one, I'd be happy to change it, but right now, I have no clue where to start.
I have a workbook utilizing a DLL to access a data provider (Bloomberg), and the requirements to get it to work correctly are quite tricky. Furthermore, deployment is a nightmare, since users might need to reference the DLL themselves.
Naturally, I first check wether the library is referenced, before testing the library itself.
Here's my code (which is working as intended) :
Public Sub TestBloomberg()
Dim ref As Object
Dim fRef As Boolean
fRef = False
For Each ref In ThisWorkbook.VBProject.References
If ref.GUID = "{4AC751C2-BB10-4702-BB05-791D93BB461C}" Then
If Not ref.IsBroken Then
fRef = True
End If
End If
Next
If fRef Then
' In separate Sub to get around User-defined type error
Call TestBloombergConnection
ElseIf Not fRef Then
' warn user about missing reference
End If
End Sub
As you can see, if the reference to the DLL is set, I proceed checking if the library works as intended (this has a lot of external factors at play, such as wether the server-application is running, the user is logged in, etc.) You can think of this as a simple ON-ERROR-GOTO-wrapped call to the dll.
I am forced to move the actual test of the functionality to another sub, as called from the second if-block. If I have no (or a broken) reference to the dll, even though the library will not be called itself, I will get a User-defined Error. If I move the exact same code to another sub, it will work perfectly.
Finally, my question:
What happens when I run my VBA code, why do I get a (i think) runtime error during compile time? How can my code be so dependend on external factors, that it can't even get to the point of failing?
What this behavior demonstrates is that VBA compiles separate subroutines separately and at different times. I had a similar situation when I was trying to resolve references on behalf of the users (solving a versioning problem, which I got to work, but then abandoned as not worth the trouble).
When you are ready to enter a subroutine, it interprets only as much as it needs to, and you could get a compile time error then, even though to you it seems like you are at run time.
The error you are actually getting is probably a 429 Automation error or something similar. You would get that if you have a broken link (dll moved, deleted, or not registered). What I remember from my project, is that I could reliably handle it if a good reference was saved in the file, or no reference was saved, but if a bad reference was saved, the code had to be isolated similar to what you found. I think I had mine in a separate class, but the principle is the same.
I think this "interpret only as much as necessary" is considered a feature of VBA. You can run a certain section of code, even if you have compile errors elsewhere. This can be useful when you only have a partially written functions or other half-finished stuff, or if you open the file on a computer without some referenced software installed. It lets at least some of the functionality still work.

VB .NET, check if dll exists

In my VB .NET project, I have several functions that use unmanaged code from within winusb.dll. I tested the code on some machine which haven't drivers installed at all (winusb) and of course errors appears: "Unable to load winusb.dll...."
Now I don't want to try/catch every function imported since will drop performances (or not?) and instead, I'm thinking to use some check in my component constructor for presence of winusb.dll, raise error event and inhibit all functions until next program start. All functions are pointless without that dll. This is a good approach?
Now how can I check reliable for all platforms (xp, wista,7,8) for presence of that dll?
I need a expert opinion to optimum solve the problem and thanks very much in advance.
If System.IO.File.Exists("C:\Windows\System32\winusb.dll") Then
' go ahead
Else
' abort
End If
A better approach however would be to install the winusb library along with your application. An installer that doesn't install all required libraries is pretty worthless.

Unreleased DirectShow CSource filter makes program crash at process shutdown

I'm developing a DirectShow CSource capture filter. It works fine, but when I close the program that is using the filter (in this case I'm testing with VLC, but the same happens with other programs), the program crashes (if I'm debugging it in Visual Studio then a breakpoint is triggered).
I've been hunting down this problem for some time now and found that both, my source filter and my source stream are not being released; this is, their reference counter is 1 at the end of the program, DllCanUnloadNow() function reports that there are 2 objects still in use, and, when CoUninitialize() is invoked, the program crashes.
I'm pretty sure that the reference counters are being handled correctly since I'm using the base classes implementation. The only unusual thing in my software that I can think of is that I'm using my own version of DllGetClassObject(): I configured the .DEF file to have MyDllGetClassObject() exported instead of DllGetClassObject() so I could insert some code before invoking the default implementation. I don't think this is a problem since I've checked that the reference counter of all objects I return at the end of MyDllGetClassObject() is 1.
I guess I'm missing something about the lifecycle of the filter, but can't figure out what (this is the very first capture filter I'm developing). Any suggestion?
Thank you in advance,
Guillermo
I finally figured out what was going on. The static method InitializeInstance in my source filter is invoked with bLoading == false and rclsid == <the GUID of my filter> at process shutdown. That seems to be the appropriate place to release that remaining reference counter from the filter instance.
I got the key idea of how important is to release all COM objects before CoUninitialize some time ago from another post on StackOverflow entitled DirectShow code crashes after exit (PushSourceDesktop sample). All I needed was just a little bit more knowledge on DirectShow filters lifecycle.
Anyway, thank you for your efforts, Roman, I know how vague this thread sounded from the beginning :)

Is there a way to force the VB6 IDE to unload libraries?

When debugging a VB6 application, I have noticed that the VB6 IDE keeps any libraries loaded if they were used by the application being debugged. The library remains loaded between debugging sessions. This interferes with my debugging because unfortunately, one of our libraries (written in delphi) keeps state around in global variables and has significant initialization/termination logic.
Simplified example of the problem: I have a foo.dll with a counter inside it. I access this counter with the following declares in VB6:
Public Declare Function GetCounter Lib "foo.dll" () As Long
Public Declare Function IncrementCounter Lib "foo.dll" () As Long
The problem in this case is that the counter is not reset when I start a new debugging session. I would rather not write application or library logic to take this "recycled library state" scenario into account. I want to be able to start a debugging session with a clean slate.
Currently I force a library unload by restarting the VB6 IDE. Is there a better way?
edit: I played around a bit with invoking kernel32.dll functions to unload/reload libaries from the immediate window; this turned out to only be a good way to crash the IDE or cause random behavior. I should have expected that as the IDE has no way of knowing that it's original handle for the library has become invalid.
I have accepted AngryHacker's answer as I am now convinced that restarting vb6.exe is the only way to start a VB6 debugging session with a completely clean slate.
I've struggled with that for years back in the day, particularly when coding ActiveX DLLs for use with IIS sites.
The only real antidote I found was to keep the library loaded in a separate VB6 instance (assuming you have the control of the source). That way you could simply press the Stop button on the toolbar and the library would no longer be loaded.
You should look at a few things:
Make sure you are disposing of any class references by setting your local or global variables = nothing when your application exits.
When debugging, NEVER hit the end/stop debugging button. This just pulls the rug out from under the code and can sometimes leave things hanging in memory.
Don't use the End command in your application exit code (see point #2).