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
Related
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
I have created a C# .NET DLL with Release/AnyCPU as per http://www-01.ibm.com/support/docview.wss?uid=swg21230705 and successfully registered it for COM Interop.
When I open my 32bit Excel on a 32bit Windows 10, and use the code
Private Sub CommandButton1_Click()
Dim obj As Variant
Set obj = CreateObject("MyTest")
MsgBox obj.AppendStr("This is")
End Sub
it returns the expected values. When I open 32bit Excel on a 64 bit Windows 8.1, and use the same code, it also returns the expected values. The same goes for a similarly crafted VB6 executable deployed on both systems.
But when I try the same from Notes 32 bit using the code
Sub Click(Source As Button)
Dim obj As Variant
set obj = CreateObject("MyTest")
MsgBox obj.AppendStr("This is")
End Sub
it returns the expected values on a 32 bit Windows 10
it throws the error "Could not create automation object" on a 64 bit Windows 8.1
Furthermore, and this is the most interesting part for me, it throws "Could not create automation object" when run as a LotusScript http agent on the Domino 64 bit server on a 64 bit Windows Server system.
Do you have any ideas how I could get the DLL function call to work with both 32 as well as 64 bit Lotus Domino Server?
Or are there any other ways to call a single function in my C# DLL from Notes, which takes a single string as parameter and returns a byte array? (e.g. through a Java agent, through a Domino shell object, or both?)
I just found the solution, and it wasn't a Domino problem at all. The linked tutorial is for pre-64bit systems and says:
To make the objects in this DLL accessible via the COM interface, enter the following command:
regasm MyTest.dll
Since the introduction of AMD64, you have to read this step as follows:
To make the objects in this DLL accessible via the COM interface for both 32 bit and 64 bit applications, enter BOTH the following commands:
%Windir%\Microsoft.NET\Framework\<version>\regasm MyTest.dll
%Windir%\Microsoft.NET\Framework64\<version>\regasm MyTest.dll
I only did the first, which made it work for 32bit, but not for 64bit.
To answer the question in a technical aspect, you can call yout 32 bits DLL by copying it to Windows\SysWow64.see Can a 64 bit EXE link against 32-bit DLLs? for more details.
To answer your need we just need to transform a string to byte array.
You can do this in java and use ls2j to call it.
I also think to use the lib of native consumer to dothis.
Look also at https://www.experts-exchange.com/questions/23120423/Using-NotesStream-to-convert-a-string-to-a-byte-array.html it give you a lotuscript solution.
I was trying to get the default printer through VBA and I came across the Windows API GetProfileString function:
GetProfileString documentation
On one website I found a working example that retrieves the printer name:
returnedChars = GetProfileString("Windows", ByVal "device", vbNullString, printerName, Len(printerName))
The site I linked states that on Windows Server 2003, Windows XP and Windows 2000 (and later versions as well, I assume - the documentation probably isn't up-to-date) the values that GetProfileString return may be taken from the registry if certain conditions are met. I opened the Registry Editor and found the correct section - ...\IniFileMapping\win.ini\Windows. To my surprise, there is no key named device. I re-read the documentation a couple of times, but it didn't help. I don't have a corresponding section in my win.ini file.
Can anyone explain how this function exactly works? It looks like it could come in handy in numerous situations, so it would be nice to know how to use it properly.
This function is one giant backwards compatibility shim. The idea is for legacy code to continue working by picking up values that were moved to the registry when Windows moved from 16-bit to 32-bit.
The documentation makes this pretty clear:
Note This function is provided only for compatibility with 16-bit Windows-based applications, therefore this function should not be called from server code. Applications should store initialization information in the registry.
The message is clear. Do not use this function.
You ask how the function works, when it reads from the registry. That is covered in some detail by the documentation and I don't think there's much to be gained by trying to re-phrase that documentation.
It would be nice to know how to use it properly.
Use the function properly by never calling it!
This problem is pretty self explanatory. Here are the details: I'm trying to include freeglut and glew in Visual Studio 2012 on Windows 8. I'm on a 64 bit system, so I thought I needed to put glew32.dll in my 64 bit system folder. I tried that and receive the following error:
"The application was unable to start correctly (0xc000007b). Click OK to close the application."
Which I've interpreted as I'm trying to put a 32 bit dll in the 64 bit folder or vice-versa.
Just for laughs, I tried putting the file in System32, but of course, it just told me the file wasn't on my computer. Any suggestions?
EDIT* May I also add that some of the set up for this was NOT the same as it would have been on Windows 7 or Visual Studio 2010 or earlier. I may have missed something because I kind of winged it using the search function combined with some documentation I found on various websites. (i.e the lib and include folders are no longer in the same place)
EDIT2* I'm sure this can probably be derived, but I want to add it anyway for clarity: If I removed the dependency for glew32.lib and comment out any code using glew.h, the window forms as it should. I don't think my source code is needed seeing as I'm 99% sure this is not a code issue, but if anyone wants to see it, let me know and I'll attach it.
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.