我正在尝试传递受密码保护的pdf,而我正努力使两个不同的代码段可以正常工作。首先是传递此函数的路径,该函数将打开pdf并查找密码框,如果没有密码框,则返回布尔值False。
ShellExecute Application.hwnd, "Open", pdfPath, vbNullString, "P:\", SW_SHOWNORMAL
parentwindow = 0
DoEvents
parentwindow = FindWindow("#32770", "Password")
If parentwindow = 0 Then
OpenLockedPdf = False
'SendMessage Application.hwnd, WM_CLOSE, 0, 0
'ShellExecute Application.hwnd, "Close", pdfPath, vbNullString, "P:\", SW_SHOWNORMAL orig
Exit Function
Else:
OpenLockedPdf = True ' delete this if the function exits here
End If
If parentwindow <> 0 Then
'Find the handle of the first child window (it is a group box).
timeCount = Now()
Do Until Now() > timeCount + TimeValue("00:00:05")
firstChildWindow = 0
DoEvents
firstChildWindow = FindWindowEx(parentwindow, ByVal 0&, "GroupBox", vbNullString)
If firstChildWindow <> 0 Then Exit Do
Loop
'Find the handle of the subsequent child window (it is the text box for filling the password).
If firstChildWindow <> 0 Then
timeCount = Now()
Do Until Now() > timeCount + TimeValue("00:00:05")
secondChildFirstWindow = 0
DoEvents
secondChildFirstWindow = FindWindowEx(firstChildWindow, ByVal 0&, "Button", "Cancel")
If secondChildFirstWindow <> 0 Then Exit Do
Loop
'The handle was found, so...
If secondChildFirstWindow <> 0 Then
'Press the Cancel button
SendMessage secondChildFirstWindow, BM_CLICK, 0, ByVal 0&
End If
End If
End If
End Function
第二种尝试方法:How to check security of PDF file from excel?
首先存在的问题是,当我逐步执行它时,它会打开并进行检查,但是我必须再次手动单击vba控制台以单击下一步以继续执行该过程。当我单击Excel vba控制台上的播放按钮时,它不起作用!
[当我尝试第二种方法时,它实际上没有检测到pdf上的密码保护。
[如果有人对如何使第一个或第二个代码起作用有任何建议,请告诉我。
谢谢。
请尝试以下操作:
Option Explicit
Private 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
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, _
ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, _
ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As Long
Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, _
ByVal lpString As String, ByVal cch As Long) As Long
Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal wCmd As Long) As Long
Private Const BM_CLICK = &HF5
Private Const SW_SHOWMAXIMIZED = 3
Private Const GW_HWNDNEXT = 2
Private Const WM_LBUTTON_DOWN = &H201
Sub testProtection()
Debug.Print passwordProtected("C:\your protected pdf path")
Debug.Print passwordProtected("C:\your unprotected pdf path")
End Sub
Private Function passwordProtected(pdfPath As String) As Boolean
Dim readerDCHwnd As LongPtr, parentwindow As LongPtr, iCount As Long
Dim groupBoxHwnd As LongPtr, butHwnd As LongPtr
Const pdfApp As String = "Adobe Acrobat Reader DC"
ShellExecute Application.hwnd, "Open", pdfPath, vbNullString, "P:\", SW_SHOWMAXIMIZED
readerDCHwnd = findWindowByPartialTitle(pdfApp)
If readerDCHwnd = 0 Then
Do While readerDCHwnd = 0
iCount = iCount + 1
Application.Wait (Now + TimeValue("0:00:1"))
DoEvents
readerDCHwnd = findWindowByPartialTitle(pdfApp)
If iCount >= 5 Then MsgBox pdfApp & " handler could not be obtained in 4 seconds..." & vbCrLf & _
"If your pdf application is not " & pdfApp & " then update pdfApp constant.", _
vbInformation, "No AR handler": Exit Function
Loop
End If
iCount = 0
Do While parentwindow = 0
iCount = iCount + 1
Application.Wait (Now + TimeValue("0:00:1"))
DoEvents
parentwindow = FindWindow("#32770", "Password")
If iCount >= 4 Then passwordProtected = False: Exit Function
Loop
groupBoxHwnd = FindWindowEx(parentwindow, ByVal CLngPtr(0), "GroupBox", vbNullString)
groupBoxHwnd = FindWindowEx(parentwindow, ByVal CLngPtr(0), "GroupBox", vbNullString)
butHwnd = FindWindowEx(groupBoxHwnd, ByVal 0&, "Button", "Cancel")
If butHwnd <> 0 Then
SendMessage butHwnd, WM_LBUTTON_DOWN, 0&, 0&
SendMessage butHwnd, BM_CLICK, 0, 0&
passwordProtected = True
Else
passwordProtected = False
End If
End Function
Function findWindowByPartialTitle(ByVal sCaption As String, Optional strSecond As String) As LongPtr
Dim lhWndP As LongPtr
Dim sStr As String
findWindowByPartialTitle = CLngPtr(0)
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText lhWndP, sStr, Len(sStr)
If Len(sStr) > 0 Then sStr = left$(sStr, Len(sStr) - 1)
If InStr(1, sStr, sCaption) > 0 And _
IIf(strSecond <> "", InStr(1, sStr, strSecond) > 0, 1 = 1) Then
findWindowByPartialTitle = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
我为Adobe Acrobat Reader DC测试了它。如果您的默认.pdf应用程序不同,则必须相应地修改常数pdfApp
。我认为,实际上,它也可以从Registry获得。首次打开pdf应用程序后,将更改其标题,同时保留打开的文档的名称。这就是为什么FindWindow API将不返回任何内容,而您必须使用findWindowByPartialTitle
的原因。这里不使用第二个参数,但是可以用于更复杂的搜索...