我们在 Word 宏中有 VBA 代码,用于下载一个或多个文档,然后使用 Windows 功能打印它们ShellExecuteEx
。该代码在 Windows 2000、XP 和 7(32 位和 64 位)上的 Word 版本 97、2000、2003、2007 和 2010(32 位)中成功运行。
但在 64 位 Word 2010 和 2013 中调用ShellExecuteEx
失败。我们更新了MSDN 上记录并在 Win32API_PtrSafe 文件中指定的VBA7(64 位)声明。例如:
#If VBA7 Then
Type SHELLEXECUTEINFO
cbSize As Long
fMask As Long
hwnd As LongPtr
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As String
nShow As Long
hInstApp As LongPtr
lpIDList As LongPtr
lpClass As String
hkeyClass As LongPtr
dwHotKey As Long
hIcon As LongPtr
hProcess As LongPtr
End Type
Declare PtrSafe Function ShellExecuteEx Lib "shell32.dll" Alias "ShellExecuteExA" _
(sei As SHELLEXECUTEINFO) As Boolean
#End If
用法是这样的:
Dim bReturn As Boolean
Dim sei As SHELLEXECUTEINFO
With sei
.cbSize = Len(sei) ' size of the object
.fMask = SEE_MASK_NOCLOSEPROCESS ' indicate that we want a hProcess back
.hwnd = GetDesktopWindow() ' the window we are calling from
.lpVerb = "print" ' print the file
.lpFile = lpFile ' the file we want to print
.lpParameters = vbNullString ' no parameters because its a file
.lpDirectory = vbNullString ' use the current dir as working dir
.nShow = SW_HIDE ' state of the window to open
End With
bReturn = ShellExecuteEx(sei)
If bReturn Then
WaitForSingleObject sei.hProcess, 5000
CloseHandle sei.hProcess
DoEvents
Else
MsgBox "ShellExecuteEx failed with code: " & Err.LastDllError
End If
在 32 位字中它可以工作,但在 64 位字中调用ShellExecuteEx
总是失败,返回 5 (SE_ERR_ACCESSDENIED)。我尝试了一系列标志值fMask
(包括 SEE_MASK_NOASYNC),尝试不指定 的值hwnd
和不同的值nShow
,所有这些都具有相同的失败结果。
更简单的ShellExecute
函数在 32 位和 64 位 Word 中都有效,但它太不灵活了。我们想要使用ShellExecuteEx
它是因为它在打印多个文档时更好:它使我们能够等待打印应用程序(Word、Adobe Reader 等)在发送另一个打印请求之前准备好。否则,如果应用程序未准备好,打印请求将失败。(我尝试在打印请求之间等待几秒钟,但这并不可靠。)
为什么ShellExecute
打印文件但ShellExecuteEx
由于访问被拒绝而失败?