64-bit VBA

Now that I'm upgraded to 64-bit, I need to update some of my Declare statements.
However, I am also going to make sure this is backward compatible so those still on the 32-bit systems can run it.  I think I can handle that part with the #IF declaration but tell me if I'm handling that wrong.

So all I did for now is copy the 32-bit declare into the 64-bit section and changed the kernel reference.  As expected, it doesn't quite work.  What do I need to fix?

Basically, I'm opening a DOS window and monitoring it to find out when it closes so I can pop up a message box.  That all works great in the 32-bit arena.
 
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" ( _
        ByVal hProcess As Long, _
        lpExitCode As Long) As Long
    Private Declare PtrSafe Function OpenProcess Lib "kernel32" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long, _
        ByVal dwProcessId As Long) As Long
    Private Const STILL_ACTIVE = &H103
    Private Const PROCESS_QUERY_INFORMATION = &H400
    Private Declare PtrSafe Function CloseHandle Lib "kernel32" ( _
        ByVal hObject As Long) As Long
#Else
    Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel64" ( _
        ByVal hProcess As Long, _
        lpExitCode As LongPtr) As Long
    Private Declare PtrSafe Function OpenProcess Lib "kernel64" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long, _
        ByVal dwProcessId As Long) As Long
    Private Const STILL_ACTIVE = &H103
    Private Const PROCESS_QUERY_INFORMATION = &H400
    Private Declare PtrSafe Function CloseHandle Lib "kernel64" ( _
        ByVal hObject As Long) As Long
#End If

Open in new window

LVL 22
rspahitzAsked:
Who is Participating?
 
rspahitzConnect With a Mentor Author Commented:
OK...I figured it out...
from this link:

http://msdn.microsoft.com/en-us/library/gg264614.aspx

I was checking for 32-bit first, and if not then using 64-bit.
Apparently the current 64-bit version is compatible with 32-bit so the win32 directive constant is set to yes...that led me to believe that I was running a 32-bit version.

by checking for win64 first, it properly used the LongPtr variables, so like this for the declares and dims:

    #If Win64 Then
        Dim hProcess As LongPtr
        Dim lR As LongPtr
    #Else
        Dim hProcess As Long
        Dim lR As Long
    #End If

Since I'm assuming it will never use 16-bit, I don't need the If Win32 check.

THANKS ALL!
0
 
SiddharthRoutConnect With a Mentor Commented:
An interesting read for you.

http://msdn.microsoft.com/en-us/library/ee691831.aspx

Read the section Application Programming Interface Compatibility

Sid
0
 
Rory ArchibaldConnect With a Mentor Commented:
Also have a look here: http://www.jkp-ads.com/Articles/apideclarations.asp
Jan Karel (and RdB) have done a few conversions and there's a general guide as to what does and what doesn't need conversion.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
rspahitzAuthor Commented:
Cool! and sure enough, the 3 I'm using aren't listed.  I suppose I could guess and see what happens...

Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel64" ( _
        ByVal hProcess As Long, _ <= LongPtr***************
        lpExitCode As Long <= LongPtr***************) As Long

    Private Declare PtrSafe Function OpenProcess Lib "kernel64" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long<= LongPtr***************, _
        ByVal dwProcessId As Long) As Long

    Private Declare PtrSafe Function CloseHandle Lib "kernel64" ( _
        ByVal hObject As Long<= LongPtr***************) As Long
0
 
Rory ArchibaldCommented:
That looks like what I would guess too. :)
0
 
rspahitzAuthor Commented:
Digging into the MS help files, it looks like it should be this, but it still doesn't work:
( e.g. http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx )

    Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel64" ( _
        ByVal hProcess As LongPtr, _
        lpExitCode As LongPtr) As Boolean

    Private Declare PtrSafe Function OpenProcess Lib "kernel64" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Boolean, _
        ByVal dwProcessId As Long) As LongPtr

    Private Declare PtrSafe Function CloseHandle Lib "kernel64" ( _
        ByVal hObject As LongPtr) As Boolean
0
 
SiddharthRoutCommented:
Unfortunately I don't have a 64 bit system so I can't test that for you :)

This is where I gracefully retreat :)

Sid
0
 
rspahitzAuthor Commented:
I'm not quite sure how to test these other than to check the return code I guess...but will it tell me if it failed to find it?
0
 
Rory ArchibaldConnect With a Mentor Commented:
I think it should still be kernel32.dll not kernel64.dll (missed that in your first posting)
0
 
rspahitzAuthor Commented:
odd...it seemed that the 64-bit stuff is not working so I added a message box and it tells me it's running the 32-bit version!

So now the question is why it's no longer working with the 32-bit version???
0
 
rspahitzAuthor Commented:
and ok about kernel32...maybe it didn't complain because it's running 32-bit...
and yet computer reports 64-bit OS in my computer.

but when I run this:


    #If Win32 Then
        MsgBox "win32"
#Else
        MsgBox "win64"
#End If

It says 32-bit...is there a separate 32-bit Office, even if you run 64-bit OS?  how do I check?
0
 
Rory ArchibaldCommented:
You only need the revised API if you are running 64 bit Office, not 64 bit windows.
0
 
rspahitzAuthor Commented:
hmmm...apparently work gave me the 32-bit office 2010, I guess.

so why is it not working compared to Office 2003?  those APIs shouldn't change, right? they're not office APIs...
0
 
rspahitzAuthor Commented:
(oh and office 2003 was on the XP machine, not this Win7-64 machine.)
0
 
rspahitzAuthor Commented:
FYI...I'll be off the board until Sunday so I'll get back to this next week and see if we can solve it, although it seems that the problem is not what I thought and may not be related to 64-bit.
0
 
Rory ArchibaldCommented:
If you can post full code I can test on office 32 bit on win 7 64 bit.
0
 
rspahitzAuthor Commented:
Let me drop what I think are the relevant pieces here
'Debug.Print "running as win32"
    Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" ( _
        ByVal hProcess As Long, _
        lpExitCode As Long) As Boolean
    Private Declare PtrSafe Function OpenProcess Lib "kernel32" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Boolean, _
        ByVal dwProcessId As Long) As Long
    Private Declare PtrSafe Function CloseHandle Lib "kernel32" ( _
        ByVal hObject As Long) As Boolean
    Private Declare PtrSafe Function GetLastError Lib "kernel32" () As Long
#Else
    'Debug.Print "running as win64"
    Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" ( _
        ByVal hProcess As LongPtr, _
        lpExitCode As LongPtr) As Boolean
    Private Declare PtrSafe Function OpenProcess Lib "kernel32" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Boolean, _
        ByVal dwProcessId As Long) As LongPtr
    Private Declare PtrSafe Function CloseHandle Lib "kernel32" ( _
        ByVal hObject As LongPtr) As Boolean
    Private Declare PtrSafe Function GetLastError Lib "kernel32" () As Long
#End If
Private Const STILL_ACTIVE = &H103
Private Const PROCESS_QUERY_INFORMATION = &H400

Private Function WaitForCompletion(dblWindowID As Double) As Boolean
    ' see if specified window is still running
    Dim bWaitForCompletion As Boolean
    #If Win32 Then
        Dim hProcess As Long
        Dim lR As Long
    #Else
        Dim hProcess As LongPtr
        Dim lR As LongPtr
    #End If
    Dim lTimeStart As Long
    
    Const TimeOut As Long = 10000 ' 10 seconds

    bWaitForCompletion = True ' for now just assume it is done...will require a separate process check.
    
    lTimeStart = Now()

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, dblWindowID)
    If hProcess <> 0 Then
        Do 'ShellExecute(dblWindowID) <> 0    ' Has Shelled program finished?
            GetExitCodeProcess hProcess, lR
            
            If lR = 0 Then
                Debug.Print GetLastError()
            Else
                Debug.Print lR;
            End If
            DoEvents
            If Now - lTimeStart > TimeOut Then
                Exit Do
            End If
        Loop While lR = STILL_ACTIVE
    End If
    Debug.Print
    
    WaitForCompletion = bWaitForCompletion
End Function

sub RunFTPBatchFile()
    Dim strFullFTPCommandLine As String
    Dim bTransferCompleted As Boolean
    Dim dblWindowID As Double
...

            strFullFTPCommandLine = "cmd /c ""C:\Temp\abc.bat"" > tempout.txt"
            dblWindowID = Shell(strFullFTPCommandLine) 
            bTransferCompleted = False
            Do Until bTransferCompleted
                bTransferCompleted = WaitForCompletion(dblWindowID)
            Loop
...
end sub

Open in new window

I hope I got all the pieces.
0
 
rspahitzAuthor Commented:
lost this as the first line:

#If Win32 Then
0
 
rspahitzAuthor Commented:
What should happen is that the VBA will wait until the window is close.  so you can change the /c to /k and it should wait until you Exit the DOS window (Exit command or close it), then maybe show a message box.

What's happening is that the GetExitCodeProcess is returning 0 in lR variable, which apparently means there was an error.  But when I check the error information with GetLastError, it also shows 0 (although I have no idea what it is supposed to give me.)

When I used to run it on XP, the code would wait until the DOS window closed, then complete the procedure.
0
 
Rory ArchibaldConnect With a Mentor Commented:
Your code works fine for me after I remove the PtrSafe parts of the #Win32 declares.
0
 
rspahitzConnect With a Mentor Author Commented:
If I remove PtrSafe from the 32-bit declares, my lines turn red and I get a message on compile:

"The code in this project must be updated for use on the 64-bit systems.
Please review and update Declare statements and then mark then with
the PtrSafe attribute."

:(
0
 
rspahitzAuthor Commented:
Those links inspired me to find the right webpages to get the answer so I'm awarding most of the points there.
0
 
Zack BarresseCEOCommented:
As a side note, you only need to declare Long variables as LongPtr if it references memory, as it's a different structure, otherwise a Long will work just fine in 64 bit.

Also, a bit of a misguidance (at least I think so), is the Win64 compilation bit is not checking for a 64 bit OS, but for 64 bit Office.  I think it's REALLY confusing the way they did that, and I know many who have requested it either be changed or updated.
0
 
rspahitzAuthor Commented:
Thanks FireFytr, and welcome :)
0
 
rspahitzAuthor Commented:
Thanks all...awarded 100 pts to Sid and rest to Rory for the extended effort :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.