Access crash when hitting breakpoints - vba

I've got a project in Access 2010 that runs without issues. That is, until I add a breakpoint and I try to debug code. As soon as it reaches the first breakpoint, the VBA project opens up and about 1 second later Access crashes and restarts.
I can add a Debug.Print and all works fine. I just can't step through code.
Repair and compact did not work, nor to create a new project and import everything.
Looking at the event viewer I get:
Faulting application name: MSACCESS.EXE, version: 14.0.4750.1000, time stamp: 0x4b8bae0f
Faulting module name: ntdll.dll, version: 6.2.9200.16579, time stamp: 0x51637f77
Exception code: 0xc0150010
Fault offset: 0x00000000001041c0
Faulting process id: 0x2ef4
Faulting application start time: 0x01cf180a44c35b8a
Faulting application path: C:\Program Files\Microsoft Office 2010\Office14\MSACCESS.EXE
I can't unregister and reregister the DLL (entry point not found).
I've tried everything on http://pcsupport.about.com/od/fixtheproblem/a/ntdlldll.htm short of reisntalling Windows and still nothing.
Running Access in Safe mode does help, but does not fix it permanently.
Any other ideas?
UPDATE: I now have a new laptop and upgraded to Access 365. And it still happens. But only on one specific project. Other projects work fine.

Seems this is not the first time this type of error happens https://learn.microsoft.com/en-us/answers/questions/269052/vba-access-stop-command.html
The above link is very detailed (in terms of text + screenshots) and may be similar to what you experience.
Anyhow... please try to open your access software using the run as administrator option (right click access icon and pick this option). There is a chance that vba is trying to use elevated permissions and without it - it results in a spectacular crash

I got this error and discovered it was because of not declaring a variable as the correct type when using the GetUserName function, declared from the advapi32.dll library. I had to change "Dim buffer As String" to "Dim buffer As String * 256" before I could call "GetUserName(buffer, Size)". This is the code:
#If VBA7 Then
Private Declare PtrSafe Function GetUserName Lib "advapi32.dll" _
Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
#Else
Private Declare Function GetUserName Lib "advapi32.dll" _
Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
#End If
Function getNetworkName() As String
Dim ret As Long, Size As Long
Dim buffer As String * 256
Size = 256
ret = GetUserName(buffer, Size)
If ret <> 0 Then
getNetworkName = Mid(buffer, 1, InStr(1, buffer, vbNullChar) - 1)
Else
getNetworkName = "API ERROR"
End If
End Function
I don't know if your issues would be the exact same thing, but maybe it's due to a data type issue like this.

Related

Unable to set FindWindow result to variable in .NET

I am attempting to use the FindWindow API using Visual Studio 2017 (.NET Framework 4.6.1) and VB.NET to retrieve the window handle for a currently running instance of Microsoft Word. I am finding that, although it has worked in the past (and is working in another area of the code) in one particular instance, although the FindWindow call is returning a value, I am not able to assign it to a variable. I have verified this in debug mode (screenshots available). I am trying to figure why the API call is not working in this particular instance.
Screenshots link: https://imgur.com/a/NuwpUyz
I have executed this call in some areas of the .NET code I am working with, so I know that it does work. I've changed the type in the definition of the "assignee" variable (from Object, to Integer, to IntPtr, etc., etc.) and rerun the application, with the same results (the "assignee" variable ends up with a value of zero, but the FindWindow call itself returns a integer value which appears to be the correct window handle.
The FindWindow API definition:
<DllImport("user32.dll")>
Public Shared Function FindWindow(ByVal strclassName As String, ByVal strWindowName As String) As Integer
End Function
The FindWindow API call:
.
.
.
Public hndMDIWord As Integer
.
.
.
.
If Word_Previously_Running Then
Try
_mdiWordApp = GetObject(, "Word.Application")
Catch ex As Exception
_mdiWordApp = New Word.Application
End Try
Else
_mdiWordApp = New Word.Application
End If
hndMDIWord = FindWindow("Opusapp", "")
If hndMDIWord <> 0 Then
SetParent(hndMDIWord, Me.Handle.ToInt32())
End If
I am expecting FindWindow to return an integer representing the window handle of the currently running instance of Word and than have that result assigned to the hndMDIWord variable. FindWindow does return the expected result, but the assignment statement for the hndMDIWord variable does not execute properly; hndMDIWord ends up with a value of zero. There is no error and no exception is thrown.
Any suggestions and/or insights will, of course, be greatly appreciated.
Regards,
Chris Fleetwood
I think the problem is: IntPtr is not compatible with Integer.
You need to declare return type as IntPtr:
<DllImport("user32.dll")>
Public Shared Function FindWindow(ByVal strclassName As String, ByVal strWindowName As String) As IntPtr
End Function
Because:
FindWindow has HWND return type
From MSDN handles are marshaled as IntPtr
Also there is a pinvoke.net website with examples of .net interop with wast majority of WinAPI functions.
Also hndMDIWord need to be declared as IntPtr and used accordingly, and other WinAPI functions need to be declared to use IntPtr for handlers too:
Public hndMDIWord As IntPtr
. . . .
If hndMDIWord <> IntPtr.Zero Then

How to run function in vba using data macro?

i am new to data macro in ms access 2013 and need some help with it.
so lets assume that i have a simple database with only one table of Users.
when i change the "Age" Field in the table, i want to run an external exe file (the reason why dosent matter).
so i learn the subject during the last few days and end up with this:
1. i build a module in ms access called RunMiniFix (MiniFix is the name of the exe file i want to run). the module uses ShellExecute function and the whole module looks like that:
Option Compare Database
Const SW_SHOW = 1
Const SW_SHOWMAXIMIZED = 3
Public Declare Function ShellExecute Lib "Shell32.dll" Alias "ShellExecuteA"
(ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
Optional ByVal nShowCmd As Long) As Long
Public Function RunMiniFix()
Dim RetVal As Long
On Error Resume Next
RetVal = ShellExecute(0, "open", "C:\Program Files\MiniFix\MiniFix.exe", "<arguments>", _
"<run in folder>", SW_SHOWMAXIMIZED)
End Function
Now, when activating the module, everything works just fine and the exe file is running.
in ms access, i build a data macro based on an 'If Then' statement, asking
if [Users]![Age] > x and then calls the build-in RunCode event from the action catalog which calls the RunMiniFix function.
Now, when saving the data macro, the ms access pops up a message box saying Microsoft access dosen't have the ability to find the name "Users" i mentioned in the phrase and recommend me to look for the right control in the form. "the form"? yes, the form!
this database is not form based. i have no gui designed what so ever. i have no buttons or click event to handle.
what i am asking is how can i trigger the RunMiniFix module when the Age field is modify. please, this is very important!
thanks a head,
oron.
Please use SetLocalVar from the action list in data macro and set the expression to name of your function. Sample:
name: "test"
Expression: RunMiniFix()

Access Application, Hidden Application Window With Form Taskbar Icon

I have an access application with one main form. When you open the application, an AutoExec macro hides the application via the Windows API apiShowWindow. Then, the AutoExec opens up the main form which is set to Popup. This all works beautifully; my database guts are hidden and the form opens up and just floats along.
However, when the access database gets hidden, you loose the taskbar icon. I have a custom icon set in the Options\Current Database\Application Icon setting. If I don't hide the database, this icon displays just fine in the task bar.
I found an API workaround that will show an icon in the taskbar for just the form. It goes a little something like this:
Public Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function SetWindowPos Lib "user32" _
(ByVal hWnd As Long, _
ByVal hWndInsertAfter As Long, _
ByVal X As Long, _
ByVal Y As Long, _
ByVal cx As Long, _
ByVal cy As Long, _
ByVal wFlags As Long) As Long
Public Sub AppTasklist(frmHwnd)
Dim WStyle As Long
Dim Result As Long
WStyle = GetWindowLong(frmHwnd, GWL_EXSTYLE)
WStyle = WStyle Or WS_EX_APPWINDOW
Result = SetWindowPos(frmHwnd, HWND_TOP, 0, 0, 0, 0, _
SWP_NOMOVE Or _
SWP_NOSIZE Or _
SWP_NOACTIVATE Or _
SWP_HIDEWINDOW)
Result = SetWindowLong(frmHwnd, GWL_EXSTYLE, WStyle)
Debug.Print Result
Result = SetWindowPos(frmHwnd, HWND_TOP, 0, 0, 0, 0, _
SWP_NOMOVE Or _
SWP_NOSIZE Or _
SWP_NOACTIVATE Or _
SWP_SHOWWINDOW)
End Sub
This approach does work; I get an icon in the taskbar dedicated to just the form. However, the icon in the taskbar is the standard Access icon.
In response to this problem, I added another API call using the SendMessageA:
Public Declare Function SendMessage32 Lib "user32" Alias _
"SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _ ByVal wParam
As Long, ByVal lParam As Long) As Long
Executed thus:
Private Const WM_SETICON = &H80
Private Const ICON_SMALL = 0&
Private Const ICON_BIG = 1&
Dim icoPth As String: icoPth = CurrentProject.Path & "\MyAppIcon.ico"
Dim NewIco As Long: NewIco = ExtractIcon32(0, icoPth, 0)
Dim frmHwnd As Long: frmHwnd = Me.hwnd 'the form's handle
SendMessage32 frmHwnd, WM_SETICON, ICON_SMALL, NewIco
SendMessage32 frmHwnd, WM_SETICON, ICON_BIG, NewIco
SendMessage32 hWndAccessApp, WM_SETICON, ICON_SMALL, NewIco
SendMessage32 hWndAccessApp, WM_SETICON, ICON_BIG, NewIco
Keep in mind that I have tried the above four lines of 'SendMessages' in various orders inside of and outside of, top of and bottom of the AppTasklist Sub to no avail.
It does appear to work at the application level, but it never seems to work at the form level.
For those of you familiar with this particular predicament, let me list some of the other options outside of VBA that I have tried.
1.) Taskbar\Properties\Taskbar buttons. I've changed this menu option to 'Never Combine' and 'Combine When Taskbar Is Full'. So, basically, this does work; I now get my icon for just the folder and the little label. BUT(!), it only works if the users have these settings checked on their end. In my experience, almost no one uses any of the options except 'Always combine, hide labels'.
2.) Changing the Registry settings. You can change the following registry key to change the default icon an application uses: "HKEY_CLASSES_ROOT\Access.Application.14\DefaultIcon(Default)." However, most users (myself included) don't have access to the HKEY_CLASSES_ROOT part of the registry. Furthermore, I would have to write some code to find the proper key and then change it (which I could do) but, it's unclear if this change would be immediate--not to mention I'd have to change it back when exiting the application.
3.) Right-clicking the pinned application, then right clicking the application in the menu does give you a properties menu with a button called 'Change Icon...' in the 'Shortcut' tab. However, for a program like Access, this button is greyed out.
I am using Windows 7 and Access 2010.
Is it possible to force the Taskbar Icon in the above scenario to something other than the standard Access Icon?
I feel like there's ether a little something I'm missing, or an API function that could be used, or a better SendMessage constant, or that, maybe, it just can't be done.
Any help would be greatly appreciated.
Also, as a disclaimer (I guess): obviously the above code was pulled from other posts from this forum and others. Most of it was unattributed from whence I got it. I've made some minor tweeks to make it work in Access as opposed to that other piece of Microsoft Software that keeps getting in my search results so I will not name it here.
Thanks!
Okay. So I'm going to answer my own question. Apparently all I really needed was a break from the action and to type out my problem. A short time after I posted the question, I got back on the horse and tried some more search terms. I eventually came across a post which really didn't seem fruitfull at the outset because it wasn't clear to me if the poster and myself were dealing with the same scenario.
I found my answer here:
http://www.access-programmers.co.uk/forums/showthread.php?t=231422
First off, your application must open via a shortcut. Fortunately for me, I've been using a Desktop shortcut from the begining.
When I started building the application, I knew from the outset that I would be using a VBScript to do the installation of the application (as well as updating when a newer version get's released). In that script, I create a Desktop shortcut to the application which I store in the user's Documents directory. I also store the application icon in that directory which I attach to the application shortcut.
If you've never created a shortcut via vba/script, you'll essentially do something like this (written in vbScript):
Dim WinShell
Dim ShtCut
Set WinShell = CreateObject("WScript.Shell")
Set ShtCut = WinShell.CreateShortcut(strDesktopPath & "\MyCoolApp.lnk")
With ShtCut
.TargetPath = (See below)
.Arguments = (See below)
.IconLocation = ...
.Desciption = "This is the coolest app, yo!"
.WorkingDirectory = strAppPath
.WindowStyle = 1
.Save
End With
Now, the target of the shortcut started out being something like this:
"C:\Users\UserName\Public\Documents\MyCoolApp\MyCoolApp.accdb"
Obviously your users may have a different enterprise structure for the Documents location...
What the above reference post suggests doing is turning that shortcut into a psuedo command line script.
To do this:
First, your actual target is going to be the path to the user's version of access (Runtime or full), like such:
"C:\Program Files (x86)\Microsoft Office\Office14\MSACCESS.EXE"
IMPORTANT! You will have to wrap this target in double-quotes, i.e.:
.TargetPath = Chr(34) & strAccessPath & Chr(34)
Next (and you won't find this in the above post, I had to figure it out), you'll need to set the Argument to the directory of the application, like such:
"C:\Users\UserName\Public\Documents\MyCoolApp\MyCoolApp.accdb"
IMPORTANT! Again, you'll have to wrap the arguments in double-quotes, i.e.:
.Arguments = Chr(34) & strAppPath & Chr(34)
Also important, I hope your app IS cool.
Once you have this shortcut set up, essentially you're making it so your application will have it's own workgroup on the taskbar. I.e., if Access is open in general, your application will have it's own group on the taskbar. This group will have your cool, custom icon associated with it. And as a huge unexpected bonus, you'll be able to pin your shortcut to the taskbar outside of Access. SWEEEEEET!
Good luck!

command line arguments works in visual studio but not from command line for a WindowsForm project in Visual Basic

I've done a little programm in visual basic.
It compress a file and upload the file on an ftp server. The programm himself work well.
My problem is that i want it to have a different behavior if it takes arguments from command line or not. If arguments are given no form shows up and if not the form is loaded.
The code getting command line arguments work fine when executed from visual basic (project properties -> debug -> start options -> command line arguments is set with the file path)
But when i execute the program from cmd with this line :
pogram.exe C:\Users\user\file.txt
The form shows up and no arguments are detected.
Here is the main for dispatch.
Module1.vb :
Module Module1
Declare Function AttachConsole Lib "kernel32" (ByVal dwProcessId As Int32) As Boolean
Declare Function FreeConsole Lib "kernel32.dll" () As Boolean
Sub Main()
Dim cmdArgs As String() = GetCommandLineArgs()
Form2.loadData()
If cmdArgs.Length = 0 Then ' NO ARGS MODE
mainWindow.commandLineMode = False
Application.Run(mainWindow)
ElseIf cmdArgs.Length < 3 And Form2.TXTnumLicence.Text = "" Then ' BAD ARGS NUMBER
Console.WriteLine("Aucun numero de licence definit. Usage : ./ODG_exchange ['filePath'] [numeroLicence [default = ./ODG_param.xml > numero_licence]]")
Application.Exit()
Else ' ARGS MODE
mainWindow.commandLineMode = True
mainWindow.commandeLine(cmdArgs)
End If
End Sub
In visual studio i also defined the startup object as Module1. Maybe it will be useful.
There is always one command line arg - the filename of the executing program.
You need to change your if statement to cmdArgs.length = 1
Well 7 days later i found the solution... Just use the good .exe and it works as well as in visual studio...
I feel so dumb, thanks for the help

How does the Apple iTunes web site launch the iTunes application on my computer when I click the blue "Launch iTunes" button?

This is new to me as a desktop developer.
If I could figure out how this is accomplished, it may be relevant to some research I'm doing, specifically how to migrate thick desktop apps to a web implementation.
The more forms-oriented and lightweight graphics I can figure out, but heavyweight 3D graphics still requires some form of non-browser application.
As nearly as I can determine, iTunes installs some form of new protocol handler on my machine, corresponding to "itms", in place of "http".
This is cool and mysterious to me, almost magical. Any help or suggestions for additional reading materials and/or resources would be very welcome.
You can register "protocol handlers" with some browsers. I think there's a place in the operating system where you can regsiter your own.
See
http://msdn.microsoft.com/en-us/library/dd588696(office.11).aspx
http://blog.ryaneby.com/archives/firefox-protocol-handlers/
Creating new ones in firefox: http://ajaxian.com/archives/creating-custom-protocol-handlers-with-html-5-and-firefox
In safari: http://discussions.apple.com/thread.jspa?threadID=1280989
Special "mobile protocol handlers" are used extensively in the iPhone/iPod to launch the phone dialler, email sending, google maps and so on... http://www.iphonedevfaq.com/index.php?title=Protocols
Here's an example of how to reconfigure the mailto: protocol handler to trigger gmail rather than an external mail client: http://lifehacker.com/392287/set-firefox-3-to-launch-gmail-for-mailto-links
Simple.
Open iTunes
Most apps now-a-days have "Custom URL Schemes"
For Example - Coda (http://panic.com/coda) you can add snippets of code via:
Add Clip
In Windows this is called a Pluggable Protocol Handler. This article on CodeProject shows how to implement a pluggable protocol handler on Windows.
Note, this is more involved then just registering a new protocol in the registry, such as myprotocol:// and having it start a specific exe whenever a myprotocol:// anchor is clicked.
It actually allows your application to receive and process the request and to create response data dynamically. If your protocol will also be called programmatically this is usually important.
This may be overkill for your situation however it is handy to know about.
The easiest way is to register a filetype to your application (also called File Association), for example ".myp" and when the user press "start myapp" on the site it downloads a file "startapp.myp".
Windows will then look at the extention of the file and find that it is registered to your app and start your application with the file as a command-parameter. Your app can then read the file and do stuff depending of it contents.
Here are code to register a filetype to your application done in VB.Net:
(Example is taken from http://www.developerfusion.com/article/36/file-assocation/2/ but copied here for persistent reason, check original site for comments)
'// Registry windows api calls
Private Declare Function RegCreateKey& Lib "advapi32.DLL" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpszSubKey As String, ByVal lphKey As Long)
Private Declare Function RegSetValue& Lib "advapi32.DLL" Alias "RegSetValueA" (ByVal hKey As Long, ByVal lpszSubKey As String, ByVal fdwType As Long, ByVal lpszValue As String, ByVal dwLength As Long)
'// Required constants
Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const MAX_PATH = 256&
Private Const REG_SZ = 1
'// procedure you call to associate the tmg extension with your program.
Private Sub MakeDefault()
Dim sKeyName As String '// Holds Key Name in registry.
Dim sKeyValue As String '// Holds Key Value in registry.
Dim ret As Long '// Holds error status if any from API calls.
Dim lphKey As Long '// Holds created key handle from RegCreateKey.
'// This creates a Root entry called "TextMagic"
sKeyName = "TextMagic" '// Application Name
sKeyValue = "TextMagic Document" '// File Description
ret = RegCreateKey&(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue&(lphKey&, Empty, REG_SZ, sKeyValue, 0&)
'// This creates a Root entry called .tmg associated with "TextMagic".
sKeyName = ".tmg" '// File Extension
sKeyValue = "TextMagic" '// Application Name
ret = RegCreateKey&(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue&(lphKey, Empty, REG_SZ, sKeyValue, 0&)
'//This sets the command line for "TextMagic".
sKeyName = "TextMagic" '// Application Name
If Right$(App.Path, 1) = "\" Then
sKeyValue = App.Path & App.EXEName & ".exe %1" '// Application Path
Else
sKeyValue = App.Path & "\" & App.EXEName & ".exe %1" '// Application Path
End If
ret = RegCreateKey&(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue&(lphKey, "shell\open\command", REG_SZ, sKeyValue, MAX_PATH)
End Sub
Private Sub Form_Load()
'// ensure we only register once. When debugging etc, remove the SaveSetting line, so your program will
'// always attempt to register the file extension
If GetSetting(App.Title, "Settings", "RegisteredFile", 0) = 0 Then
'// associate tmg extension with this app
MakeDefault()
SaveSetting(App.Title, "Settings", "RegisteredFile", 1)
End If
'// check command line argument:
If Command$ <> Empty Then
'// we have a file to open
'// Fetch the file name from Command$ and then read the file if needed.
End If
End Sub
Just a follow-up for those who answered.
Turns out that the situation is somewhat complicated. Although about:config is available for FireFox, making the appropriate entries just doesn't work.
This link: http://support.mozilla.com/tiki-view_forum_thread.php?locale=fr&forumId=1&comments_parentId=74068 describes problems for Linux, but I can verify that the same problems also occur under Windows.
To make this work under Windows, I had to create a .REG file which contains the appropriate information, according to this link: http://kb.mozillazine.org/Register_protocol#Windows
Now it works!
Thanks for all the responses.