Check if a pdf reader is installed on a pc

kelly mort

Well-known Member
Joined
Apr 10, 2017
Messages
2,169
Office Version
  1. 2016
Platform
  1. Windows
I have been searching the Web for solutions. I have seen a few examples of how to check if an Adobe Reader is installed but what I want is to be able to check if any pdf reader at all is installed.
This from excel forum:

I also came across this post on stack overflow:
Which is not VBA code though.

Can someone help me with how to use VBA to check if any pdf reader is installed?
Thanks in advance.
 

Excel Facts

Workdays for a market open Mon, Wed, Friday?
Yes! Use "0101011" for the weekend argument in NETWORKDAYS.INTL or WORKDAY.INTL. The 7 digits start on Monday. 1 means it is a weekend.
Bump:

Cross posted at:
 
Upvote 0
When you say any PDF reader, do you mean any software that can read PDF files ? If so, it is difficult because that includes a long list of software such as Word, Internet Explorer and many others etc
 
Upvote 0
Yes, I mean any software that can read pdf.
I was thinking there could be an attribute or something that could identify such programs.
Because looking at the conversation here:
It looked as if there was a way (I didn't understand most of the discussions though).

But if there is a way to check for the most popular ones I would be grateful to get the way around it.
 
Upvote 0
Yes, I mean any software that can read pdf.
But if there is a way to check for the most popular ones I would be grateful to get the way around it.

I think the best way is to use file association but, for that, we first need to know the most popular file extensions of the document files created by PDF Viewers\Readers which I don't know.

We could assume that all documents with a .pdf extension are by default, opened with the most popular PDF Viewers\Readers such as Adobe Reader or Adobe Acrobat but, although this may be the case most of the time , it is not strictly true.

Anyway, here is this code:

In a Standard Module:
VBA Code:
Option Explicit

Private Enum ASSOC_FILTER
    ASSOC_FILTER_NONE = &H0
    ASSOC_FILTER_RECOMMENDED = &H1
End Enum

#If VBA7 Then
    Private Declare PtrSafe Function SHAssocEnumHandlers Lib "shell32" (ByVal pszExtra As LongPtr, ByVal afFilter As ASSOC_FILTER, ByVal ppEnumHandler As LongPtr) As Long
    Private Declare PtrSafe Function DispCallFunc Lib "oleAut32.dll" (ByVal pvInstance As LongPtr, ByVal offsetinVft As Long, ByVal CallConv As Long, ByVal retTYP As Integer, ByVal paCNT As Long, ByRef paTypes As Integer, ByRef paValues As LongPtr, ByRef retVAR As Variant) As Long
    Private Declare PtrSafe Sub SetLastError Lib "kernel32.dll" (ByVal dwErrCode As Long)
    Private Declare PtrSafe Function SysReAllocString Lib "oleAut32.dll" (ByVal pBSTR As LongPtr, Optional ByVal pszStrPtr As LongPtr) As Long
#Else
    Private Declare Function SHAssocEnumHandlers Lib "shell32" (ByVal pszExtra As Long, ByVal afFilter As ASSOC_FILTER, ByVal ppEnumHandler As Long) As Long
    Private Declare Function DispCallFunc Lib "oleAut32.dll" (ByVal pvInstance As Long, ByVal offsetinVft As Long, ByVal CallConv As Long, ByVal retTYP As Integer, ByVal paCNT As Long, ByRef paTypes As Integer, ByRef paValues As Long, ByRef retVAR As Variant) As Long
    Private Declare Sub SetLastError Lib "kernel32.dll" (ByVal dwErrCode As Long)
    Private Declare Function SysReAllocString Lib "oleAut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long) As Long
#End If


Public Function Is_PDF_Reader_Installed() As Boolean
    Is_PDF_Reader_Installed = Len(FindExecutable_With_AssocHandlerINTERFACE("pdf"))
End Function

Private Function FindExecutable_With_AssocHandlerINTERFACE(ByVal DocumetFileExtension As String) As String

    #If Win64 Then
        Const vTblOffsetFac_32_64 = 2&
        Dim pEnumHandlers As LongLong
        Dim pAssocHandler As LongLong
         Dim pceltFetched As LongLong
        Dim pExecutablePathName As LongLong
    #Else
        Const vTblOffsetFac_32_64 = 1&
        Dim pEnumHandlers As Long
        Dim pAssocHandler As Long
        Dim pceltFetched As Long
        Dim pExecutablePathName As Long
    #End If
 
    Const IEnumAssocHandlers_Next = 12 * vTblOffsetFac_32_64
    Const IAssocHandler_GetName = 12 * vTblOffsetFac_32_64
    Const CC_STDCALL = 4&
    Const S_OK = 0&
 
    Dim Unk As IUnknown

    If Len(DocumetFileExtension) Then
        DocumetFileExtension = IIf(Left(DocumetFileExtension, 1) = ".", DocumetFileExtension, "." & DocumetFileExtension)
        If SHAssocEnumHandlers(StrPtr(DocumetFileExtension), ASSOC_FILTER_RECOMMENDED, VarPtr(Unk)) = S_OK Then
            pEnumHandlers = ObjPtr(Unk)
            If vtblCall(pEnumHandlers, IEnumAssocHandlers_Next, vbLong, CC_STDCALL, 1&, VarPtr(pAssocHandler), VarPtr(pceltFetched)) = S_OK Then
                If vtblCall(pAssocHandler, IAssocHandler_GetName, vbLong, CC_STDCALL, VarPtr(pExecutablePathName)) = S_OK Then
                    FindExecutable_With_AssocHandlerINTERFACE = GetStrFromPtrW(pExecutablePathName)
                End If
            End If
        End If
    End If

End Function

#If Win64 Then
    Private Function vtblCall(ByVal InterfacePointer As LongLong, ByVal VTableOffset As Long, ByVal FunctionReturnType As Long, ByVal CallConvention As Long, ParamArray FunctionParameters() As Variant) As Variant

    Dim vParamPtr() As LongLong
#Else
    Private Function vtblCall(ByVal InterfacePointer As Long, ByVal VTableOffset As Long, ByVal FunctionReturnType As Long, ByVal CallConvention As Long, ParamArray FunctionParameters() As Variant) As Variant

    Dim vParamPtr() As Long
#End If

    If InterfacePointer = 0& Or VTableOffset < 0& Then Exit Function
    If Not (FunctionReturnType And &HFFFF0000) = 0& Then Exit Function

    Dim pIndex As Long, pCount As Long
    Dim vParamType() As Integer
    Dim vRtn As Variant, vParams() As Variant

    vParams() = FunctionParameters()
    pCount = Abs(UBound(vParams) - LBound(vParams) + 1&)
    If pCount = 0& Then
        ReDim vParamPtr(0 To 0)
        ReDim vParamType(0 To 0)
    Else
        ReDim vParamPtr(0 To pCount - 1&)
        ReDim vParamType(0 To pCount - 1&)
        For pIndex = 0& To pCount - 1&
            vParamPtr(pIndex) = VarPtr(vParams(pIndex))
            vParamType(pIndex) = VarType(vParams(pIndex))
        Next
    End If
 
    pIndex = DispCallFunc(InterfacePointer, VTableOffset, CallConvention, FunctionReturnType, pCount, vParamType(0), vParamPtr(0), vRtn)
    If pIndex = 0& Then
        vtblCall = vRtn
    Else
        SetLastError pIndex
    End If

End Function

#If Win64 Then
    Private Function GetStrFromPtrW(ByVal Ptr As LongLong) As String
#Else
    Private Function GetStrFromPtrW(ByVal Ptr As Long) As String
#End If

    SysReAllocString VarPtr(GetStrFromPtrW), Ptr

End Function


Usage Example :
VBA Code:
Sub Test()
    MsgBox Is_PDF_Reader_Installed
End Sub
 
Upvote 0
Oh okay. I now get why you asked the first question.

I Uninstalled my pdf reader and it was still returning true:

So when I tried to open the pdf file (searching for program from installed list), word showed up.

Is it possible to bypass that - that's eliminating word from the list (my choice of pdf readers).

With broswers, I am okay.

I want to eliminate word since it has to convert the document, mostly changing the structure of it.
 
Upvote 0
Now that you have pdf reader uninstalled, can you change the Is_PDF_Reader_Installed function as follows:

VBA Code:
Public Function Is_PDF_Reader_Installed() As Boolean
    Debug.Print FindExecutable_With_AssocHandlerINTERFACE(".pdf")
    Is_PDF_Reader_Installed = Len(FindExecutable_With_AssocHandlerINTERFACE(".pdf"))
End Function

Now, when you run the Test macro, what string do you get in the immediate window ?
 
Upvote 0
This is what I get:

C:\Program Files (x86) \Microsoft Office \Root\Office16\Winword.exe
 
Upvote 0
This is what I get:

C:\Program Files (x86) \Microsoft Office \Root\Office16\Winword.exe
In that case, change the Is_PDF_Reader_Installed as follows in order to exclude WinWord.exe
VBA Code:
Public Function Is_PDF_Reader_Installed() As Boolean

    Dim sExecutablePath As String

    sExecutablePath = FindExecutable_With_AssocHandlerINTERFACE(".PDF")
   
    If Len(sExecutablePath) And UCase(Right(sExecutablePath, 11)) <> UCase("WINWORD.EXE") Then
        Is_PDF_Reader_Installed = True
    End If

End Function
 
Upvote 0
Solution

Forum statistics

Threads
1,223,911
Messages
6,175,324
Members
452,635
Latest member
laura12345

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top