visual-studioprocessiconsshortcutwin32exception

Error when launching some .lnk files and getting their icon using Process.Start and SHGetFileInfo()


I have problems getting launching some shortcuts and getting their icon for some strange and unknown reason, using the following methods :

Public Shared Sub Launch(itemToLaunch As String)
        Process.Start(itemToLaunch)
End Sub



Public Function GetShellIcon(ByVal path As String) As Icon

        Dim info As SHFILEINFO = New SHFILEINFO()
        Dim retval As IntPtr = SHGetFileInfo(path, 0, info, Marshal.SizeOf(info), SHGFI_ICON Or SHGFI_SMALLICON Or SHGFI_LARGEICON)

        If retval = IntPtr.Zero Then
            Return New Icon(GetType(Control), "Error.ico")
        End If

        Dim cargt() As Type = {GetType(IntPtr)}
        Dim ci As ConstructorInfo = GetType(Icon).GetConstructor(BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, cargt, Nothing)
        Dim cargs() As Object = {info.IconHandle}
        Dim icon As Icon = CType(ci.Invoke(cargs), Icon)

        Return icon
    End Function

 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
    Private Structure SHFILEINFO
        Public IconHandle As IntPtr
        Public IconIndex As Integer
        Public Attributes As UInteger
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)>
        Public DisplayString As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)>
        Public TypeName As String
    End Structure

    Private Declare Auto Function SHGetFileInfo Lib "Shell32.dll" (path As String, attributes As Integer, ByRef info As SHFILEINFO, infoSize As Integer, flags As Integer) As IntPtr

    Public Const SHGFI_ICON = &H100
    Public Const SHGFI_SMALLICON = &H1
    Public Const SHGFI_LARGEICON = &H0         ' Large icon

These methods works well on almost any item, but sometimes they send me a System.ComponentModel.Win32Exception in System.dll when trying to execute a shortcut file, and on these same files, getting their icon.

It gives me the following message (given by Process.Start is called with a ProcessStartInfo parameter with ErrorDialog=True) :

enter image description here

This error is different than the one that is raised if the path to the .lnk file is not correct pointing to an non existing file :

enter image description here

As an example, you can reproduce this problem this way :

Locate on a Windows 7 install the following files :
C:\Program Files\DVD Maker\DVDMaker.exe (native with Windows 7)

C:\Program Files\WinRAR\WinRAR.exe (v5.0 64 bits, but I guess this will have the same effect with another version)

C:\Program Files\Windows NT\Accessories\wordpad.exe (native with Windows 7)

Create a Visual basic project, put 4 PictureBoxes onto a Form and name them :

And some Labels to help yourself.

Then copy/paste the following code into the Form code window :

Imports System.Reflection
Imports System.Runtime.InteropServices

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Me.ExeOrigPictureBox.Tag = "C:\Program Files\WinRAR\WinRAR.exe"
        Me.ExeCopyPictureBox.Tag = "C:\Users\Moi\Desktop\WinRAR.exe"

        Me.LnkOrigPictureBox.Tag = "C:\Users\Moi\Desktop\WinRAR.exe linkorig.lnk"
        Me.LnkCopyPictureBox.Tag = "C:\Users\Moi\Desktop\WinRAR.exe linkcopy.lnk"

        Me.ExeOrigPictureBox.Image = GetShellIcon(Me.ExeOrigPictureBox.Tag).ToBitmap
        Me.ExeCopyPictureBox.Image = GetShellIcon(Me.ExeCopyPictureBox.Tag).ToBitmap

        Me.LnkOrigPictureBox.Image = GetShellIcon(Me.LnkOrigPictureBox.Tag).ToBitmap
        Me.LnkCopyPictureBox.Image = GetShellIcon(Me.LnkCopyPictureBox.Tag).ToBitmap
    End Sub

    Private Sub ExeOrigPictureBox_Click(sender As Object, e As EventArgs) Handles ExeOrigPictureBox.Click, ExeCopyPictureBox.Click, LnkOrigPictureBox.Click, LnkCopyPictureBox.Click
        Dim pBox As PictureBox = DirectCast(sender, PictureBox)

        Dim pi As ProcessStartInfo = New ProcessStartInfo
        pi.FileName = pBox.Tag
        pi.ErrorDialog = True
        Process.Start(pi)
    End Sub
End Class

Module Shell32
    Public Function GetShellIcon(ByVal path As String) As Icon

        Dim info As SHFILEINFO = New SHFILEINFO()
        Dim retval As IntPtr = SHGetFileInfo(path, 0, info, Marshal.SizeOf(info), SHGFI_ICON Or SHGFI_SMALLICON Or SHGFI_LARGEICON)

        If retval = IntPtr.Zero Then
            Return New Icon(GetType(Control), "Error.ico")
        End If

        Dim cargt() As Type = {GetType(IntPtr)}
        Dim ci As ConstructorInfo = GetType(Icon).GetConstructor(BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, cargt, Nothing)
        Dim cargs() As Object = {info.IconHandle}
        Dim icon As Icon = CType(ci.Invoke(cargs), Icon)

        Return icon
    End Function

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
    Private Structure SHFILEINFO
        Public IconHandle As IntPtr
        Public IconIndex As Integer
        Public Attributes As UInteger
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)>
        Public DisplayString As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)>
        Public TypeName As String
    End Structure

    Private Declare Auto Function SHGetFileInfo Lib "Shell32.dll" (path As String, attributes As Integer, ByRef info As SHFILEINFO, infoSize As Integer, flags As Integer) As IntPtr

    Public Const SHGFI_ICON = &H100
    Public Const SHGFI_SMALLICON = &H1
    Public Const SHGFI_LARGEICON = &H0         ' Large icon
End Module

Then execute.

You will obtain the following :

enter image description here

Clicking on any of the well displayed icons launches the WinRar application.
Clicking on the bad displayed icon displays this error :

enter image description here

Changing the value of Me.LnkOrigPictureBox.Tag with a wrong path like "C:\Users\Moi\Desktop\WinRARdontexistshere.exe linkorig.lnk" and doing the same thing displays another visual and error (as expected) :

enter image description here

This don't work neither with DVDMaker.exe

enter image description here

But everything is fine with wordpad.exe, icon and application launch.

enter image description here

(I've tested the case of the lower/uppercase to see if it interfers, but this is not the problem)

I've noticed the problem on some other apps without understanding the reasons of this, for example :

and other standard Windows apps.

When copy/pasting the problematic file path C:\Users\Moi\Desktop\WinRAR.exe linkorig.lnk onto a Windows explorer title bar, the WinRAR.exe app is launched.

Of course same thing is I double-click the .lnk file.

It is also launched well when copy/pasted into a Windows-R command window.

And also launched if called by typing WinRAR.lnk from a command-line window being placed in the C:\Users\Moi\Desktop\ folder.

I'm running onto a Windows 7 64 bits. The app is compiled using Visual Studio Express 2015. I'm logged as administrator (the one and only default account created on the Windows install). Runing the compiled app "as an administrator" does not change anything.

I tried using some configurations such the following without success :

        Dim info As ProcessStartInfo = New ProcessStartInfo(--- here the path ---)
        info.CreateNoWindow = False
        info.UseShellExecute = False
        info.RedirectStandardError = True
        info.RedirectStandardOutput = True
        info.RedirectStandardInput = True
        Dim whatever As Process = Process.Start(info)

How could I solve this launch problem, and the icon retrieval problem of these files ?


Solution

  • Woow... I found the answer by luck when I saw, making some tests with some examples found over the net, that the icon problem and the error message when trying to use the corresponding file was also present when using a standard OpenFileDialog. I suspected a bug in the .Net framework. And the solution was near this, and I still don't really understand its deep reasons.

    The problem was the following :

    The project was defined by default into the project settings to run with .Net Framework 4.5

    I switched it to run with Framework 4
    Runned the app : no more problem

    I switched it back to run with Framework 4.5
    No more problem at all.