使用以下方法,由于某些奇怪和未知的原因,我无法启动一些快捷方式并获取它们的图标:
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 个链接快捷方式到桌面。重命名这些快捷方式(为方便起见)“[文件名] linkorig”
- 通过右键单击拖动,为从桌面复制到桌面的 3 个文件中的每一个创建 3 个链接快捷方式。重命名这些快捷方式(为方便起见)“[文件名]链接复制”
创建一个 Visual basic 项目,将 4 个 PictureBoxes 放到一个 Form 上并命名它们:
- ExeOrigPictureBox
- 执行复制图片框
- LnkOrigPictureBox
- LnkCopy图片框
还有一些标签可以帮助自己。
然后将以下代码复制/粘贴到表单代码窗口中:
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 应用程序。
单击显示的错误图标会显示此错误:
Me.LnkOrigPictureBox.Tag
使用错误的路径更改值"C:\Users\Moi\Desktop\WinRARdontexistshere.exe linkorig.lnk"
并执行相同的操作会显示另一个视觉和错误(如预期的那样):
这也不适用于DVDMaker.exe
但一切都很好wordpad.exe
,图标和应用程序启动。
(我已经测试了小写/大写的情况,看看它是否会干扰,但这不是问题)
我在不了解原因的情况下注意到其他一些应用程序的问题,例如:
- 油漆.net
- 虚拟盒子
- 克隆间谍
- 虚拟配音
和其他标准 Windows 应用程序。
将有问题的文件路径复制/粘贴C:\Users\Moi\Desktop\WinRAR.exe linkorig.lnk
到 Windows 资源管理器标题栏时,会启动 WinRAR.exe 应用程序。
当然同样的事情是我双击 .lnk 文件。
当复制/粘贴到 Windows-R 命令窗口时,它也能很好地启动。
WinRAR.lnk
如果通过从放置在C:\Users\Moi\Desktop\
文件夹中的命令行窗口键入来调用,也会启动。
我正在运行 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)
我该如何解决这个启动问题,以及这些文件的图标检索问题?