Laden...

Icons aus EXE-/DLL-Datei extrahieren

Erstellt von fusionwedge vor 19 Jahren Letzter Beitrag vor 13 Jahren 28.211 Views
Information von herbivore vor 15 Jahren

Dies ist ein Thread, auf den aus der FAQ verwiesen wird. Bitte keine weitere Diskussion, sondern nur wichtige Ergänzungen und diese bitte knapp und präzise. Vielen Dank!

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren
Icons aus EXE-/DLL-Datei extrahieren

Hallo,

wie erhalte ich bitte aus einer DLL-, einer EXE-, oder einer anderen Datei ein Symbol, um es in

meinem TreeView anzeigen lassen zu können?
Ich habs mit dem Icon-Konstruktor versucht, der akzeptiert aber nur ".ico"-dateien.

_
416 Beiträge seit 2005
vor 19 Jahren

Hi,

du kannst es mal mit der SDK Funktion ExtractIconEx versuchen und dann das Handle mit Icon.FromHandle konvertieren

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Danke.

Aber das wird bei mir in der Dokumentation nicht angezeigt (ich habe vom Framework nur die Dokumentation von 1.0, liegt es daran?).
In welchem Namespace liegt diese Methode, was ist der Rückgabewert und womit Überlade ich sie?

_
416 Beiträge seit 2005
vor 19 Jahren

Die Funktion ExtractIconEx gibts nicht im FrameWork, also auch in keinem Namespace. Du musst sie also direkt über die Windows API aufrufen.

Folgendermaßen wird sie deklariert. Beachte dass du die Icons am Ende noch zerstören musst um den reservierten Speicherplatz wieder freizugeben.

[DllImport("shell32.dll", CharSet=CharSet.Auto)]
 static extern uint ExtractIconEx(string szFileName, int nIconIndex,
   IntPtr[] phiconLarge, IntPtr[] phiconSmall, uint nIcons);

[DllImport("user32.dll", SetLastError=true)]
 static extern int DestroyIcon(IntPtr hIcon);
 

den Rückgabewert von ExtractIconEx übergibst du dann an Image.FromHandle.

Getestet hab ich das allerdings nicht, sollte aber eigentlich funktionieren.

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo fusionwedge,

ExtractIcon ist eine eine Funktion von dem Win32-API, die du dir mit DllImport reinholen kannst.

Was deine eigentliche Frage angeht. Mir ist nicht genau klar, was du willst.

  1. Icons aus bestehenden .exe und .dll Dateien rausziehen, sodass man nachher, das Icon auf der Platte hat?

Dafür gibt es extra Tools, z.B. PE Resource Explorer von http://www.wilsonc.demon.co.uk/d7resourceexplorer.htm oder Resource Hacker von http://www.users.on.net/johnson/resourcehacker/ .

  1. Icons in die .exe-Datei deines Programms einbinden, um alles in der .exe-Datei komplett zu haben, um nicht mit separaten .ico-Dateien hantieren zu müssen?

Dazu musst du das Icon in eine .resources-Datei packen die du dann per Compliler-Option /res:<name>.resources einbinden kannst. Zugriff auf das Icon bekommst du mit


rm = new ResourceManager ("<name>", GetType().Assembly);
Icon = (Icon)rm.GetObject ("<name>.ico");

Für das Erstellen von .ressource-Dateien (zur Compile-Zeit) kann man die Klasse ResourceWriter verwenden. Ich habe mir ein keines (allerdings nicht allgemein verwendbares) Tools dafür geschrieben, dass diese Klasse benutzt.

  1. Icons zur Laufzeit aus anderen .exe-Dateien laden?

In diesem Fall ist wohl wirklich ExtractIcon angezeigt.

HTH

herbivore

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Danke für die Antworten.
Wo gibt es denn eine Libary über alle API-Funktionen?
ExtractIconEx habe ich übrigens noch in meiner Visual C++6.0 Dokumentation gefunden, aber halt ohne DLL-Namen.

Ich meinte Nummer 3.

Ich wollte direkt von jeder Datei das im Explorer angezeigte Icon sehen. Und wie bekomme ich die Symbole der anderen Dateien (z.B. Txt, Doc, etc).
Ich dachte, ich finde die Pfadangaben der Bilder in der Registry, aber ich finde den (theoretisch) passenden Schlüssel nicht.
Ich wollte nämlich gerne eine Anzeige aller Ordner und Daten samt Icons haben.

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo fusionwedge,

die Pfade der Icons stehen schon in der Registry. Für z.B. .txt-Dateien guckst du unter HKEY_CLASSES_ROOT.txt und findest im Standardwert den Eintrag txtfile. Damit guckst du jetzt unter HKEY_CLASSES_ROOT\txtfile\DefaultIcon und findest dort "%SystemRoot%\system32\shell32.dll,-152" also das Icon mit dem Index 152 in der Datei %SystemRoot%\system32\shell32.dll. Die Icons müssen in der DLL als Win32-Ressourcen gespeichert sein, um auf diese weise ansprechbar zu sein.

HTH

herbivore

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Super, danke.

Ich würde euch gerne bewerten, aber das ist ja scheinbar nicht möglich!

Wo finde ich eine Dokumentation zur API?

_
416 Beiträge seit 2005
vor 19 Jahren
Hinweis von herbivore vor 10 Jahren

Link aktualisiert

Bspw. ExtractIconEx function

Wie du das ganze dann in C# einbinden kannst, kannst du bei http://www.pinvoke.net nachlesen

142 Beiträge seit 2004
vor 19 Jahren

Hallo @fusionwedge,

Ich würde auch gerne die Symbole von den Dateien, die ich in die ListView lese mit anzeigen lassen. Bin leider noch ein Anfänger, und hab es mit API Funktionen noch nicht so. Was heisen soll, das ich mein Vorhaben einfach nicht auf die Reihe bringe.

Ich wäre dir, wenn du mir helfen könntest sehr dankbar!

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Sorry, bin leider nicht oft hier.
Wenn du dich hier noch mal meldest (dann weiß ich ja, dass du das liest), dann erklär ichs dir.

142 Beiträge seit 2004
vor 19 Jahren

Hallo!

Habs glesen.

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Gut.
Was ist denn genau dein Problem?
Hast du schon eine ListView und brauchst nur noch die Symbole, oder brauchst du noch eine Art Explorer, um die Dateien zu finden?

Fusionwedge

142 Beiträge seit 2004
vor 19 Jahren

@fusionwedge

Hab da schon was gefunden, mit dem kannst du aus jeder Datei das Icon ziehn.
Der einzige Nachteil ist, das die Auflösung zu wünschen übrig läst. Kann aber auch an den Einstellungen liegen. Aber man kann damit leben!

	[StructLayout(LayoutKind.Sequential)]
	public struct SHFILEINFO
	{
		public IntPtr hIcon;
		public IntPtr iIcon;
		public uint dwAttributes;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
		public string szDisplayName;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
		public string szTypeName;
	}

	public class ExtractIcon
	{
		/// <summary>
		/// Methode zum extrahieren von einem Icon aus einer Datei.
		/// </summary>
		/// <param name="FilePath">Hier übergeben Sie den Pfad der Datei von dem das Icon extrahiert werden soll.</param>
		/// <param name="Small">Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben.</param>
		public static Icon GetIcon(string FilePath ,bool Small)
		{
			IntPtr hImgSmall;    
			IntPtr hImgLarge;         
			SHFILEINFO shinfo = new SHFILEINFO();
			if (Small)
			{
				hImgSmall = Win32.SHGetFileInfo(FilePath, 0, 
					ref shinfo,(uint)Marshal.SizeOf(shinfo),
					Win32.SHGFI_ICON |Win32.SHGFI_SMALLICON);
			}
			else
			{
				hImgLarge = Win32.SHGetFileInfo(FilePath, 0,
					ref shinfo, (uint)Marshal.SizeOf(shinfo),
					Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
			}
			return(System.Drawing.Icon.FromHandle(shinfo.hIcon));
		}
	}

	/// <summary>
	/// DLL Definition für IconExtract.
	/// </summary>
	class Win32
	{
		public const uint SHGFI_ICON = 0x100;
		public const uint SHGFI_LARGEICON = 0x0;
		public const uint SHGFI_SMALLICON = 0x1;

		[DllImport("shell32.dll")]
		public static extern IntPtr SHGetFileInfo(string pszPath,
			uint dwFileAttributes,
			ref SHFILEINFO psfi,
			uint cbSizeFileInfo,
			uint uFlags);
	}

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Wenn ich das richtig verstehe, dann musst du beim Aufruf von

GetIcon(string FilePath ,bool Small)

für den Wert Small "false" eingeben. Dann wird das große Bild zurückgegeben und du hast ne bessere Auflösung:

also so

GetIcon("C:\BlaBlaBla\Bla.txt", false);

Kann aber auch sein, dass du ein kleines Bild haben willst, dann musst du "true" eingeben:

GetIcon("C:\BlaBlaBla\Bla.txt", false);

Hoffe, dass das dein Problem ist (was ich aber nicht glaube, weil das zu offensichtlich wäre... 😄)

142 Beiträge seit 2004
vor 19 Jahren

@fusionwedge

Ich weis wie ich das anzuwenden habe, dachte nur weil du doch auch danach gesucht hast!

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

142 Beiträge seit 2004
vor 19 Jahren

@fusionwedge
Wie regelst du das mit den Icons jetzt, über die Registry?

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

using Microsoft.Win32;

// IntPtr ist ein Handle des Icons
// GetIcons()[0] gibt das große Symbol zurück und GetIcons()[1] das kleine
// Z.B. so: Icon tmp = Icon.FromHandle(GetIcons("txt", "C:\\Test\\", TestItem)[0]);
// Sonst bei fragen bitte melden. Ich hab das jetzt nämlich nicht alles umgeschrieben...

protected IntPtr[] GetIcons(string endung, string pfad, ListViewItem item)
		{
			RegistryKey key;
			
			IntPtr[] Icos	= new IntPtr[2];
			
			IntPtr[] Symbolgross	= new IntPtr[1];
			IntPtr[] Symbolklein	= new IntPtr[1];
			
/* Wenn es keinen Eintrag in der Registry für die Endung gibt, kommt catch ins Spiel (z.b.: bei .EXE und .LNK Dateien)*/
			try{
				key	= Registry.ClassesRoot.OpenSubKey(endung, true);
				
				string str		= key.GetValue(null).ToString();
				key				= Registry.ClassesRoot.OpenSubKey(str + "\\DefaultIcon", true);
				str				= key.GetValue(null).ToString();
				string temp		= str;
				int index2		= 1;
				
				while(true)
				{
					temp	= temp.Remove(0, temp.Length - index2);
					temp	= temp.Remove(1, index2 - 1);
					if(temp	== ",")
					{
						break;
						// Ende if
					}
					temp	= str;
					index2++;
					// Ende while
				}
				temp = str.Remove(0, str.Length - index2 + 1);
				
				ExtractIconEx(str.Remove(str.Length - index2, index2), Int32.Parse(str.Remove(0, str.Length + 1 - index2)), Symbolgross, Symbolklein, 1);
				Icos[0]	= Symbolgross[0];
				Icos[1]	= Symbolklein[0];
				// Ende try
			}
			catch(Exception)
			{
				if((endung.ToUpper() == ".EXE") || (endung.ToUpper() == ".LNK"))
				{
					if(ExtractIconEx(pfad + "\\" + item.Text + endung, 0, Symbolgross, Symbolklein, 1) == 0)
					{
						ExtractIconEx(Environment.SystemDirectory + "\\System32\\Shell32.dll", 0, Symbolgross, Symbolklein, 1);
						// Ende if
					}
					// Ende if
				}
				else
				{
/* Wenn es sich um eine unbekannte Endung handelt, dann wähle ein Standarticon*/
					ExtractIconEx(Environment.SystemDirectory + "\\System32\\Shell32.dll", 0, Symbolgross, Symbolklein, 1);
					// Ende else
				}
				Icos[0]	= Symbolgross[0];
				Icos[1]	= Symbolklein[0];
				// Ende catch
			}
			 return Icos;
			// Ende GetIcons()
		}

142 Beiträge seit 2004
vor 19 Jahren

@fusionwedge

Interessante Lösung über die Reg, bin begeistert.

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

F
fusionwedge Themenstarter:in
27 Beiträge seit 2005
vor 19 Jahren

Danke, die ist ja von "herbivore" (danke noch mal).

Hoffe, ich konnte dir helfen.

4.221 Beiträge seit 2005
vor 13 Jahren

Weiterer interessanter Link wie extrahiere ich Icon's aus Dll's.

StolenIcon

Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

5.742 Beiträge seit 2007
vor 13 Jahren

Weiterer interessanter Link wie extrahiere ich Icon's aus Dll's.

Dann aber bitte immer die Lizenz prüfen, ob diese das auch zulässt!