TommySzalapski
asked on
VBA or VBS enumerate all open Acrobat Reader documents
I want to (in some type of code) find all the pdf files that are open in Acrobat Reader (I only have Reader)
Since I don't have Acrobat Pro, I can't get any API calls to work (e.g. GetObject(, "AcroExch.App"))
The solution to the related link (searching running tasks) doesn't work since it only finds the first one, and that only if the pdf was double clicked (since it parses the shell command that started the process).
I need the entire path of the files. I had the idea to try to capture it from the open windows, but don't know how well that would work since only the file name shows and it's formatted differently in XP and 7.
Any ideas?
Since I don't have Acrobat Pro, I can't get any API calls to work (e.g. GetObject(, "AcroExch.App"))
The solution to the related link (searching running tasks) doesn't work since it only finds the first one, and that only if the pdf was double clicked (since it parses the shell command that started the process).
I need the entire path of the files. I had the idea to try to capture it from the open windows, but don't know how well that would work since only the file name shows and it's formatted differently in XP and 7.
Any ideas?
There is one way I can think of...
If I close all the pdf one by one then I can get you the path of all the pdf's. I can then reopen them at the end. Would that help?
Sid
If I close all the pdf one by one then I can get you the path of all the pdf's. I can then reopen them at the end. Would that help?
Sid
ASKER
Closing is fine. Don't bother reopening, I can do that. The version for Word and Excel closes them too (since that's the best way to iterate through Excel instances). Closing them doesn't change the command line for the process though.
Interested to see what you can up with.
Interested to see what you can up with.
ASKER
came* up with
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Sorry you need to run the last Sub Sample. Also press Ctl G to see immediate window where the output will be generated.
Sid
Sid
ASKER
Did you ever find a way to get the path?
No Tommy. Even when I close the 1st pdf file, the Acro Exe still refers to the first file!!! I could get the name of all the pdf's though...
Still trying to figure out other way...
Sid
Still trying to figure out other way...
Sid
ASKER
That's because you are looking at the command that started Acrobat.
If you start Acrobat by itself and then open pdfs, the command shell string won't give you any file at all.
If you start Acrobat by itself and then open pdfs, the command shell string won't give you any file at all.
Exactly but the API that I know can get the path of the Exe and that is not that we are looking at. So I am still thinking of an alternative to get the paths from the window name.
Sid
Sid
OPTION 1
Ok I have been experimenting and I got stuck. But I am close...
Here is an example that I am trying to incorporate for just one pdf file. If this works then I will be able to get the path for all the PDF in the loop.
Under the file menu of Adobe is the submenu "properties" I am able to click that. I am just stuck as to how to retrieve the value of "Location". See snapshot.
Sid
Code Used
Ok I have been experimenting and I got stuck. But I am close...
Here is an example that I am trying to incorporate for just one pdf file. If this works then I will be able to get the path for all the PDF in the loop.
Under the file menu of Adobe is the submenu "properties" I am able to click that. I am just stuck as to how to retrieve the value of "Location". See snapshot.
Sid
Code Used
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const WM_GETTEXT = &HD
Const WM_GETTEXTLENGTH = &HE
Private Sub Command_Click()
Dim parenthwnd As Long
'~~> Testing with 1.pdf
parenthwnd = FindWindow(vbNullString, "1.pdf - Adobe Reader")
'~~> Bringing the window to the foreground
SetForegroundWindow parenthwnd
'~~> Stimulating Alt F + R
SendKeys "%F", True
SendKeys "R", True
'~~> Getting the handle of the "Document Properties"
parenthwnd = FindWindow(vbNullString, "Document Properties")
'~~> The code works till here
End Sub
Untitled.jpg
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
You mean something like this?
egl1044-411890.flv
egl1044-411890.flv
ASKER
I don't really feel like waiting for an 11MB video to download so I can watch it full screen but if it's getting the path and filename of all pdfs open in Acrobat Reader, then yes. I'm not really looking for a video though, I'm looking for code that I can run. Can you post the code you used?
ASKER
Yes. That looks like what I want. Can you post the code, please?
Even I am curious to see that code.
Sid
Sid
ASKER
egl1044?
How do I contact Southmod?
Sid
Sid
Much appreciated modus_in_rebus :)
Sid
Sid
Did you get a solution for this yet?
ASKER
No. I've found programs that find all the open file handles and list them (Process Hacker etc), but none of them have an API that let me get the list programmatically. This may be my best option so far.
I've also been pointed to some Windows API calls beginning with NtQuerySystemInformation but I haven't had the time to try to get them working in VBScript yet.
I've also been pointed to some Windows API calls beginning with NtQuerySystemInformation but I haven't had the time to try to get them working in VBScript yet.
Do you want me to create library that you can use from script?
ASKER
Sure.
Here play with this version until I finish the library. Let me know if you find bugs... If you need more explanation of how to use the library let me know example script version in code section.
' AdobePDFX32.DLL
' Version 1.0 Beta
' egl1044
' acroPDF.VBS
Dim AcrobatCore '// AdobePDFX32
Dim AcroProcess '// IAcrobatProcess
Dim AcroProcessCol '// IAcrobatProcessCollection
Dim AcroPDFFile '// IAcrobatPDFFile
Dim AcroPDFFileCol '// IAcrobatPDFFileCollection
Dim AcroProcessRef '// IAcrobatProcess (user referenced)
Sub SetObjectInitialStates
Set AcrobatCore = Nothing
Set AcroProcess = Nothing
Set AcroProcessCol = Nothing
Set AcroPDFFile = Nothing
Set AcroPDFFileCol = Nothing
Set AcroProcessRef = Nothing
End Sub
'// Set all object variables to Nothing
Call SetObjectInitialStates
'// Create Core object
Set AcrobatCore = CreateObject("AdobePDFX32.Core")
'// Get a collection of Acrobat processes
Set AcroProcessCol = AcrobatCore.GetAcrobatProcesses
'// Enumerate the IAcrobatProcessCollection collection
'// There can be atleast two available, the IAcrobatProcess interface
'// that you should reference should have a valid MainWindowHandle
'// property not equal to zero.
Msgbox "Acrobat Reader Process Count: " & AcroProcessCol.Count
For Each AcroProcess In AcroProcessCol
'// Reference the interface on condition.
If AcroProcess.MainWindowHandle <> 0 Then
Set AcroProcessRef = AcroProcess
Exit For
End If
Next
'// Display the IAcrobatProcess Interface referenced above.
If Not AcroProcessRef Is Nothing Then
Msgbox ( AcroProcessRef.Name & vbCrlf & AcroProcessRef.ProcessId & vbCrlf & AcroProcessRef.MainWindowHandle)
End If
'// Obtain the list of open PDF files
If Not AcroProcessRef Is Nothing Then
'// Get a collection of IAcrobatPDFFile
Set AcroPDFFileCol = AcrobatCore.GetAcrobatPDFFiles(AcroProcessRef)
'// Enumerate the IAcrobatPDFFileCollection collection
Msgbox "Acrobat Reader Open PDF Count: " & AcroPDFFileCol.Count
For Each AcroPDFFile In AcroPDFFileCol
'// Display the FullName of each opened PDF document.
Msgbox ( AcroPDFFile.FullName )
Next
End If
AdobePDFX32.dll
Pleased to announce Acroof 1.0.0.0 Release Enjoy Tom
changes_acroof
Acroof Revision History
Acroof 1.0.0.0: 4/5/2011 - Stable: XP,Vista,Windows 7
- New: Added new detection scheme
- New: Added Win32 file path support for Vista or later operating systems.
- New: Added Win32 file path support for Window XP operating system.
- New: Added Win32 file path support for network paths.
- New: Added MUP and LanmanRedirector support in Windows XP operating system.
- New: Added runtime functionality verification
- Fix: Removed various class/interfaces no longer required with the new detection scheme.
- Some minor changes and improvements
changes_acroof
Acroof Revision History
Acroof 1.0.0.0: 4/5/2011 - Stable: XP,Vista,Windows 7
- New: Added new detection scheme
- New: Added Win32 file path support for Vista or later operating systems.
- New: Added Win32 file path support for Window XP operating system.
- New: Added Win32 file path support for network paths.
- New: Added MUP and LanmanRedirector support in Windows XP operating system.
- New: Added runtime functionality verification
- Fix: Removed various class/interfaces no longer required with the new detection scheme.
- Some minor changes and improvements
Dim oCore '// Acroof.Core
Dim oFile '// IPDFFile
Dim oFileCol '// IPDFFileCollection
Set oCore = CreateObject("Acroof.Core")
If oCore.IsCoreSupported Then
Set oFileCol = oCore.GetOpenPDFFiles
If oFileCol.Count <> 0 Then
For Each oFile In oFileCol
MsgBox oFile.FullName
Next
Else
MsgBox "No files opened"
End If
End If
Acroof-1000.zip
ASKER
I really appreciate all the time you put into this, but I think you missed the part where I said I only have Acrobat Reader and so I can't call the Acrobat API at all.
I set a reference to your dll and it lets me declare
Dim oCore As Acroof.Core
So the library is running and connected but when it gets to the line
Set oCore = CreateObject("Acroof.Core" )
It says it cannot create the object (which is what I expected to see)
If I set references to every Acro* thing in there it still won't let this line work (which I tried from your other post just to prove the point). It gives the same error.
Set AcrobatCore = CreateObject("AdobePDFX32. Core")
I'm sorry you spent so much time on this, but I still can't call any Acrobat ATIs.
I set a reference to your dll and it lets me declare
Dim oCore As Acroof.Core
So the library is running and connected but when it gets to the line
Set oCore = CreateObject("Acroof.Core"
It says it cannot create the object (which is what I expected to see)
If I set references to every Acro* thing in there it still won't let this line work (which I tried from your other post just to prove the point). It gives the same error.
Set AcrobatCore = CreateObject("AdobePDFX32.
I'm sorry you spent so much time on this, but I still can't call any Acrobat ATIs.
It doesn't use the acrobat type library only internal windows API... You have to run RegSvr32 on acroof.dll before you can use it
ASKER
I see. Yes that works nicely. Thanks a lot. The only problem is that it requires Admin privaleges to run, but since that wasn't specified in the original question, I won't count it against you. Post the code that you are using in the current dll, please, and then I'll close this out.
ASKER
Admin privaleges to set up I mean, not run. Once set up, I know it will run for anybody.
<< The only problem is that it requires Admin privaleges to run, but since that wasn't specified in the original question, I won't count it against you. >>
1) Yes and No. You can use per user registration without admin rights and still use the library
2) Count it against me? If you mean points they don't really concern me, I come here to help others
3) The source code not going to happen because it's not a couple lines of code
1) Yes and No. You can use per user registration without admin rights and still use the library
2) Count it against me? If you mean points they don't really concern me, I come here to help others
3) The source code not going to happen because it's not a couple lines of code
ASKER
You can use per user registration without admin rights and still use the library
I had to elevate to admin to register the dll at all.
The source code not going to happen because it's not a couple lines of code
Then why did you bother writing it? This site is supposed to be for experts to freely exchange knowledge. If I wanted a third party app, then you could have read that I had one already. Your library is very inflexible. What if I want it to do something slightly different later? The original question specifically asked for a code solution.
I had to elevate to admin to register the dll at all.
The source code not going to happen because it's not a couple lines of code
Then why did you bother writing it? This site is supposed to be for experts to freely exchange knowledge. If I wanted a third party app, then you could have read that I had one already. Your library is very inflexible. What if I want it to do something slightly different later? The original question specifically asked for a code solution.
< Do you want me to create library that you can use from script? >
TommySzalapski: Sure.
You can delete this question if it's not up to your standards
TommySzalapski: Sure.
You can delete this question if it's not up to your standards
ASKER
I am a very active member on this site. I would prefer if you ask me if I did something on purpose before assuming I messed something up. I needed a code solution (as a library or not, but code nonetheless) and Sid got the closest to providing one. I accepted all the most useful posts and spent some time choosing them. Now I have to do it all again.
ASKER
I see. His post wasn't asking for a response, but I understand the notion of the system flagging it. In the future, I will make sure mine is the last post when I close.
I know how to get the path from the running EXE but not from File names. I am working on that at the moment.
Sid