Programmstart aus Anwendung über die Desktop-Verknüpfung geht bei einzelnen 64-Bit Anwendungen nicht

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von thilo.

    Programmstart aus Anwendung über die Desktop-Verknüpfung geht bei einzelnen 64-Bit Anwendungen nicht

    Hallo Comunity,

    da man unter Win11 den "Desktop"-button auf der Taskleiste für die alphabetische Liste der Desktopverknüpfungen eingespart hat, versuche ich gerade den selbst zu basteln.
    Das funktioniert auch weitgehend. Ich schreibe die Desktopverknüpfungen in eine Listbox und starte sie per Mouseclick über:
    Process.Start(xxx.lnk)

    Bei einigen 64-Bit-Anwendungen im Ordner "Program Files" habe ich die Fehlermeldung "Das System kann den angebenen Pfad nicht finden"

    FreeCad, verschiedene Slicer, VLC kann ich starten, Office, GoogleEarth, FritzVpn, TeamViever und ein alter TightVNC enden in der Fehlermeldung.

    Hat jemand eine Idee, wo der Hund begraben liegt?
    Ich habe bei zwei Verknüpfungen unter Eigenschaften -> Sicherheit alle Rechte auf Vollzugriff gestellt, hat aber nichts geholfen.

    Gruß Thilo
    Hi,
    kommt die Fehlermeldung vom System oder den Anwendungen selbst?
    Ist in den Verknüpfunhen der Arbeitsordnerpfad korrekt gesetzt?
    Hast Du vielleicht Probleme mit Leerzeichen in den Verknüpfungen?
    Wenn Du die Listbox-Items mit process.start(chr(34) & xxx.lnk & chr(34)) startest, funzt es dann?
    Ich habe versucht das nachzubauen und bei mir war es die Verknüpfung zu Paint.NET die nicht ging. Process.Start(""C:\Users\Public\Desktop\Paint.NET.lnk"

    Ich endete damit mit dem "Windows Script Host Object Model" das Ziel der Verknüpfung herauszulesen, was aber teilweise den 32-bit und nicht den 64-bit Programmpfad zurückgab.
    Deshalb hab ich noch ein Replace eingebaut. (Sicher nicht die sauberste Lösung aber es geht)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Verweis auf "Windows Script Host Object Model" (wshom.ocx) notwendig
    2. Sub StartLNK(shortcutPath As String)
    3. If IO.File.Exists(shortcutPath) Then
    4. Try
    5. Process.Start(shortcutPath)
    6. Catch ex As ComponentModel.Win32Exception
    7. Try
    8. Dim shell As New WshShell()
    9. Dim shortcut As IWshShortcut = CType(shell.CreateShortcut(shortcutPath), IWshShortcut)
    10. Dim targetPath As String = shortcut.TargetPath
    11. If Not IO.File.Exists(targetPath) Then
    12. targetPath = targetPath.Replace("Program Files (x86)", "Program Files")
    13. End If
    14. If IO.File.Exists(targetPath) Then
    15. Process.Start(targetPath)
    16. Else
    17. MessageBox.Show("Das Ziel der Verknüpfung wurde nicht gefunden: " & targetPath)
    18. End If
    19. Catch ex2 As ComponentModel.Win32Exception
    20. MessageBox.Show("Fehler beim Starten der Verknüpfung: " & ex2.Message)
    21. End Try
    22. End Try
    23. Else
    24. MessageBox.Show("Die Verknüpfung wurde nicht gefunden: " & shortcutPath)
    25. End If
    26. End Sub

    HenryV schrieb:

    Verweis auf "Windows Script Host Object Model" (wshom.ocx) notwendig
    Hmm, eine OCX? Du kannst auch die COM Interfaces IShellLinkA/W, IShellLinkDataList und IPersistFile (IPersistFile ist in System.Runtime.InteropServices.ComTypes enthalten) nutzen um entsprechende Informationen aus einer .lnk Datei auszulesen. Ist dann allerdings auch etwas mehr Code. :D
    Mfg -Franky-
    Hallo zusammen - Danke für die Antworten.
    Ich bin noch nicht wirklich weiter gekommen
    Der Reihen nach:
    @Dideldum Die Fehlermeldung kommt von der Anwendung, die Arbeitsordnerpfade sind i.O., Leerzeichen war auch meine erste Idee - ist aber in beiden Fällen gemischt, chr(34) funktionniert auch nur bei den Programmen, bei denen es vorher schon ging.

    @HenryV Das Prinzip habe ich verstanden, die wshom.ocx habe ich in die Verweise aufgenommen und trotzdem habe ich noch drei Fehler. Die Typen WshShel und IWshShortcut sind nicht definiert.
    Was habe ich da übersehen? Fehlt da noch ein Imports...?

    @-Franky- offenbar führen viele Wege nach ROM. Mit deinen Tips bin ich als Hobbyprogrammierer geistig überfordert.

    Gruß
    Thilo

    thilo schrieb:

    offenbar führen viele Wege nach ROM. Mit deinen Tips bin ich als Hobbyprogrammierer geistig überfordert.
    Ersteres ist wohl wahr aber.... Weil Wochenende ist und so schwer ist das gar nicht wenn man den Hinweisen folgt, die MS Doku liest und von mir aus auch den MS Copilot nutzt. Da ich Dir gern einen Ansporn geben möchte, ist folgendes nur ein Democode. Also nicht vollständig. Es müssen nur noch entsprechende Properties angelegt und eventuell muss der Code noch Deinen Bedürfnissen angepasst werden. Natürlich lassen sich da noch mehr Infos aus einer .lnk auslesen bzw. können diese auch geschrieben werden. Wer mich kennt, alles ohne zusätzliche Verweise oder Nuget-Pakete.

    Eine Klasse "ShellLink"
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Text
    2. Imports System.Runtime.InteropServices
    3. Public Class ShellLink
    4. #Region "Const"
    5. Private Const S_OK As Integer = 0
    6. Private Const STGM_READ As Integer = 0
    7. Private Const MAXPATH As Integer = 260
    8. Private Const CLSID_ShellLink As String = "00021401-0000-0000-c000-000000000046"
    9. Private Const IID_IShellLinkW As String = "000214F9-0000-0000-C000-000000000046"
    10. Private Const IID_IShellLinkDataList As String = "45E2B4AE-B1C3-11D0-B92F-00A0C90312E1"
    11. #End Region
    12. #Region "Enums"
    13. Private Enum SHELL_LINK_DATA_FLAGS As UInteger
    14. SLDF_DEFAULT = &H0&
    15. SLDF_HAS_ID_LIST = &H1&
    16. SLDF_HAS_LINK_INFO = &H2&
    17. SLDF_HAS_NAME = &H4&
    18. SLDF_HAS_RELPATH = &H8&
    19. SLDF_HAS_WORKINGDIR = &H10&
    20. SLDF_HAS_ARGS = &H20&
    21. SLDF_HAS_ICONLOCATION = &H40&
    22. SLDF_UNICODE = &H80&
    23. SLDF_FORCE_NO_LINKINFO = &H100&
    24. SLDF_HAS_EXP_SZ = &H200&
    25. SLDF_RUN_IN_SEPARATE = &H400&
    26. SLDF_HAS_LOGO3ID = &H800&
    27. SLDF_HAS_DARWINID = &H1000&
    28. SLDF_RUNAS_USER = &H2000&
    29. SLDF_HAS_EXP_ICON_SZ = &H4000&
    30. SLDF_NO_PIDL_ALIAS = &H8000&
    31. SLDF_FORCE_UNCNAME = &H10000&
    32. SLDF_RUN_WITH_SHIMLAYER = &H20000&
    33. SLDF_FORCE_NO_LINKTRACK = &H40000&
    34. SLDF_ENABLE_TARGET_METADATA = &H80000&
    35. SLDF_DISABLE_LINK_PATH_TRACKING = &H100000&
    36. SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING = &H200000&
    37. SLDF_NO_KF_ALIAS = &H400000&
    38. SLDF_ALLOW_LINK_TO_LINK = &H800000&
    39. SLDF_UNALIAS_ON_SAVE = &H1000000&
    40. SLDF_PREFER_ENVIRONMENT_PATH = &H2000000&
    41. SLDF_KEEP_LOCAL_IDLIST_FOR_UNC_TARGET = &H4000000&
    42. SLDF_PERSIST_VOLUME_ID_RELATIVE = &H8000000&
    43. SLDF_VALID = &H3FF7FF&
    44. SLDF_RESERVED = &H80000000&
    45. End Enum
    46. Private Enum SLGP_FLAGS As UInteger
    47. SLGP_SHORTPATH = &H1&
    48. SLGP_UNCPRIORITY = &H2&
    49. SLGP_RAWPATH = &H4&
    50. SLGP_RELATIVEPRIORITY = &H8&
    51. End Enum
    52. Private Enum SW_SHOW_COMMAND As UInteger
    53. SW_SHOWNORMAL = &H1&
    54. SW_SHOWMINIMIZED = &H2&
    55. SW_SHOWMAXIMIZED = &H3&
    56. SW_SHOWNOACTIVATE = &H4&
    57. SW_SHOW = &H5&
    58. SW_SHOWMINNOACTIVE = &H7&
    59. SW_SHOWNA = &H8&
    60. SW_SHOWDEFAULT = &HA&
    61. End Enum
    62. #End Region
    63. #Region "Class"
    64. Public Sub New(LnkFile As String)
    65. Dim ShellLinkW As IShellLinkW = CType(Activator.CreateInstance(Type.GetTypeFromCLSID(New Guid(CLSID_ShellLink))), IShellLinkW)
    66. If ShellLinkW IsNot Nothing Then
    67. Dim PersistFile As ComTypes.IPersistFile = CType(ShellLinkW, ComTypes.IPersistFile)
    68. If PersistFile IsNot Nothing Then
    69. PersistFile.Load(LnkFile, STGM_READ)
    70. Dim ShellLinkDataList As IShellLinkDataList = CType(ShellLinkW, IShellLinkDataList)
    71. If ShellLinkDataList IsNot Nothing Then
    72. Dim ShellLinkDataFlags As SHELL_LINK_DATA_FLAGS
    73. If ShellLinkDataList.GetFlags(ShellLinkDataFlags) = S_OK Then
    74. If ShellLinkDataFlags And SHELL_LINK_DATA_FLAGS.SLDF_HAS_RELPATH Then
    75. Dim RelPath As New StringBuilder(MAXPATH)
    76. Dim Win32FindData As New WIN32_FIND_DATA
    77. If ShellLinkW.GetPath(RelPath, RelPath.Capacity, Win32FindData, SLGP_FLAGS.SLGP_RELATIVEPRIORITY) = S_OK Then
    78. Debug.Print("RelPath = " & RelPath.ToString)
    79. End If
    80. Else
    81. Dim RawPath As New StringBuilder(MAXPATH)
    82. Dim Win32FindData As New WIN32_FIND_DATA
    83. If ShellLinkW.GetPath(RawPath, RawPath.Capacity, Win32FindData, SLGP_FLAGS.SLGP_RAWPATH) = S_OK Then
    84. Debug.Print("RawPath = " & RawPath.ToString)
    85. End If
    86. End If
    87. If ShellLinkDataFlags And SHELL_LINK_DATA_FLAGS.SLDF_HAS_ARGS Then
    88. Dim Args As New StringBuilder(MAXPATH)
    89. If ShellLinkW.GetArguments(Args, Args.Capacity) = S_OK Then
    90. Debug.Print("Args = " & Args.ToString)
    91. End If
    92. End If
    93. If ShellLinkDataFlags And SHELL_LINK_DATA_FLAGS.SLDF_HAS_WORKINGDIR Then
    94. Dim WorkingDirectory As New StringBuilder(MAXPATH)
    95. If ShellLinkW.GetWorkingDirectory(WorkingDirectory, WorkingDirectory.Capacity) = S_OK Then
    96. Debug.Print("WorkingDirectory = " & WorkingDirectory.ToString)
    97. End If
    98. End If
    99. If ShellLinkDataFlags And SHELL_LINK_DATA_FLAGS.SLDF_HAS_NAME Then
    100. Dim Description As New StringBuilder(MAXPATH)
    101. If ShellLinkW.GetDescription(Description, Description.Capacity) = S_OK Then
    102. Debug.Print("Description = " & Description.ToString)
    103. End If
    104. End If
    105. Dim ShowCommand As SW_SHOW_COMMAND
    106. If ShellLinkW.GetShowCmd(ShowCommand) = S_OK Then
    107. Debug.Print("ShowCommand = " & ShowCommand.ToString)
    108. End If
    109. End If
    110. Marshal.ReleaseComObject(ShellLinkDataList)
    111. End If
    112. Marshal.ReleaseComObject(PersistFile)
    113. End If
    114. Marshal.ReleaseComObject(ShellLinkW)
    115. End If
    116. End Sub
    117. #End Region
    118. #Region "Structures"
    119. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
    120. Public Structure WIN32_FIND_DATA
    121. Public dwFileAttributes As UInteger
    122. Public ftCreationTime As ComTypes.FILETIME
    123. Public ftLastAccessTime As ComTypes.FILETIME
    124. Public ftLastWriteTime As ComTypes.FILETIME
    125. Public nFileSizeHigh As UInteger
    126. Public nFileSizeLow As UInteger
    127. Public dwReserved0 As UInteger
    128. Public dwReserved1 As UInteger
    129. <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> Public cFileName As String
    130. <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> Public cAlternateFileName As String
    131. End Structure
    132. #End Region
    133. #Region "Interface IShellLinkW"
    134. <ComImport>
    135. <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    136. <Guid(IID_IShellLinkW)>
    137. Private Interface IShellLinkW
    138. <PreserveSig> Function GetPath(<Out, MarshalAs(UnmanagedType.LPWStr)> pszFile As StringBuilder,
    139. <[In]> cchMaxPath As Integer,
    140. <Out> ByRef pfd As WIN32_FIND_DATA,
    141. <[In]> fFlags As SLGP_FLAGS) As Integer
    142. <PreserveSig> Function GetIDList(<Out> ByRef ppidl As IntPtr) As Integer
    143. <PreserveSig> Function SetIDList(<[In]> pidl As IntPtr) As Integer
    144. <PreserveSig> Function GetDescription(<Out, MarshalAs(UnmanagedType.LPWStr)> pszName As StringBuilder,
    145. <[In]> cchMaxName As Integer) As Integer
    146. <PreserveSig> Function SetDescription(<[In], MarshalAs(UnmanagedType.LPWStr)> pszName As String) As Integer
    147. <PreserveSig> Function GetWorkingDirectory(<Out, MarshalAs(UnmanagedType.LPWStr)> pszDir As StringBuilder,
    148. <[In]> cchMaxPath As Integer) As Integer
    149. <PreserveSig> Function SetWorkingDirectory(<[In], MarshalAs(UnmanagedType.LPWStr)> pszDir As String) As Integer
    150. <PreserveSig> Function GetArguments(<Out, MarshalAs(UnmanagedType.LPWStr)> pszArgs As StringBuilder,
    151. <[In]> cchMaxPath As Integer) As Integer
    152. <PreserveSig> Function SetArguments(<[In], MarshalAs(UnmanagedType.LPWStr)> pszArgs As String) As Integer
    153. <PreserveSig> Function GetHotkey(<Out> ByRef pwHotkey As Short) As Integer
    154. <PreserveSig> Function SetHotkey(<[In]> wHotkey As Short) As Integer
    155. <PreserveSig> Function GetShowCmd(<Out> ByRef piShowCmd As SW_SHOW_COMMAND) As Integer
    156. <PreserveSig> Function SetShowCmd(<[In]> iShowCmd As SW_SHOW_COMMAND) As Integer
    157. <PreserveSig> Function GetIconLocation(<Out, MarshalAs(UnmanagedType.LPWStr)> pszIconPath As StringBuilder,
    158. <[In]> cchIconPath As Integer,
    159. <Out> ByRef piIcon As Integer) As Integer
    160. <PreserveSig> Function SetIconLocation(<[In], MarshalAs(UnmanagedType.LPWStr)> pszIconPath As String,
    161. <[In]> iIcon As Integer) As Integer
    162. <PreserveSig> Function SetRelativePath(<[In], MarshalAs(UnmanagedType.LPWStr)> pszPathRel As String,
    163. <[In]> dwReserved As Integer) As Integer
    164. <PreserveSig> Function Resolve(<[In]> hwnd As IntPtr,
    165. <[In]> fFlags As UInteger) As Integer
    166. <PreserveSig> Function SetPath(<[In], MarshalAs(UnmanagedType.LPWStr)> pszFile As String) As Integer
    167. End Interface
    168. #End Region
    169. #Region "Interface IShellLinkDataList"
    170. <ComImport>
    171. <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    172. <Guid(IID_IShellLinkDataList)>
    173. Private Interface IShellLinkDataList
    174. <PreserveSig> Function AddDataBlock(<[In]> pDataBlock As IntPtr) As Integer
    175. <PreserveSig> Function CopyDataBlock(<[In]> dwSig As Integer,
    176. <Out> ByRef ppDataBlock As IntPtr) As Integer
    177. <PreserveSig> Function RemoveDataBlock(<[In]> dwSig As Integer) As Integer
    178. <PreserveSig> Function GetFlags(<Out> ByRef pdwFlags As SHELL_LINK_DATA_FLAGS) As Integer
    179. <PreserveSig> Function SetFlags(<[In]> dwFlags As SHELL_LINK_DATA_FLAGS) As Integer
    180. End Interface
    181. #End Region
    182. End Class



    Aufgerufen wird das dann wie folgt.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Dim LnkInfo As New ShellLink("Pfad zur .lnk Datei")
    4. End Sub
    5. End Class


    Ich habe zb. eine Reboot.lnk auf meinem Desktop. Wenn ich diese mit meinem Code auslese, bekomme ich folgende Infos.
    ​ RelPath = C:\Windows\System32\shutdown.exe Args = /g /f /t 0 WorkingDirectory = C:\WINDOWS\system32 ShowCommand = SW_SHOWNORMAL
    Mfg -Franky-