Ken Ray
Ken Ray

Reputation: 2528

.Net Windows application - how to automatically call a program by file association

I have a windows .net program that (among other things) will display image files. These can be in either TIFF or PDF format, and at the moment the way they are displayed is to see what the file extension is, then to call the appropriate program to display that file.

Here's the code fragment:

            imagepath = imagedataset.Tables("Table").Rows(imagecal).Item(2)
        imagepath = "\\tylerimaging\DocumentUpload\" & imagedataset.Tables("Table").Rows(imagecal).Item(3) & "\" & imagedataset.Tables("table").Rows(imagecal).Item(4)
        Dim PDFImage As String = imagepath.Substring(imagepath.Length - 3)
        If UCase(PDFImage) = "PDF" Then
            System.Diagnostics.Process.Start("AcroRd32.exe", imagepath)
        Else
            Try
                System.Diagnostics.Process.Start("MSPVIEW.EXE", imagepath)
            Catch ex As Exception
                If ex.Message = "The system cannot find the file specified" Then
                    System.Diagnostics.Process.Start("ois.exe", imagepath)
                End If
            End Try
        End If
    End If

Now, the problem is that if someone doesn't have the acrobat reader installed, for example, but the full version of adobe acrobat, the process.start for AcroRd32.exe will fail. But, Windows clearly has the association between the file type of PDF and Acrobat - so, here's my question - how can I get the file displayed by whatever program is associated with that file type in Windows?

Thanks in Advance....

Upvotes: 2

Views: 595

Answers (3)

competent_tech
competent_tech

Reputation: 44971

We have implemented a common library set of methods that will first attempt to open the file using Process.Start and, if that fails, prompt the user to select the application to open the file with (open as).

This implementation also addresses a legacy issue where opening RTF files would throw an InvalidOperationException. The usual entry point is to call OpenFileForUser with the full path to the file.

Public Structure SHELLEXECUTEINFO
    Public Size As Integer
    Public Mask As Integer
    Public hwnd As IntPtr
    <MarshalAs(UnmanagedType.LPStr)> Public Verb As String
    <MarshalAs(UnmanagedType.LPStr)> Public File As String
    <MarshalAs(UnmanagedType.LPStr)> Public Parameters As String
    <MarshalAs(UnmanagedType.LPStr)> Public Directory As String
    Dim Show As Integer
    Dim InstApp As IntPtr
    Dim IDList As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)> Public [Class] As String
    Public hkeyClass As IntPtr
    Public HotKey As Integer
    Public Icon As IntPtr
    Public Process As IntPtr
End Structure

Public Const SW_NORMAL As Integer = 1

' Code For OpenWithDialog Box
<DllImport("Shell32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Function ShellExecuteEx(ByRef lpExecInfo As SHELLEXECUTEINFO) As Boolean
End Function

''' <summary>
''' This method executes the shell method for opening the specified file, allowing the user to choose 
''' which program they would like to use to open the file.
''' </summary>
''' <param name="sFileName"></param>
''' <remarks></remarks>
Public Sub OpenFileForUserAs(ByVal sFileName As String)
    ' Exceptions are handled by the caller

    Dim oShellExecuteInfo As New SHELLEXECUTEINFO

    With oShellExecuteInfo
        .Size = System.Runtime.InteropServices.Marshal.SizeOf(oShellExecuteInfo)
        .Verb = "openas"
        .File = sFileName
        .Show = SW_NORMAL
    End With
    If Not ShellExecuteEx(oShellExecuteInfo) Then
        Throw New System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error())
    End If
End Sub

''' <summary>
''' This method opens the file for the user
''' </summary>
''' <param name="sFileName"></param>
''' <remarks></remarks>
Public Function OpenFileForUser(ByVal sFileName As String) As System.Diagnostics.Process
    ' Exceptions are handled by the caller

    Try
        Return System.Diagnostics.Process.Start(sFileName, "")
    Catch theInvalidOperation As InvalidOperationException
        ' happens with rtf; just sink the exception
    Catch ex As System.ComponentModel.Win32Exception
        Select Case ex.NativeErrorCode
            Case 1155
                Call OpenFileForUserAs(sFileName)
            Case 1223
                ' Operation Cancelled By User
            Case Else
                Throw ex
        End Select
    End Try

    Return Nothing
End Function

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 613461

Call Process.Start() passing just the document file name. By default this uses the UseShellExecute option which means that the shell is asked to perform the open verb on the document. That's the same as double clicking the document from the shell UI.

Upvotes: 2

LarsTech
LarsTech

Reputation: 81675

Try calling Process.Start on the PDF or TIFF file itself. Windows will take care of it or raise an exception if nothing is associated with the file type.

Upvotes: 4

Related Questions