none
Icon aus .exe laden (per Shell32) liefert kein Ergebnis RRS feed

  • Frage

  • Hallo,

    ich möchte aus einer .exe den Icon extrahieren. Da diese .exe leider auf einem Netzwerk-Share liegt, muss ich diesen leider wohl über P-Invoke (Interop) laden.

    Da ich auf diesem Gebiet noch unerfahren hab, hab ich mir per Internet und C#-Beispielen folgende Funktion zusammengebaut:

        <DllImport("Shell32", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function ExtractAssociatedIcon(ByVal hInst As IntPtr, ByVal builder As StringBuilder, ByRef pIcon As UShort) As Boolean
        End Function
    
        Public Shared Function returnIcon(ByVal pFileName As String) As System.Drawing.Icon
            Dim uicon As UShort
            Dim builder As New StringBuilder(pFileName)
            Dim handle As IntPtr = ExtractAssociatedIcon(IntPtr.Zero, builder, uicon)
            Dim result As Icon = Icon.FromHandle(handle)
            Return result
        End Function
    


    Leider liefert mir diese keinen Icon zurück (result = empty)

    Hat jemand eine Idee ?

     

    Vielen Dank

    Donnerstag, 20. Oktober 2011 11:03

Antworten

  • Hallo,

    nichts desto trotz hast Du das Rad neu erfunden ;-)

    Die Methode wird bereits durch die Icon-Klasse als ExtractAssociatedIcon-Methode bereitgestellt.

    Der DLLImport erwartet als letzten Parameter einen ByRef Integer:

    <DllImport("shell32.dll", BestFitMapping = false, CharSet = CharSet.Auto, EntryPoint = "ExtractAssociatedIcon") > _
    Public Shared Function ExtractAssociatedIcon(ByVal hInst As IntPtr, ByVal iconPath As StringBuilder, ByRef index As Integer) As IntPtr
    End Function
    
    

    (abgeleitet aus System.Drawing.SafeNativeMethods - ohne HandlefRef)

    Gruß Elmar

    Donnerstag, 20. Oktober 2011 12:03
    Beantworter
  • Hallo,

    bei einem ByRef Parameter spielt es schon eine Rolle ob die Variable zwei (short) oder vier Byte (integer) hat.
    denn die API-Funktion schreibt da auch zurück.

    Gruß Elmar

    Donnerstag, 20. Oktober 2011 14:00
    Beantworter
  • Ach ich bin doch blind, hab den Fehler gefunden:

    Ich musste noch den Rückgabewert der 'ExtractAssociatedIcon'-Funktion auf IntPtr ändern.

    Donnerstag, 20. Oktober 2011 11:05

Alle Antworten

  • Ach ich bin doch blind, hab den Fehler gefunden:

    Ich musste noch den Rückgabewert der 'ExtractAssociatedIcon'-Funktion auf IntPtr ändern.

    Donnerstag, 20. Oktober 2011 11:05
  • Hallo,

    nichts desto trotz hast Du das Rad neu erfunden ;-)

    Die Methode wird bereits durch die Icon-Klasse als ExtractAssociatedIcon-Methode bereitgestellt.

    Der DLLImport erwartet als letzten Parameter einen ByRef Integer:

    <DllImport("shell32.dll", BestFitMapping = false, CharSet = CharSet.Auto, EntryPoint = "ExtractAssociatedIcon") > _
    Public Shared Function ExtractAssociatedIcon(ByVal hInst As IntPtr, ByVal iconPath As StringBuilder, ByRef index As Integer) As IntPtr
    End Function
    
    

    (abgeleitet aus System.Drawing.SafeNativeMethods - ohne HandlefRef)

    Gruß Elmar

    Donnerstag, 20. Oktober 2011 12:03
    Beantworter
  • Hallo,

    nichts desto trotz hast Du das Rad neu erfunden ;-)

    Die Methode wird bereits durch die Icon-Klasse als ExtractAssociatedIcon-Methode bereitgestellt.

    Der DLLImport erwartet als letzten Parameter einen ByRef Integer:

    <DllImport("shell32.dll", BestFitMapping = false, CharSet = CharSet.Auto, EntryPoint = "ExtractAssociatedIcon") > _
    Public Shared Function ExtractAssociatedIcon(ByVal hInst As IntPtr, ByVal iconPath As StringBuilder, ByRef index As Integer) As IntPtr
    End Function
    
    

    (abgeleitet aus System.Drawing.SafeNativeMethods - ohne HandlefRef)

     

    Gruß Elmar

    Die Extract-Methode funktioniert ja wie beschrieben nicht, da sich die .exe auf einem Netzwerk-Laufwerk befindet, welcher nur per \\Server\Pfad... angesprochen werden kann.

    Darum sieht das dann so aus:

     If FileIO.FileSystem.FileExists(_CurrentAppPath) Then
                            Try
                                picBoxApplicationIcon.Image = Icon.ExtractAssociatedIcon(_CurrentAppPath).ToBitmap
                            Catch exArgument As ArgumentException 'Fehler abfangen bei Shares
                                picBoxApplicationIcon.Image = SharedFunctions.returnIcon(_CurrentAppPath).ToBitmap
                            End Try
    End if
    

     

    Ist dieser Integer-Parameter wichtig ? Denn es scheint bisher mit meiner Methode problemlos zu funktionieren.


    • Bearbeitet Ralf Stiegele Donnerstag, 20. Oktober 2011 12:52 Typo
    Donnerstag, 20. Oktober 2011 12:52
  • Hallo,

    bei einem ByRef Parameter spielt es schon eine Rolle ob die Variable zwei (short) oder vier Byte (integer) hat.
    denn die API-Funktion schreibt da auch zurück.

    Gruß Elmar

    Donnerstag, 20. Oktober 2011 14:00
    Beantworter
  • Ist dieser Integer-Parameter wichtig ? Denn es scheint bisher mit meiner Methode problemlos zu funktionieren.

     

    Hallo RQ-1,

    Ich verwende ihm zum Beispiel eine gewisse Icon zu extrahieren.

    [VB.NET Code]

    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports System.IO
    Imports System.Drawing.Imaging
    Imports System.ComponentModel
    
    Public Class Form1
    
        Private Declare Auto Function ExtractAssociatedIcon Lib "shell32" ( _
          ByVal hInst As IntPtr, ByVal path As String, ByRef index As Integer) As IntPtr
        Private Declare Auto Function DestroyIcon Lib "user32" (ByVal hIcon As IntPtr) As Boolean
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
          
    
            Dim myIcon As Icon = ExtractIcon("C:\Windows\System32\moricons.dll", 3) '//ist die 4 Icon aus der Liste (0 based)
            '//Dim myIcon As Icon = ExtractIcon("C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe")
            Dim imageStream As Stream = New MemoryStream()
            Dim bmp As Bitmap = myIcon.ToBitmap()
            bmp.Save(imageStream, ImageFormat.Jpeg)
    
    
            PictureBox1.Image = Image.FromStream(imageStream)
            imageStream.Close()
    
        End Sub
    
        Public Shared Function ExtractIcon(ByVal path As String, Optional ByVal index As Integer = 0) As Icon
            Dim handle As IntPtr = ExtractAssociatedIcon(IntPtr.Zero, path, index)
            If handle = IntPtr.Zero Then Throw New Win32Exception(Marshal.GetLastWin32Error())
            Dim retval As Icon = Nothing
            Using temp As Icon = Icon.FromHandle(handle)
                retval = CType(temp.Clone(), Icon)
                DestroyIcon(handle)
            End Using
            Return retval
        End Function
    
    
    End Class
    


     

     

    Kleiner Hinweis: Die 'System.Drawing.Icon.ExtractAssociatedIcon' und  die ExtractAssociatedIcon extrahieren nur ein 32 x 32 Pixel-Icon. (“Both the ExtractAssociatedIcon and 'System.Drawing.Icon.ExtractAssociatedIcon' extract only a 32x32 pixels icon.”)…und vielleicht möchtest Du auch 16 x 16 Pixel-Icons bekommen: Building a Better ExtractAssociatedIcon

    Grüße,

    Robert

    Donnerstag, 20. Oktober 2011 14:44
    Moderator