Icon aus Datei Extrahieren -> FTP
- VB.NET
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 62 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.
-
-
Bei jeder Datei kann man Icon extrahieren, nicht nur bei DLL/EXE:
visual-basic5.de/vbclassic/dotnet/extractassociatedicon.htm <<< dieser beispiel extrahiert das Icon bei jeder Datei -
-
-
-
Um das jetzt noch mal klar zu stellen:
Die Icons werden von den Programmen, die sie öffnen können, bereitgestellt, nicht von den Dateien selbst. Wenn man Dateien auf einen FTP-Server rauflädt, sind die Icons nicht dabei. Es gibt da allerdings Unterschiede. Beispielsweise werden bei .txt-Dateien die Icons von einem Programm bereitgestellt bzw. als Icon auf der Festplatte gespeichert. Ausführbare Dateien können Icons in ihren Resourcen zur Verfügung stellen. Ich denke jetzt nicht, dass standardmäßig andere Wege zur Icon-Gewinnung unterstützt werden. Für Iconresourcen verwendet man halt ExtractAssociatedIcon(Ex) und erstellt die Instanz der Icon-Klasse vom Handle. Bei Icondateien verwendet man den von der Icon-Klasse gebotenen Konstruktor und ggf. Environment.ExpandEnvironmentVariables. Problematisch ist halt nur, wenn der Eintrag wie z.B. bei .exe-Dateien aussieht, die ja ein dynamisches Icon haben. Den kann man nicht auswerten, ohne dass die Dateien heruntergeladen werden. Dumm ist auch, dass ich nicht die Argumentwerte der Format-Funktion weiß, die benötigt werden. %1 dürfte wohl der Dateiname sein, aber gibt es da noch andere Argumente und wo findet man sie? Wenn ihr mir die Informationen besorgt, versuch' ich, einen kurzen Code zusammenzuschreiben, der die Icons anhand der Extensions aus der Registry ermittelt. Da unterscheiden sich halt dann die Icons auf den verschiedenen Systemen. Das ist aber auch die vom Explorer verwendete Methode.
Gruß
~blaze~ -
Danke ~balze~,
das habe ich nicht so schön erklärt.
Ich versuche mal raus zu bekommen wie diese Argumente sind und wo man sie findet.~blaze~ schrieb:
Da unterscheiden sich halt dann die Icons auf den verschiedenen Systemen.
und das währe sogar Perfekt. Dann währe die Methode automatisch immer up to date.
ich melde mich sobal ich etwas habe.
danke dir
Bernd
Edit:
ich habe die frage mal bei msdn abgesetzt, dauert halt ein wenig bei denen. -
Icons stecken doch bekanntlich in der selben Stelle in den Dateien, sonst wüsste Windows auch nicht wo/was das Icon vom jeweiligen Programm ist.
Du kannst also folgendes machen (erfordert vermutlich eine große Menge an Kenntnissen):
Anstatt das du dir die Datei komplett auf den Rechner siehst holst du dir die Bytes, die das Icon beinhalten auf den Rechner und liest nur diese aus.
So hast du die notwendige Downloadgröße auf 0,1% reduziert.
Nachteil:
- Du müsstest wissen an welcher Stelle im Code das Icon liegt und ich weiß auch nicht ob man mit dem Filereader nur bestimmte Bytes auslesen kann. -
-
Antwort von MSDN ist da.
Hallo Bernd,
die Werte die Du suchst stehen in HKEY_CLASSES_ROOT und zwar als Schlüssel DefaultIcon. In der Regel findest Du den Schlüssel in der ausgeschriebenen Version eines jeden Dateityps (z.B. dllfile statt dll).
Die Werte des Schlüssels DefaultIcon sind aber nur Verweise auf Ressourcendateien oder eingebettete Ressourcen. Um diese Bilder zu nutzen, musst Du jeweillige Datei laden und die Ressource auslesen.
Schöne Grüße
Oliver
Ich schaue nochmals mit regedit da rein.
Edit:
~blaze~ , meinst du die ?
-
Ja genau. Das war das was ich gemeint habe. Die Extension ist ja genau der Sub-Key des HKEY_CLASSES_ROOT und der Default-Eintrag verweist auf den Key, der das DefaultIcon definiert.
Per Microsoft.Win32.RegistryKey kannst du auf die Schlüssel zugreifen (Microsoft.Win32.Registry enthält statische Felder, die auch den Classes-Root-Schlüssel enthalten).
Spoiler anzeigen VB.NET-Quellcode
- <System.Runtime.InteropServices.DllImport("shell32.dll")> _
- Private Shared Function ExtractIcon(ByVal hInst As IntPtr, ByVal lpIconPath As String, ByVal lpiIcon As Integer) As IntPtr
- End Function
- Public Shared Function GetIcon(ByVal extension As String) As Icon
- 'Key der Extension finden (extension muss mit . anfangen)
- Dim extensionKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(extension)
- If extensionKey IsNot Nothing Then 'Wenn der Key gefunden werden konnte, wird der Default-Wert ermittelt
- Dim extensionInfo As Microsoft.Win32.RegistryKey
- Dim extensionInfoObject As Object = extensionKey.GetValue(Nothing, Nothing)
- If extensionInfoObject IsNot Nothing Then 'wenn ein Default-Wert existiert, ...
- Select Case extensionKey.GetValueKind(Nothing) 'wird der Typ des jeweiligen untersucht
- Case Microsoft.Win32.RegistryValueKind.String 'bei Strings wird einfach der referenzierte Knoten geoeffnet
- extensionInfo = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(DirectCast(extensionInfoObject, String))
- Exit Select
- Case Microsoft.Win32.RegistryValueKind.ExpandString
- 'Wenn der String erweiterbare Umgebungsvariablen enthalet werden diese erweitert und der Knoten anschliessend geoeffnet
- extensionInfo = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(Environment.ExpandEnvironmentVariables(DirectCast(extensionInfoObject, String)))
- Exit Select
- Case Else
- extensionKey.Close() 'Falls der Typ nicht unterstuetzt wird, wird einfach Null (Nothing) zurueckgegeben
- Return Nothing
- End Select
- 'Wenn der Schluessel mit weiteren Informationen zum Typen verfuegbar ist
- If extensionInfo IsNot Nothing Then
- 'Wird der DefaultIcon-Schluessel geoeffnet
- Dim defaultIcon As Microsoft.Win32.RegistryKey = extensionInfo.OpenSubKey("DefaultIcon")
- If defaultIcon IsNot Nothing Then 'existiert dieser, ...
- 'wird dessen Standardwert ermittelt
- Dim defaultIconValue As Object = defaultIcon.GetValue(Nothing, Nothing)
- If defaultIconValue IsNot Nothing Then 'existiert dieser, ...
- Dim kind As Microsoft.Win32.RegistryValueKind = defaultIcon.GetValueKind(Nothing)
- 'werden alle jetzt nicht mehr benoetigten Schluessel geschlossen
- defaultIcon.Close()
- extensionKey.Close()
- extensionInfo.Close()
- 'der Typ des Knotens wird untersucht
- If kind = Microsoft.Win32.RegistryValueKind.ExpandString Then
- 'Erweiterbare Umgebungsvariablen werden wieder erweitert
- defaultIconValue = Environment.ExpandEnvironmentVariables(DirectCast(defaultIconValue, String))
- ElseIf Not kind = Microsoft.Win32.RegistryValueKind.String Then
- 'Nicht unterstuetzte Typen resultieren in einem Rueckgabewert Null (Nothing)
- Return Nothing
- End If
- 'Existiert ein Verweis auf eine Icon-Datei...
- If Not String.IsNullOrEmpty(DirectCast(defaultIconValue, String)) Then
- 'wird der String formattiert (siehe Format-Funktion unten)
- Dim formatted() As String = Format(DirectCast(defaultIconValue, String), New String() {})
- If formatted Is Nothing Then 'schlaegt das formattieren fehl, wird null zurueckgegeben
- Return Nothing
- ElseIf formatted.Length = 1 Then 'enthaelt das formattierte Array nur einen Wert
- 'wird untersucht, ob eine Datei mit dem Pfad existiert
- If IO.File.Exists(formatted(0)) Then
- 'und das Icon der Datei extrahiert
- Return Icon.ExtractAssociatedIcon(formatted(0))
- Else
- 'andernfalls wird nichts zurueckgegeben
- Return Nothing
- End If
- ElseIf formatted.Length = 2 Then 'sind zwei Werte vorhanden
- 'wird wieder ueberprueft, ob eine Datei mit dem Dateinamen existiert
- If IO.File.Exists(formatted(0)) Then
- Dim arg As Integer
- 'es wird ueberprueft, ob der zweite Parameter eine Ganzzahl ist
- If Integer.TryParse(formatted(1), arg) Then
- If arg = -1 Then 'ist arg = -1, wird es einfach mit 0 ersetzt (-1 gibt die Anzahl der Icons zurueck)
- arg = 0
- End If
- 'Findet das Icon-Handle
- Dim hicon As IntPtr = ExtractIcon(Process.GetCurrentProcess().Handle, formatted(0), arg)
- If hicon = IntPtr.Zero Then 'wenn die Funktion fehlschlaegt, wird Null (Nothing) zurueckgegeben
- Return Nothing
- Else
- 'andernfalls wird ein Icon vom Handle erzeugt
- Return Icon.FromHandle(hicon)
- End If
- Else 'schlaegt die Integer-Konversion des 2. Arguments fehl, wird Null (Nothing) zurueckgegeben
- Return Nothing
- End If
- Else 'ist eine ungueltige Anzahl an Argumenten vorhanden, wird Null (Nothing) zurueckgegeben
- Return Nothing
- End If
- Else 'schlaegt die Integer-Konversion des Arguments fehl, wird Null (Nothing) zurueckgegeben
- Return Nothing
- End If
- Else 'existiert kein Verweis auf eine Datei, die ein Icon bereitstellt, wird Null (Nothing) zurueckgegeben
- Return Nothing
- End If
- Else 'existiert kein Standardwert fuer den DefaultIcon-Schluessel, wird Null (Nothing) zurueckgegeben
- defaultIcon.Close()
- extensionKey.Close()
- extensionInfo.Close()
- Return Nothing
- End If
- Else 'existiert der DefaultIcon-Schluessel nicht, wird Null (Nothing) zurueckgegeben
- extensionKey.Close()
- extensionInfo.Close()
- Return Nothing
- End If
- Else 'existiert der Schluessel nicht, auf den der Schluessel der Dateierweiterung verweist, wird Null (Nothing) zurueckgegeben
- extensionKey.Close()
- Return Nothing
- End If
- Else 'ist kein Standardwert fuer den Erweiterungsschluessel verfuegbar, wird Null (Nothing) zurueckgegeben
- extensionKey.Close()
- Return Nothing
- End If
- Else 'Existiert kein Schluessel fuer die Erweiterung, wird Null (Nothing) zurueckgegeben
- Return Nothing
- End If
- End Function
- Public Shared Function Format(ByVal input As String, ByVal arguments() As String) As String()
- 'Zwischenpuffer
- Dim outputBuffer As New System.Text.StringBuilder(input.Length)
- Dim numberBuffer As New System.Text.StringBuilder(256)
- Dim temporaryInt As Integer
- Dim chars As IEnumerator(Of Char) = input.GetEnumerator()
- Dim output As New List(Of String)(2) 'Sinnvolle Kapazitaet der Liste angeben (eigentlich genuegen 2)
- While chars.MoveNext()
- If chars.Current = ","c Then 'einzelne Segmente trennen
- output.Add(outputBuffer.ToString()) 'zuletzt eingelesenes und ausgewertetes Segment hinzufuegen
- outputBuffer.Remove(0, outputBuffer.Length) 'Puffer leeren
- ElseIf chars.Current = """"c Then 'Gaensefuesschen erreicht (liest bis zum naechsten Gaensefuesschen)
- Do
- If chars.MoveNext() Then
- 'Wenn der Buchstabe ein % ist, wird eine Zahl eingelesen, die ein Argument (arguments)
- 'anspricht
- If chars.Current = "%"c Then
- If chars.MoveNext() Then
- If chars.Current = "%"c Then
- outputBuffer.Append("%"c) '%% als % auswerten
- ElseIf Char.IsLetterOrDigit(chars.Current) Then
- 'solange Buchstaben einlesen, bis ein nicht alphanumerischer Buchstabe erreicht wird.
- Do
- numberBuffer.Append(chars.Current)
- Loop While Char.IsLetterOrDigit(chars.Current) AndAlso chars.MoveNext()
- 'ist die Eingabe ueberhaupt eine Zahl...
- If Integer.TryParse(numberBuffer.ToString(), temporaryInt) Then
- '... wird ueberprueft, ob sie ein gueltiges Argument ist
- If temporaryInt >= arguments.GetLowerBound(0) AndAlso temporaryInt <= arguments.GetUpperBound(0) Then
- outputBuffer.Append(arguments(temporaryInt)) 'das Argument wird dem Puffer hinzugefuegt
- Else
- Return Nothing 'nicht genuegend Argumente
- End If
- Else
- Return Nothing 'ungueltige Zahl
- End If
- End If
- End If
- ElseIf Not chars.Current = """" Then 'wenn der Buchstabe kein Gaensefuesschen ist, ...
- outputBuffer.Append(chars.Current) '... wird es dem Puffer hinzugefuegt
- Else
- 'sonst wird der Puffer verlassen (mit Exit Do prinzipiell guenstiger, als per Variable)
- Exit Do
- End If
- Else
- Return Nothing 'ungueltige Syntax
- End If
- Loop
- Else
- outputBuffer.Append(chars.Current) '"normale" Zeichen werden unveraendert dem Puffer hinzugefuegt
- End If
- End While
- output.Add(outputBuffer.ToString()) 'letztes Segment der Liste hinzufuegen
- Return output.ToArray() 'Array der Liste ausgeben
- End Function
Und hier ein kleines Anwendungsbeispiel:
VB.NET-Quellcode
- Public Sub EnumerateExtensionIcons()
- Dim images As New ImageList 'Liste der Bilder erstellen
- Dim icon As Icon'Momentanes Icon
- images.ColorDepth = ColorDepth.Depth32Bit 'Farbtiefe auf 32-Bit ARGB einstellen
- images.Images.Add(Me.Icon) 'Standardicon 'Irgendein Icon als Standardicon hinzufuegen (steht fuer nicht ermittelbare Icons)
- tvExtensions.BeginUpdate()'Update des Ziel-Treeviews einleiten
- For Each rkn As String In Microsoft.Win32.Registry.ClassesRoot.GetSubKeyNames() 'Alle Schluessel in ClassesRoot durchlaufen
- If rkn.Length > 0 AndAlso rkn.Chars(0) = "."c Then'ueberpruefen, ob der Schluessel eine Dateierweiterung ist/sein koennte
- icon = GetIcon(rkn)'Icon ermitteln
- If icon Is Nothing Then'Wenn kein Icon verfuegbar ist, wird das Standardicon (Index = 0) eingesetzt
- tvExtensions.Nodes.Add(rkn, rkn, 0, 0)
- Else
- images.Images.Add(icon)'ansonsten wird das Icon zur Liste hinzugefuegt
- tvExtensions.Nodes.Add(rkn, rkn, images.Images.Count - 1, images.Images.Count - 1) 'und ein Item mit den Bild-Indices erzeugt
- End If
- End If
- Next
- tvExtensions.ImageList = images 'die Bilderliste der TreeView auf die Liste setzen
- tvExtensions.EndUpdate() 'Update abschliessen
- End Sub
Gruß
~blaze~ -
Hallo ~blaze~,
coole Nr. die du abziehst. Vielen dank dafür.
Aber gleich noch ne Frage hinterher geschoben.
Damit später das Icon einer Extension zugeordnet werden kann, habe ich mir gedacht
- in der ImageListe das Icon und das Extension zu speichern.
- das Extension könnte ja im Tag platz nehmen.
Das mache ich dann wie folgt
VB.NET-Quellcode
- ImageList1.Images.Add(icon) 'ansonsten wird das Icon zur Liste hinzugefuegt
- ' Den Namen und die lfd. Nr. anzeigen lassen
- ListBox1.Items.Add(rkn & " -> " & (ImageList1.Images.Count - 1).ToString)
- ' Den Namen in der Tag mitschreiben
- ImageList1.Images.Item(ImageList1.Images.Count - 1).Tag = rkn.ToString
Er bringt mir keinen Fehler, nun gehe ich davon aus er macht es auch.
Leider bringt er mir nichts mehr zurück.
Griefe ich denn nicht auf das Richtige Item zurück. beim einschreiben ins TAG ?
Oder soll ich lieber Paralell eine Dictonary laufen lassen ?
danke
BerndDieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Bernd“ ()
-
ImageList kann bereits Keys Bilder zuordnen.
Generell würde ich selbst Tags vermeiden, da sie einfach viel zu allgemein nutzbar sind und man schnell den Überblick verliert. Die würde ich wenn dann nur in kleinen Programmen verwenden.
Gruß
~blaze~ -
Ok ~balze~
ich glaube ein danke reicht hier bald nicht mehr.
wenn du mal Hilfe brauchst, scheu dich nicht mich zu fragen.
DANKE
Ich hatte bisher noch nicht das Vergnügen mit TreeView und ImageListe.
Meine anderen Projekte habe eigentlich immer mit einem DGV realisiert. Was eigentlich auch schöner ist.
Nuja und die Beispiele in meinen Büchern und bei MSDN sind nciht immer die ausgibigsten.
naja, nu weis ich ja bescheid.
vielen dank
Bernd -
Diese kleine Function von mir holt einfach das Icon, das bei einem Dateityp angezeigt wird.
VB.NET-Quellcode
- Public Function GetIcon(ByVal extension As String) As Icon
- extension = extension.ToLower()
- Dim tmpFile As String = Application.LocalUserAppDataPath & "\tmp." & extension
- System.IO.File.Create(tmpFile).Close()
- Dim icon As Icon = icon.ExtractAssociatedIcon(tmpFile)
- System.IO.File.Delete(tmpFile)
- Return icon
- End Function
So wird eine vordefinierte ImageList völlig überflüssig.Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Quadsoft“ ()
-
Imagelists sind eigentlich schon relativ weit verbreitet. Ich finde DataGridViews generell nicht schlecht, aber wenn man sich Programme so ansieht, stellt man fest, dass sie sehr selten benutzt werden. Für ListViews, DataGridViews usw. läuft das ganze übrigens analog. Die ImageList wird nur zum zwischenspeichern der Icons verwendet.
@Quadsoft:
Ich glaube du hast den Sinn einer ImageList nicht ganz verstanden... TreeViews und ListViews können zum Anzeigen der Icons ImageList-Instanzen verwenden. Das mache ich mir hier zunutze. Deine Funktion ist im Übrigen total unsauber und es läuft abgesehen von der verwendeten Datei auf das gleiche hinaus.
Gruß
~blaze~ -
~blaze~ schrieb:
Ich glaube du hast den Sinn einer ImageList nicht ganz verstanden... TreeViews und ListViews können zum Anzeigen der Icons ImageList-Instanzen verwenden.
Das ist mir klar. Aber warum sollte man eine ImageList mit 1000 Icons von den verschiedensten Dateitypen mitschleppen? Unterstelle mir nicht, es nicht verstanden zu haben. Man muss auch bei Verwendung meiner Funktion eine ImageList erstellen, aber nur mit denjenigen Icons, die man auch wirklich benutzen will (dynamisch)
Und btw: Die Funktion gibt das Icon eines Dateityps zurück. Wenn du mir sagst, wie es einfacher geht, dann bitte. -
-
Quadsoft schrieb:
So wird eine vordefinierte ImageList völlig überflüssig.
Extrahiert aber wieder nur das Icon aus einer vorhanden Datei.
Und was ist wenn die Datei kein Icon hat ?
Nach ~blaze~ seiner Methode findet er aber alle die sich bei Windows registriert haben.
Da ist die Trefferquote um einiges höher.
@ ~blaze~
bin noch beim Experimentieren.
Wie gesagt, ich habe mir ein Aufgabe als Ziel gesetzt. Nun greifen dort Themen die ich bisher nie gebraucht habe.
- TreeView
- ImageListe
- FTP auslesen
Wenn meine Test also etwas länger dauern ,bzw. die Antworten, liegt es daran das ich mich nicht mit C&P zufrieden gebe.
Wenn dann hacke ich solange drauf rum, bis ich das auch in der Birne habe.
Danke euch Beiden
Bernd -
ImageList ist einfach eine Collection, auf die man mit Schlüssel und/oder per Index zugreifen kann. Wenn Bilder ohne Index übergeben werden geht das mit dem Schlüssel halt nicht so einfach. ImageLists können außerdem noch verschiedene Farbtiefen für die Bilder unterstützten, wie 32-Bit Argbs.
TreeView und ListView enthalten beide Auflistungen. Das TreeView stellt mit der Nodes-Eigenschaft eine Auflistung von Knoten zur Verfügung. Knoten können wieder eigene Knoten enthalten. Das wird über die Nodes-Eigenschaft der jeweiligen Knoten geregelt. Außerdem können Knoten einen ImageKey und einen ImageIndex angeben, der ihnen ein Bild aus einer ImageList lädt. Die ImageList wird der ImageList-Eigenschaft des TreeViews zugewiesen, damit die Knoten darauf zugreifen können. ListViews enthalten normalerweise nur "oberste Items", also Items, die keine eigenen Unter-Items enthalten.
Wenn ich es noch richtig in Erinnerung habe, geht man beim Zugriff auf den Ftp-Server so vor:
- Webclient auf die URI erstellen
- Method (siehe System.Net.WebRequestMethods.Ftp z.B. System.Net.WebRequestMethods.Ftp.ListDirectory), Credentials usw. zuweisen
- Response abfragen
- Response-Stream auswerten
Bei System.Net.WebRequestMethods.Ftp.ListDirectory sind die Dateien durch Zeilen getrennt, wenn ich mich nicht täusche.
Gruß
~blaze~
-
Ähnliche Themen
-
5 Benutzer haben hier geschrieben
- Gast (39)
- ~blaze~ (17)
- Quadsoft (3)
- haiyyu (3)
- RodFromGermany (1)