2011-03-31 135 views
24

我在Excel 2007中開發的VBA應用程序,它包含以下代碼,以允許從Shell32.dll訪問ShellExecute功能:我應該如何讓我的VBA代碼與64位Windows兼容?

Private 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, ByVal nShowCmd As Long) As Long 

我最初說:

顯然,應用程序將不會 在64位版本的Windows (仍在使用32位Office 2007)上編譯。我假設這是因爲 Declare聲明需要更新。

我讀過,Office 2010的推出 一個新的VBA運行時(VB7),而這 具有可在Declare語句中使用 一些新的關鍵字,允許它 正常在64位Windows上工作。 VB7也有新的預定義的編譯器 常量來支持條件 編譯,其中無論是舊的或新的 聲明將被使用, 根據應用 是否在32位或64位Windows上運行。

但是,由於我堅持2007年辦公室 我需要一個替代解決方案。 我有什麼選擇? (我真的 寧願不必發佈2 我的應用程序的獨立版本,如果 在所有可能)。

然而,按照以下大衛的回答,我弄錯了,其中我Declare聲明將無法工作情況。在64位Windows 64位上,Office 2010無法正常工作的唯一情況是。所以,Office 2007不是問題。

回答

44

我已經對人們遇到了這個問題32個和64位版本在與Office新的64位機2010

所有我需要做的就是這樣的代碼更改行:

Private 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, ByVal nShowCmd As Long) As Long 

這樣:

#If VBA7 Then 
    Private Declare PtrSafe 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, ByVal nShowCmd As Long) As Long 
#Else 
    Private 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, ByVal nShowCmd As Long) As Long 
#End If 

你當然會想,以確保您使用的庫可在兩臺機器上,但到目前爲止,沒有我用一直是一個難題。

請注意,在舊的VB6中,PtrSafe甚至不是一個有效的命令,所以它會以紅色顯示,就好像您有一個編譯錯誤,但它實際上不會給出錯誤,因爲編譯器會跳過if塊的第一部分。

code Appearance

應用程序使用上面的代碼編譯和完美的Office 2003,2007年運行,和2010年32位和64位。

+1

如果問題是64位辦公室,那麼VBA7不是答案。你需要win64編譯常量。 VBA7仍然可以在Office 2010 32位上運行。 – 2012-07-18 23:44:43

+2

@AnonymousType這些指令正是從VB7和PtrSafe聲明的MSDN文檔:http://msdn.microsoft.com/en-us/library/ee691831.aspx需要使用PtrSafe來自使用VB7,而不是在64位系統上使用Office。 64個系統只支持VB7只是巧合,所以這一舉兩得。 – Alain 2012-07-19 00:46:23

+3

'#if Win64'僅在需要加載兩個不同的dll或在32位和64位系統上使用具有不同簽名的函數的奇怪情況下才需要。爲了使傳統電子表格在強制使用VB7的64位計算機上工作,沒有必要。 32位Office 2010有意與所有傳統VB6電子表格兼容,無需任何修改(根據文檔)。 – Alain 2012-07-19 01:05:01

4

Office 2007只有32位,所以沒有問題。您的問題只出現在具有32位和64位版本的Office 64位上。

當您只有Office 2007時,您無法指望用戶支持64位Office 2010。解決方案是升級。

如果你擁有的唯一DeclareShellExecute那麼你將不會有太大,一旦你得到64位Office保持做的,但它不是真的可行,以支持用戶的時候可以運行的程序,你船!想想他們在報告錯誤時會做什麼?

+0

感謝。 「64位」的問題是由一位同事報道的,後者隨後離開了大樓,所以細節很粗略,我顯然錯誤地填充了空白。 – 2011-03-31 22:21:54

+0

所以,澄清...我現有的Declare語句將在32位和64位Windows上的Office 2007中工作?並將在32位Windows上的Office 2010中工作?但是對於64位Windows上的Office 2010,我需要使用新的VB7功能 - 這意味着我需要我的應用程序的2010特定版本?是否沒有辦法擁有支持所有版本的向後兼容的東西?(以前的Office版本通常都是這種情況)? – 2011-03-31 22:25:29

+0

你應該可以擁有你的代碼的單一版本,但你真的想自己測試一下。 – 2011-03-31 22:32:04

0

這個答案很可能是錯的,上下文錯了。我認爲現在VBA現在運行在CLR上,但事實並非如此。無論如何,這個回覆可能對有人有用。或不。


如果您運行Office 2010 32位模式,那麼它與Office 2007相同(「問題」是Office以64位模式運行)。這是執行上下文(VBA/CLR)的位,這在這裏很重要,加載的VBA/CLR的位數取決於主機進程的位數。

之間64分之32位呼叫,最顯着的事情出差錯使用longint(恆定大小在CLR)代替IntPtr(動態大小的基於位元)爲「指針類型」。

ShellExecute函數具有的簽名:

HINSTANCE ShellExecute(
    __in_opt HWND hwnd, 
    __in_opt LPCTSTR lpOperation, 
    __in  LPCTSTR lpFile, 
    __in_opt LPCTSTR lpParameters, 
    __in_opt LPCTSTR lpDirectory, 
    __in  INT nShowCmd 
); 

在這種情況下,重要的是HWND被IntPtr(這是因爲一個HWND是一個「處理」是void* /「void指針」)和不是long。以pinvoke.net ShellExecute爲例。 (雖然一些「解決方案」在pinvoke.net上是陰暗的,但它最初是一個很好的選擇)。

快樂編碼。


至於任何「新的語法」,我不知道。

+0

問題是我認爲的VBA。 – 2011-03-31 22:14:23

+0

@David Heffernan謝謝。我很困惑它與VB.NET/VSTO。 – 2011-03-31 22:22:50

2

使用PTRSAFE,看看,關於Excel 2010中

工作更正錯字從書「的Microsoft Excel 2010強大的編程與VBA」。

#If vba7 and win64 then 
    declare ptrsafe function .... 
#Else 
    declare function .... 
#End If 

VAL(application.version)> 12.0將無法​​工作,因爲Office 2010使用我的內部工具有

3

實際上,檢查32位或64位平臺的正確方法是使用在所有版本的VBA(16位,32位和64位版本)中定義的Win64常量。

#If Win64 Then 
' Win64=true, Win32=true, Win16= false 
#ElseIf Win32 Then 
' Win32=true, Win16=false 
#Else 
' Win16=true 
#End If 

資料來源:編譯VBA幫助常數

+0

這就是系統拱不Excel的btw – HaveAGuess 2013-10-14 17:25:16

+0

@HaveAGuess根據微軟[文檔] (https://msdn.microsoft.com/en-us/library/office/gg264421.aspx#Anchor_1)它確實是Office體系結構,而不是系統體系結構。引用文章:「Win64條件編譯常量用於確定Office的哪個版本(32位或64位)正在運行。」 – pyskell 2017-03-23 15:50:55

4

,我發現這個代碼(注意,有些Long更改爲LongPtr):

Declare PtrSafe Function ShellExecute Lib "shell32.dll" _ 
Alias "ShellExecuteA" (ByVal hwnd As LongPtr, ByVal lpOperation As String, _ 
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As _ 
String, ByVal nShowCmd As Long) As LongPtr 

來源:http://www.cadsharp.com/docs/Win32API_PtrSafe.txt

+0

謝謝。好資源。 – 2015-11-02 16:10:44

相關問題