2015-11-29 17 views
0

我有得到一些啓動快捷方式和得到他們的圖標一些奇怪的和未知的原因,使用下列方法的問題,他們的圖標:錯誤時,一些.LNK文件,並得到使用的Process.Start和的SHGetFileInfo()

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 

這些方法幾乎適用於任何項目,但有時它們會在System.dll中向我發送System.ComponentModel.Win32Exception嘗試執行快捷方式文件時,並在這些相同的文件上獲取它們的圖標。

它給我以下消息(由給定的Process.Start被稱爲與ErrorDialog = True時的ProcessStartInfo參數):

enter image description here

此誤差大於如果路徑被提出的一個不同到.lnk文件是不正確的指向一個不存在的文件:

enter image description here

舉個例子,你可以重現這個問題是這樣的:

找到在Windows 7安裝下列文件:
C:\Program Files\DVD Maker\DVDMaker.exe(本機與Windows 7)

C:\Program Files\WinRAR\WinRAR.exe(V5.0 64位,但我想這將有同樣的效果另一個版本)

C:\Program Files\Windows NT\Accessories\wordpad.exe(本機與Windows 7)

  • 複製他們每個人的桌面
  • 使用右鍵單擊拖動,爲這3個文件中的每一個從其原始位置創建3個鏈接快捷方式到桌面。重命名這些快捷方式(爲了方便起見)「[Filename] linkorig」
  • 使用右鍵單擊並拖放,爲從桌面到桌面的3個複製文件中的每一個創建3個鏈接快捷方式。重命名這些快捷鍵(爲了方便) 「[文件名]連接複製」

創建一個Visual Basic項目,把4個PictureBoxes到窗體並將其命名爲:

  • ExeOrigPictureBox
  • ExeCopyPictureBox
  • LnkOrigPictureBox
  • LnkCopyPictureBox

和一些標籤來幫助你自己。

然後將以下代碼複製/粘貼到表單代碼窗口:

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 

然後執行。

您將獲得以下內容:

enter image description here

點擊任何公顯示的圖標啓動WinRAR的應用。
點擊壞顯示的圖標顯示此錯誤:

enter image description here

與像"C:\Users\Moi\Desktop\WinRARdontexistshere.exe linkorig.lnk"錯誤路徑改變的Me.LnkOrigPictureBox.Tag價值和做同樣的事情顯示另一個視覺和錯誤(如預期):

enter image description here

這不工作也沒有用DVDMaker.exe

enter image description here

但一切都很好,wordpad.exe,圖標和應用程序啓動。

enter image description here

(我測試過的低/大寫的情況下,看它是否interfers,但這不是問題)我對一些其他應用程序注意到了這個問題,而不理解

的這種情況的原因,例如:

  • 油漆.NET
  • VirtualBox的
  • CloneSpy
  • VirtualDub

和其他標準Windows應用程序。

將有問題的文件路徑C:\Users\Moi\Desktop\WinRAR.exe linkorig.lnk複製/粘貼到Windows資源管理器標題欄時,會啓動WinRAR.exe應用程序。

當然,同樣的事情是我雙擊.lnk文件。

複製/粘貼到Windows-R命令窗口時,它也可以正常啓動。

如果通過從位於C:\Users\Moi\Desktop\文件夾中的命令行窗口鍵入WinRAR.lnk來調用,也會啓動。

我跑到Windows 7 64位。該應用程序使用Visual Studio Express 2015編譯。我以管理員身份登錄(Windows安裝時創建的唯一默認帳戶)。以「管理員身份」運行編譯的應用程序不會改變任何內容。

我嘗試使用一些配置,下面沒有成功:

 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) 

我怎麼能解決這個問題推出的,並且這些文件的圖標檢索問題?

回答

0

Woow ...當我看到這個答案時,我發現通過網絡發現的一些示例進行了一些測試,當使用標準OpenFileDialog時,圖標問題和嘗試使用相應文件時的錯誤消息也存在。我懷疑.Net框架中存在一個錯誤。解決辦法就在這附近,我仍然不明白它的深層原因。

問題是以下幾點:

該項目是由默認定義爲項目設置我切換它與框架與運行.Net框架4.5

運行4
拼命地跑應用程序:無更多問題

我將其切換回運行Framework 4.5
沒有更多的問題。