Go Back   Access World Forums > Microsoft Access Discussion > Modules & VBA

 
Reply
 
Thread Tools Rate Thread Display Modes
Old 05-27-2019, 11:35 PM   #1
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
DLL with callback problem

I have made a simple dll with C for use in an Ms Access vba project. The dll makes a new thread and makes use of a vba callback function inside the thread's code. According to MS documentation the vba callback function has to be in a vba module and not in a form's code. Inside the callback function I set a form's filter property. But because of this the Access crashes when the execution it arrives there!!! Why? Other references to form's components have no problem (for example when I set the value of the form's textbox)
The mysterious is that I found the problem exists only when the vba Callback Sub is called from the Thread function (ThreadFunc). If it is called from within dll main thread then form's filter is set ok without crash (!!!)

Thanks

The C dll code compiled with VS 2017:
Code:
#include <windows.h>
#include <stdlib.h>
#include <tchar.h> 

typedef void(__stdcall * CallbackFunction)();

DWORD __stdcall ThreadFunc(CallbackFunction Callback) { 
    Callback();
    return 0;
}
 
__declspec(dllexport) void __stdcall message(CallbackFunction Callback) {
     // Array to store thread handles
    HANDLE Array_Of_Thread_Handles[1];
    Array_Of_Thread_Handles[0] = CreateThread(NULL, 0, ThreadFunc, Callback, 0, NULL);
}
And here is the code that call the dll function "message" from within vba
Code:
Private Sub Form_Load()
    Call message(AddressOf Callback)
End Sub
The vba Declaration of dll
Code:
 Public Declare Sub message Lib "test.dll" Alias "_message@4" (ByVal Callback As Long)
The vba callback subroutine (resides on a Module according to MS documentation)
Code:
 Public Sub Callback()
    On Error Resume Next
    Forms("MyForm").txtTest="test" 'this line executed well and the string "test" appears ok in the form.
    Forms("MyForm").Filter="" 'in this line Access crashes out
    Forms("MyForm").FilterOn=True
End Sub


Last edited by nonlinearly; 05-28-2019 at 12:33 AM.
nonlinearly is offline   Reply With Quote
Old 05-28-2019, 05:09 AM   #2
sonic8
Newly Registered User
 
Join Date: Oct 2015
Posts: 213
Thanks: 34
Thanked 62 Times in 59 Posts
sonic8 is on a distinguished road
Re: DLL with callback problem

Quote:
Originally Posted by marlan View Post
Access (as all Office Apps) is a COM object (?!), and can therefore not run in multi-thread environment.
COM-Objects in general do not have limitations with multi threading, Windows UI elements do.



I posted a longer answer on UA where the OP asked the same question.
__________________
New video:
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
sonic8 is offline   Reply With Quote
Old 05-28-2019, 06:06 AM   #3
The_Doc_Man
Happy Retired Curmudgeon
 
Join Date: Feb 2001
Location: Suburban New Orleans, LA, USA
Posts: 13,931
Thanks: 79
Thanked 1,564 Times in 1,452 Posts
The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold
Re: DLL with callback problem

First, I will confirm marlan's memory. Since VBA is pseudo-compiled and the VBA environment interprets the pseudo-code, multi-threading is not possible within VBA. There is only one VBA interpreter and it is, to the best of my knowledge, not coded re-entrantly to allow for multiple threading. Note that this is a different statement than saying that ACCESS cannot deal with multiple threads of its own; it surely can do so. It is that VBA and Access SQL via JET or ACE, being interpreted, do not support true parallel operation. Further, since JET & ACE are called synchronously, native Access + JET/ACE is ALSO not truly parallel even though they occupy two processes. A pass-thru or remote procedure call operation to an active SQL back-end is the only way that Access does things in parallel from the user viewpoint. Everything else, from our perspective, is serialized.

However, since the inner workings of Access are pretty much a "black box" to us, it is very hard to say what would happen if a self-contained, self-terminating thread were to be created, or if you arranged for ANOTHER call that would rejoin that thread and dissolve it at a later time.

Second, I am not sure about the issue of directly setting the .Filter that way. Not that you cannot directly load .Filter and .FilterOn properties, but from that context I am not sure about threading as a way to get there. I had to pull out my Win32 API reference books for this one.

I think an experiment might pinpoint the problem. Change the order of filling the text box and the filter. Make the .Filter and .FilterOn be the first things you set and see which line crashes. If, as I suspect, it is the 2nd line to touch a property, then you will set the .Filter but fail to set .FilterOn, and if so, that means you can't do this in a thread.

When I read the discussion about the thread created this way, my question (for my own consideration) is that you are using 0 for the fdwCreate argument, which means the thread gets executed immediately. In the code you have specified, there is no thread self-termination so you would leave a dangling thread.

What bothers me most is that this is being triggered from a form event routine, Form_Load. Form events declared via "Private Sub" syntax are not like true interrupt events; they are synchronous. However, the description of CreateThread suggests that there are limits of what can happen when a thread is created. I don't think that you are running into the "serialization of DLL initiation" problem because by that time, the other DLL code should be ready. But since this code has to be in the address space, it is subject to the limitations of having only one thread active at any time within the process. I'm thinking that somewhere along the way, the VBA interpreter finds your CallBack routine but on the attempt to return, it gets lost. That is because your code flow leaves the Access environment then enters that environment again but with that "foreign" call still on the stack.

Tell us in ENGLISH with NO references to code: What were you trying to do? Because there is no reason you couldn't have done a filter modification in ordinary VBA without resorting to C++ code. So I suspect this was an experiment to learn how to write your own DLL code. But the callback part, calling back into the VBA environment, is the tricky part. I don't think that works. At least, if it does, I have never seen it before. I can only say I think this fails because of attempting to re-enter an interpreted environment in a non-standard way.

Third, we have a reason for not liking it when folks cross-post to multiple forums without stating that they are doing so. And you got a valid response on UA regarding the lack of tools to allow a shared resource to be controlled in such a way as to prevent it from two threads "stepping on something" that results in "destructive interference." It is valid to consider that when you attempt to set the filter you will have an automatic reaction from MSACCESS.EXE to do its "behind the scenes" work to modify the bound form's recordset (which is where the filter gets copied when you supply it) - and therein lies the problem. THAT part of Access might WELL be in its own thread and vying for access to the form properties.

We don't blacklist you or anything like that when you cross-post without revealing it - but we do consider it rude and potentially wasteful of our time when you ask a question that already has reasonable answers. "Shopping around" for a better answer is easily understandable. In the future, if you feel that you are getting nowhere on one forum, we know you might wish to use another forum - but it is considered polite to note that fact and very impolite not to do so.

__________________
I'm a certified grandpa (3 times now) and proud of it.
Retired over one year and survived being home all day with the wife. She must really love me.
If I have helped you, please either click the thanks or click the scales.

Last edited by The_Doc_Man; 05-28-2019 at 06:26 AM.
The_Doc_Man is offline   Reply With Quote
Old 05-28-2019, 06:35 AM   #4
The_Doc_Man
Happy Retired Curmudgeon
 
Join Date: Feb 2001
Location: Suburban New Orleans, LA, USA
Posts: 13,931
Thanks: 79
Thanked 1,564 Times in 1,452 Posts
The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold
Re: DLL with callback problem

Now, a second post with a different thrust, because you SHOULD have more info that would be crucial. If Access really crashes, it is not in a vacuum. Even WinXP does serious event logging. Run your experiment, and when Access crashes, note the time on the little date/time display in the far right end of the Windows Task Bar.

From your desktop, get to Control Panel >> Administrative Tools >> Event Viewer. You will have System and Security logs and might also have Application logs. Heck, depending on your anti-virus, you might even have something there. One by one, visit each log file with Event Viewer.

The events are sorted by date and time so it should be trivial to find anything in each log from that time involving MSACCESS.EXE as the failing process. You would be looking for the final status code and anything else it tries to tell you about the events of the crash. That might be instructive.
__________________
I'm a certified grandpa (3 times now) and proud of it.
Retired over one year and survived being home all day with the wife. She must really love me.
If I have helped you, please either click the thanks or click the scales.
The_Doc_Man is offline   Reply With Quote
Old 05-29-2019, 03:29 AM   #5
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

below I have the report from Event Viewer


Faulting application name: MSACCESS.EXE, version: 14.0.7230.5000, time stamp: 0x5c6738e8
Faulting module name: MSACCESS.EXE, version: 14.0.7230.5000, time stamp: 0x5c6738e8
Exception code: 0xc0000005
Fault offset: 0x0015a3f1
Faulting process id: 0x66fc
Faulting application start time: 0x01d5161113939034
Faulting application path: C:\Program Files (x86)\Microsoft Office\Office14\MSACCESS.EXE
Faulting module path: C:\Program Files (x86)\Microsoft Office\Office14\MSACCESS.EXE
Report Id: 665b2a08-8204-11e9-862a-64315042aab9
nonlinearly is offline   Reply With Quote
Old 05-29-2019, 03:57 AM   #6
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

more information:
1. I have switched the textbox reference with filter. So first to execute the filter and second the textbox. The result was that filter executed but not textbox value set.
2. I removed textbox and filter's settings. I wrote only one line of code: MyForm.RecordSource="...". Access crashes out!!!


I need to monitoring a text file for changes. And I used some Windows API in dll like FindFirstChangeNotification. Based on these changes I have to filter the form using a vba callback that is called form within dll thread function. The problem is that everything is ok (I open and read the txt, I log the contents of txt in the SQL Server backend database using ADO but when I set some form's properties Access crashes out)


If I can't use threading in Access even with a dll then I have to leave MS Access when I need to make more serious applications. And I think that after this disappointment I will leave MS Access forever.
But I have a question. Are there Windows API dll functions that use internally threading with callback? If yes would be nice to use one with the same way to see how it is work. I know that there are API functions with callback (for example EnumWindows) but I do not know with threading inside DLL.

Last edited by nonlinearly; 05-29-2019 at 04:19 AM.
nonlinearly is offline   Reply With Quote
Old 05-29-2019, 04:54 AM   #7
sonic8
Newly Registered User
 
Join Date: Oct 2015
Posts: 213
Thanks: 34
Thanked 62 Times in 59 Posts
sonic8 is on a distinguished road
Re: DLL with callback problem

Quote:
Originally Posted by nonlinearly View Post
If I can't use threading in Access even with a dll then I have to leave MS Access when I need to make more serious applications.
Access is not the proper tool if you want to create an application with serious multi threading.
In any case, you need to understand threading on a deep level before creating an application with serious multi threading in any development environment.


Quote:
Originally Posted by nonlinearly View Post
Are there Windows API dll functions that use internally threading with callback?
I assume most Windows API functions are designed with great care to not invoke a callback from a different thread, because of the problems this might cause.


However, the obvious prime example of an Windows API functions that will invoke a callback on a different thread is CreateThread.

__________________
New video:
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
sonic8 is offline   Reply With Quote
Old 05-29-2019, 06:11 AM   #8
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

Quote:
Originally Posted by sonic8 View Post
I assume most Windows API functions are designed with great care to not invoke a callback from a different thread, because of the problems this might cause.

Ok... This means that if we could call the Callback from the main thread of dll (ie from dll message function) would be perfect. Indeed I have tried it and works perfect. But we must have a mechanism in the dll that thread function notify the main dll thread when it has to inform for a change. The problem also is that that "message" dll function runs in the same thread as vba's!!!
nonlinearly is offline   Reply With Quote
Old 05-29-2019, 06:20 AM   #9
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

If we create a C callback inside dll and the thread function call this (instead of vba callback) and then the dll callback call vba callback?
nonlinearly is offline   Reply With Quote
Old 05-29-2019, 06:27 AM   #10
The_Doc_Man
Happy Retired Curmudgeon
 
Join Date: Feb 2001
Location: Suburban New Orleans, LA, USA
Posts: 13,931
Thanks: 79
Thanked 1,564 Times in 1,452 Posts
The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold
Re: DLL with callback problem

Quote:
Exception code: 0xc0000005
...
Faulting module path: C:\Program Files (x86)\Microsoft Office\Office14\MSACCESS.EXE
As I suspected, you got a type of error common to mis-use of addresses. In this code, the "c" says that it is a severe error. (Translation: Unrecoverable.) The "5" says it is a memory access violation.

First, remember that in windows your process is VIRTUAL. It has addresses that are mapped to physical memory by hardware memory relocation registers. Under Windows ever since Windows NT came out, NO process ever directly touches a physical memory address once the boot sequence is finished. Even the O/S uses virtual mapping once the startup code terminates. Therefore, when you try to touch something in memory, it MUST be in a mapped area.

There are ways to make certain specific memory areas accessible but you have to use system API calls to do it. If you have Win7 or Win10, the O/S has a feature called code protection that uses the memory management hardware to prevent rogue code from overwriting any executable code. The code authors have a way to set the code's memory usage tags so that the image load process includes setting memory access codes appropriately.

A memory access violation occurs in one of only a couple of ways. Error 5 says that EITHER you attempted to refer to an address for which no physical mapping is defined (i.e. no physical memory, i.e. the hardware memory fetch circuit fails to develop a full physical address) OR you attempted to write to an address that was mapped as READ-ONLY (i.e. modify protected code, i.e. the hardware memory write circuit encounters a memory page mapped with the NOWRITE flag set.)

This is a kernel-level hardware fault - a true hardware interrupt as opposed to ordinary Access events caused by a purely normal software action like opening a form. It is unlikely that you would be easily able to intercept this fault with a trap handler because the faulting module is within MSACCESS.EXE, not your .DLL file. A trap handler only has visibility to your code, not to the Access executable code.

Quote:
I have switched the textbox reference with filter. So first to execute the filter and second the textbox. The result was that filter executed but not textbox value set.
As I predicted, the problem stayed as the second line (not counting the ON ERROR line) which means that the VBA interpreter got lost after the first executable line that tried to touch the external object. The first touch worked, but the next touch did not.

You cannot use threading like this because the Access environment isn't oriented towards user-level threading. You need to write your whole application in something that uses "true" compilation as opposed to VBA's pseudo-code compilation.

Quote:
I need to monitoring a text file for changes.
If it is really just a text file then monitor its date of last update. When it changes, you know to take a closer look at it. If you need a real-time monitor of text file changes, though, I don't know where you are going to find support. I'm not even sure how I would approach this problem with OpenVMS and that is considered "mainframe" these days.
__________________
I'm a certified grandpa (3 times now) and proud of it.
Retired over one year and survived being home all day with the wife. She must really love me.
If I have helped you, please either click the thanks or click the scales.
The_Doc_Man is offline   Reply With Quote
Old 05-29-2019, 07:41 AM   #11
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

Quote:
Originally Posted by The_Doc_Man View Post
If it is really just a text file then monitor its date of last update. When it changes, you know to take a closer look at it. If you need a real-time monitor of text file changes, though, I don't know where you are going to find support.

I need a real time solution and not polling... so I leave behind Access and I change platform from now on...
The problem is that the application is too huge and works for years to develop again from scratch only for this reason!!!


Thanks anyway
nonlinearly is offline   Reply With Quote
Old 05-29-2019, 12:57 PM   #12
The_Doc_Man
Happy Retired Curmudgeon
 
Join Date: Feb 2001
Location: Suburban New Orleans, LA, USA
Posts: 13,931
Thanks: 79
Thanked 1,564 Times in 1,452 Posts
The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold The_Doc_Man is a splendid one to behold
Re: DLL with callback problem

Here is your reality. The file system isn't really set up to support real-time file update monitoring. The only way I know that you COULD do this with Windows would be to write a driver mod that would trap a write operation to a particular device/file combo and somehow trigger some watchdog process. If we are dealing with a case of Network Attached Storage, I'm not even sure which driver you would need to modify to support that interception.

You should also note that most security code will stop you from that approach because that is the behavior of virus-class malware. Windows Defender should stop you cold if you try to do this. I know Norton and Kaspersky would stop you. Don't have as much experience with other anti-virals but I'll bet they would also complain.

Windows won't tell you what you want to know. You are inventing an ability that Microsoft chose to not implement. I am not saying you can't because I told you the only approach that has half a chance, basically a driver "hook" modification. But you are clearly overreaching the abilities of the "standard" tools defined under Windows.

I wish you luck, and if you wish to try another platform, some of the Open UNIX variants give you source code, even at driver level, that you could modify to try to intercept file actions. However, in their infinite (?) wisdom, Microsoft has not seen fit to publish a lot of their code. Oh, one more thing. Doing what you are trying to do WILL in all probability violate the conditions of your software warranty AND any support contract you might have.
__________________
I'm a certified grandpa (3 times now) and proud of it.
Retired over one year and survived being home all day with the wife. She must really love me.
If I have helped you, please either click the thanks or click the scales.
The_Doc_Man is offline   Reply With Quote
Old 05-30-2019, 12:03 AM   #13
sonic8
Newly Registered User
 
Join Date: Oct 2015
Posts: 213
Thanks: 34
Thanked 62 Times in 59 Posts
sonic8 is on a distinguished road
Re: DLL with callback problem

@nonlinearly: I'm getting slightly annoyed. After starting two threads in different forums simultaneously, it appears you are not even reading the replies in the other forum anymore.
Quote:
Originally Posted by nonlinearly View Post
I need a real time solution and not polling... so I leave behind Access and I change platform from now on...
The problem is that the application is too huge and works for years to develop again from scratch only for this reason!!!

It is your responsibility as developer to handle the syncing of the threads to update the UI. This is not an Access specific issue. Access reacts very badly to ignoring this by crashing, but it will cause problems in all environments. - Leaving Access just for this reason is not a sensible decision, as you yourself recognized already.
__________________
New video:
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
sonic8 is offline   Reply With Quote
Old 06-03-2019, 12:55 AM   #14
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

Quote:
Originally Posted by The_Doc_Man View Post
....The file system isn't really set up to support real-time file update monitoring. .....

You are inventing an ability that Microsoft chose to not implement. .... But you are clearly overreaching the abilities of the "standard" tools defined under Windows.

...However, in their infinite (?) wisdom, Microsoft has not seen fit to publish a lot of their code. ...



This is wrong... I have already code from Microsoft that do this... monitoring a Windows folder for changes!!! And works like a charm for other languages like C#... !!! The problem is not Windows but Access.
Monitoring folder's changes in Windows is used quite often and there is code for all languages. There is code for C#, C++,Java etc. So I do not understand yours last comments!
nonlinearly is offline   Reply With Quote
Old 06-03-2019, 01:04 AM   #15
nonlinearly
Newly Registered User
 
Join Date: Jun 2012
Posts: 21
Thanks: 3
Thanked 0 Times in 0 Posts
nonlinearly is on a distinguished road
Re: DLL with callback problem

Quote:
Originally Posted by sonic8 View Post
@nonlinearly: I'm getting slightly annoyed. After starting two threads in different forums simultaneously, it appears you are not even reading the replies in the other forum anymore.
Don't be so rushed


Quote:
Originally Posted by sonic8 View Post
It is your responsibility as developer to handle the syncing of the threads to update the UI.
I'm not asking people just to confirm my question


Quote:
Originally Posted by sonic8 View Post
This is not an Access specific issue. Access reacts very badly to ignoring this by crashing, but it will cause problems in all environments. - Leaving Access just for this reason is not a sensible decision, as you yourself recognized already.
Just read my previous response


Thanks anyway

nonlinearly is offline   Reply With Quote
Reply

Tags
api , callback function , dll , threading

Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
can't run callback function 'onribbonload' Bechert Modules & VBA 1 11-28-2014 09:34 AM
Access Ribbon Callback msadiqrajani Modules & VBA 1 05-11-2011 02:22 AM
Setting a Callback!!!!!!!! Dazzle Forms 4 06-23-2008 03:09 AM
Callback function not displaying data ray147 Modules & VBA 0 12-13-2005 05:58 AM
Balloon Callback charityg Forms 3 06-01-2001 06:47 AM




All times are GMT -8. The time now is 01:15 PM.


Microsoft Access Help
General
Tables
Queries
Forms
Reports
Macros
Modules & VBA
Theory & Practice
Access FAQs
Code Repository
Sample Databases
Video Tutorials

Featured Forum post


Sponsored Links


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
(c) copyright 2017 Access World