Using visual basic in say Excel, I am able to declare WinAPI functions using the DECLARE keyword - e.g.
Declare Function SetLocaleInfo Lib "kernel32" Alias "SetLocaleInfoA" ( _
ByVal Locale As Long,
ByVal LCType As Long,
ByVal lpLCData As String
) As Boolean
However when using this syntax in a *.VBS file - it fails with a compile error.
Can anyone tell me what I need to do to run WinAPI functions from *.VBS files?
You can't run WinAPI functions from VBScript without some extra third-party support.
I believe there used to be vendor of a COM component which allowed VBScript to call into a standard dll but I can't remember what it was called and its quite possible that my imagination is playing tricks on me.
Plenty of forum posts mention 'dynacall' as the wrapper I think you're talking about however the two main links they post seem defunct
For what it's worth HTA may be worth looking at as an easy to use substitute
http://www.microsoft.com/downloads/en/details.aspx?FamilyId=231D8143-F21B-4707-B583-AE7B9152E6D9&displaylang=en
Related
I am trying to fix some ~20 year old VBA code in Access that uses Windows Standard Serial Communications created by MarshallSoft Computing. The 32 bit version stopped working. For implementation reasons, it would be a lot easier to use something native in VBA that doesn't require installing a new library. The code just uses a handful of the WSC32 functions and it would be great if there was a native library in VBA that paralleled those functions. Any help is appreciated!
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
https://gist.github.com/heiswayi/f47dfd8dc38955322bef is the David M. Hitchner example.
A search for "Darren Richards Win32 comms API wrapper for VBA" gave me some links (on Google, not on Bing) to postings of the (shorter) Darren Richards example, but not an original source.
From http://www.hardandsoftware.net/NETCommOCX.htm, NETCOMM.OCX is a way of using the original MSCOMM32.OCX in VBA. I agree that using the native windows API is simpler, but if you want scripting as well, NETCOMM.OCX works in VBS.
You can just write to COM1, but the VBA file system object has trouble with binary, and with reading. And NTFS used the same syntax for creating forks in the file system that BASIC used for configuring COM ports. (And MS never implemented a pseudo file system fork to restore the missing function, which they could easily have done). As a consequence, you effectively either have to use a comm object or the Windows API.
This question already has an answer here:
32bit vs 64bit Office - Ptrsafe function delcaration - when can I use it
(1 answer)
Closed 1 year ago.
I would like to know how you know whether you even need to declare PtrSafe in your Microsoft Access database for an ACCDE to work on a 32-bit version of Microsoft Access. To my knowledge, I do not have any statements with the word Declare in them. My database has tons of subs and one global dim variable in a few forms, but that's it. I recently had someone unable to open my ACCDE file, and he got a 64-bit message error, but I have no idea even where to find which code is giving him issues. I'm not an expert with Access or VBA and don't quite understand when the PtrSafe statement needs to be used or not used.
UPDATE: the problem wasn't PtrSafe. The problem was that the file was an accde. The accdb file is bit agnostic, as long as PtrSafe rules are followed or no declare statements are used, but the accde has a bitness, meaning if it's compiled on a 64 bit version, it will only open on a 64 bit version.
===================================================
You'll need to use PtrSafe if your code will ever need to execute on a 64 bit version AND you are using DECLARE statements to interact with the Win32.api. See the section on api compatibility in the second link for more.
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/ptrsafe-keyword
https://learn.microsoft.com/en-us/office/client-developer/shared/compatibility-between-the-32-bit-and-64-bit-versions-of-office
I'm trying to implement an API Hooking mechanism.
What I have so far, is a DLL injected into other processes via a SetWindowsHookEx call, and some code to implement the hooks themselves.
For example, I can successfully hook MessageBoxA calls across multiple different applications (thats not the end goal).
What I need to do is hook some graphics functions, in particular textout functions as I need to be able to screen scrape.
Now - I'm aware which textout functions I need (TextOutA/W, ExtTextOutA/W for the application I'm trying to access), and I'm aware I need to hook Begin/EndPaint or Get/ReleaseDC to match the DC's to window handles and determine if the textout is on a window I'm interested in.
My problem is that while I can hook the textout functions, messageboxes and so on without any problems what so ever, GetDC results in a hard crash as does BeginPaint.
The code is quite long, so I'll post what I'm having problems with, but I can post more if it helps.
The rough frame work is as follows;
function CustomBeginPaint(hWnd: HWND; var lpPaint: TPaintStruct): HDC;
begin
UninstallHook();
Result := BeginPaint(hWnd, lpPaint );
InstallHook();
end;
Even this quite simple function fails constantly, returning zero.
I'm at a complete loss to explain whats going on, as the hWnd is always 1309192 despite trying this on multiple machines.
So the key issue was, as Andreas Hausladen mentioned thread safety - but not due to the VCL.
I'm trying to run some LotusScript code (very similar to Visual Basic) in Lotus Domino on Windows servers.
The code calls some Windows API functions, and works fine on 32-bit Windows 2003 servers, but doesn't work on the one 64-bit server we've tried it on.
Here's one of our external function declarations:
Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _
(Byval lpFile As String, Byval lpDirectory As String, Byval lpResult As String) As Long
When trying to call that function, LotusScript produces the error message "External function not found".
I have tried both removing the Alias from the declaration, and changing the alias to "FindExecutable" with the same result.
I have also:
- For comparison, tried calling the GetForegroundWindow function in user32.dll - this works.
- Used the Dir function to confirm that shell32 exists with the path "c:\windows\syswow64\shell32.dll", then...
- Changed the Lib in the declaration to the dll's full path - this produces "Error in loading DLL" when calling the function.
Is there anything that must be done differently when calling shell32 functions on a 64-bit server?
Any other reason why the function call would fail on one particular server?
Just ran into this myself with a custom 64-bit DLL on 64-bit Domino. It appears it may be a known issue on 64-bit versions of Domino that IBM has decided to term as a "permanent restriction":
LO47066: "EXTERNAL FUNCTION NOT FOUND." ERROR FROM LOTUSSCRIPT AGENT USING SOME DLL FUNCTIONS IN DOMINO 64-BIT
My guess is that the As Long might be the culprit here - it probably is a bit integer on 32 bit and 64 bit on 64 bit...
Did you try using "Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableW" "
The program executing that script, is that a 64-bit application? If that's the case it is possible that this application cannot load 32-bit DLLs. (That would be the second problem)
To track down the first problem, load shell32.dll explicitly using LoadLibrary (don't use the full path!) and then use GetModuleFileName to get the full file name loaded. There can be all kinds of things responsible for messing with DLL paths. (WOW layer, UAC, path variable, ...)
If that actually works, you can try using Dependency Walker to see if FindExecutable is exported, but I think you'll run into problems before that.
I don't need this declaration because it only makes my code big and unreadable.
Is there a way to make Visual Studio (VS) not add it automatically. Every time I remove it, it is added back by VS.
Function DoStuff(Tom As String)
NOT
Function DoStuff(ByVal Tom As String)
It actually makes your code more clear to the non-believers. I don't think they hurt readability of the code, rather the opposite.
Install Visual Studio 2010 Service pack 1. It doesn't insert the ByVal declaration.
Turn off pretty formatting at Tools/Options/Text Editor/Basic/VB Specific/Pretty Listing (reformatting) of code.