我有得到一些啓動快捷方式和得到他們的圖標一些奇怪的和未知的原因,使用下列方法的問題,他們的圖標:錯誤時,一些.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參數):
此誤差大於如果路徑被提出的一個不同到.lnk文件是不正確的指向一個不存在的文件:
舉個例子,你可以重現這個問題是這樣的:
找到在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
然後執行。
您將獲得以下內容:
點擊任何公顯示的圖標啓動WinRAR的應用。
點擊壞顯示的圖標顯示此錯誤:
與像"C:\Users\Moi\Desktop\WinRARdontexistshere.exe linkorig.lnk"
錯誤路徑改變的Me.LnkOrigPictureBox.Tag
價值和做同樣的事情顯示另一個視覺和錯誤(如預期):
這不工作也沒有用DVDMaker.exe
但一切都很好,wordpad.exe
,圖標和應用程序啓動。
(我測試過的低/大寫的情況下,看它是否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)
我怎麼能解決這個問題推出的,並且這些文件的圖標檢索問題?