none
Datei aus Anwendung entpacken RRS feed

  • Frage

  • Hallo,

    Gibt es eine Möglichkeit eine Datei aus meiner Anwendung zu entpacken, wenn ich die Anwendung starte? Ich suche kein Setup-Projekt! Ich will es wirklich aus meiner .exe-Datei entpacken.


    Koopakiller - http://koopakiller.ko.ohost.de/
    Montag, 5. Dezember 2011 18:10

Antworten

  • Hallo K.,

    Szenario A:

    Mal angenommen, Du hast die Datei Settings.exe über [Projekt > Eigenschaften > Ressourcen > Ressource hinzufügen > Vorhandene Datei hinzufügen...] als Ressource hinzugefügt. Nach erfolgtem Import heißt deine Ressource nun Settings.

    So extrahierst Du die Datei aus den Ressourcen (einfache Version):

    string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "settings.exe");

    byte[] fileBytes = Properties.Resources.Settings;

    File.WriteAllBytes(fileName, fileBytes);

    Wenn Du die Neugier hast, zu sehen, was dahintersteckt, kannst Du nach Import der Ressource die Datei Resources.Designer.cs im Editor öffnen und dir die Property Settings ansehen. Du wirst merken, dass hier eine Klasse namens ResourceManager verwendet wird (auf die ich bereits im ersten Posting hingewiesen habe). Über den Aufruf ResourceManager.GetObject("Settings", resourceCulture) wird ein Objekt zurückgegeben, das anschließend in ein byte[]-Array umgewandelt wird.

     

    Aber der Zugriff auf die Ressource kann auch low-level und entsprechend performant (wenn z.B. mehrere Resourcen gleichzeitig extrahiert werden sollen) gestaltet werden:

    Assembly executingAssembly = this.GetType().Assembly;
    string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Settings.exe");

     

    string exeFileResourceName = "Settings";

    string applicationNamespace = "WindowsFormsApplication1";

    string propertiesNamespace = String.Format("{0}.Properties", applicationNamespace);

    string resourcesNamespace = String.Format("{0}.Resources", propertiesNamespace);

     

    string resgenExtension = "resources";

    string completeResourceName = String.Format("{0}.{1}", resourcesNamespace, resgenExtension);

     

    using (Stream resourceStream = executingAssembly.GetManifestResourceStream(completeResourceName)) {

        if(resourceStream != null) {

            ResourceReader reader = new ResourceReader(resourceStream);

     

            foreach (DictionaryEntry entry in reader) {

                if (entry.Key.ToString() == exeFileResourceName) {

                    byte[] fileBytes = (byte[])entry.Value;

                    File.WriteAllBytes(fileName, fileBytes);

                }

            }

        }

    }

     

    Wie Du siehst, muss der Ressourcenname aus mehreren Informationsteilen zusammengestellt werden (nochmals: s. Chris Sells Artikel oben). Der Ressourcen-Strom wird anschließend an einen ResourceReader weitergegeben, der die DictionaryEntry-Einträge durchsucht, den richtigen findet und das Byte-Array letztendlich auf die Festplatte speichert.

    Szenario B (s. Link in Stefans Posting):
    Wenn Du hingegen die ausführbare Datei über Projekt > Vorhandenes Element hinzufügen in dein Projekt eingefügt hast (und im Eigenschaftenfenster als Buildvorgang 'Eingebettete Ressource' ausgewählt hast!), kann die Ressource über einen voll qualifizierten Namen angesprochen werden, der sich wie folgt zusammensetzt:

    [Standardnamespace].[Relativer Projektpfad].[DateiName]

    D.h. wenn dein Standardnamespace (Projekt > Eigenschaften > Anwendung) z.B. WindowsFormsApplication1 lautet und Du die Datei im Projektordner EXE gespeichert hast, würde der Ressourcenname so aussehen:

    WindowsFormsApplication1.EXE.Settings.exe

    Und falls die ausführbare Datei im Projekt-Stammordner residiert:

    WindowsFormsApplication1.Settings.exe


    Gruß
    Marcel

    • Bearbeitet Marcel RomaModerator Mittwoch, 7. Dezember 2011 11:25 Text verschoben
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 18:38
    Dienstag, 6. Dezember 2011 21:42
    Moderator
  • Hi,

    wenn Du auch noch sagen würdest, wo Du diese Datei wie in deiner Anwendung vorliegen hast, könnte man dir evtl. auch helfen.

    Falls das auch Teil deiner Frage ist: Man kann auch Dateien als Resource in die Anwendung packen und diese dann bspw. per

      System.IO.File....

    ins Dateisystem schreiben. Siehe dazu bspw.:

      http://social.msdn.microsoft.com/Forums/de-DE/visualcsharpde/thread/1ef5bfd9-a54b-4dfb-9c3f-66dd28d1cf93/

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    • Als Antwort vorgeschlagen Marcel RomaModerator Mittwoch, 7. Dezember 2011 17:40
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 18:38
    Montag, 5. Dezember 2011 19:38
    Moderator
  • Hallo K.,

    Du könntest die gewünschte Datei einfach als Resource in deine Anwendung packen (wie Stefan das bereits vorschlug!). Da Resourcen in den Metadaten der Assembly eingebettet sind, kann man sehr einfach auf sie zugreifen. Die zwei gebräuchlichsten Modi sind der direkte Zugriff über Stream und der Zugriff über den ResourceManager. Bei Dateien ist meist der Streamzugriff gebräuchlich, da etwas performanter.

    GetManifestResourceStream:
    http://msdn.microsoft.com/de-de/library/xc4235zt(v=VS.100).aspx

    ResourceManager:
    http://msdn.microsoft.com/de-de/library/system.resources.resourcemanager.aspx

    Ralph Westphal - Single Assembly Deployment of Managed and Unmanaged Code (Codebeispiel):
    http://weblogs.asp.net/ralfw/archive/2007/02/04/single-assembly-deployment-of-managed-and-unmanaged-code.aspx 

    Chris Sells - Microsoft .NET Framework Resource Basics:
    http://msdn.microsoft.com/de-de/library/ms950960.aspx

    Gruß
    Marcel

    • Bearbeitet Marcel RomaModerator Dienstag, 6. Dezember 2011 08:54 Hinweis auf Stefans Posting
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 16:55
    Dienstag, 6. Dezember 2011 08:30
    Moderator

Alle Antworten

  • Hi,

    wenn Du auch noch sagen würdest, wo Du diese Datei wie in deiner Anwendung vorliegen hast, könnte man dir evtl. auch helfen.

    Falls das auch Teil deiner Frage ist: Man kann auch Dateien als Resource in die Anwendung packen und diese dann bspw. per

      System.IO.File....

    ins Dateisystem schreiben. Siehe dazu bspw.:

      http://social.msdn.microsoft.com/Forums/de-DE/visualcsharpde/thread/1ef5bfd9-a54b-4dfb-9c3f-66dd28d1cf93/

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    • Als Antwort vorgeschlagen Marcel RomaModerator Mittwoch, 7. Dezember 2011 17:40
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 18:38
    Montag, 5. Dezember 2011 19:38
    Moderator
  • Hallo K.,

    Du könntest die gewünschte Datei einfach als Resource in deine Anwendung packen (wie Stefan das bereits vorschlug!). Da Resourcen in den Metadaten der Assembly eingebettet sind, kann man sehr einfach auf sie zugreifen. Die zwei gebräuchlichsten Modi sind der direkte Zugriff über Stream und der Zugriff über den ResourceManager. Bei Dateien ist meist der Streamzugriff gebräuchlich, da etwas performanter.

    GetManifestResourceStream:
    http://msdn.microsoft.com/de-de/library/xc4235zt(v=VS.100).aspx

    ResourceManager:
    http://msdn.microsoft.com/de-de/library/system.resources.resourcemanager.aspx

    Ralph Westphal - Single Assembly Deployment of Managed and Unmanaged Code (Codebeispiel):
    http://weblogs.asp.net/ralfw/archive/2007/02/04/single-assembly-deployment-of-managed-and-unmanaged-code.aspx 

    Chris Sells - Microsoft .NET Framework Resource Basics:
    http://msdn.microsoft.com/de-de/library/ms950960.aspx

    Gruß
    Marcel

    • Bearbeitet Marcel RomaModerator Dienstag, 6. Dezember 2011 08:54 Hinweis auf Stefans Posting
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 16:55
    Dienstag, 6. Dezember 2011 08:30
    Moderator
  • Hallo Marcel,

    nur aus Interesse: Wo ist jetzt der große Unterschied zu dem, was ich geschrieben habe?

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 17:05
    • Tag als Antwort aufgehoben Marcel RomaModerator Mittwoch, 7. Dezember 2011 17:39
    Dienstag, 6. Dezember 2011 08:35
    Moderator
  • Hallo Stefan,

    Die Gemeinsamkeiten überwiegen. Ich wollte dich nicht korrigieren, sondern nur etwas mehr Informationen in die Diskussion einfließen lassen. Also danke für deine Frage. Ich hätte auf dein Posting konkret Bezug nehmen sollen. Ich habe das zwischenzeitlich nachgeholt.

    Gruß
    Marcel

    Dienstag, 6. Dezember 2011 08:55
    Moderator
  • Bei mir Scheiterts jetzt noch an der Zeile hier:

    someStream = thisAssembly.GetManifestResourceStream(".......settings.exe");

    Ich weis nicht wie genau ich das aufrufen soll um an settings.exe ran zu kommen.

     


    Koopakiller - http://koopakiller.ko.ohost.de/
    Dienstag, 6. Dezember 2011 19:00
  • Hallo K.,

    Szenario A:

    Mal angenommen, Du hast die Datei Settings.exe über [Projekt > Eigenschaften > Ressourcen > Ressource hinzufügen > Vorhandene Datei hinzufügen...] als Ressource hinzugefügt. Nach erfolgtem Import heißt deine Ressource nun Settings.

    So extrahierst Du die Datei aus den Ressourcen (einfache Version):

    string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "settings.exe");

    byte[] fileBytes = Properties.Resources.Settings;

    File.WriteAllBytes(fileName, fileBytes);

    Wenn Du die Neugier hast, zu sehen, was dahintersteckt, kannst Du nach Import der Ressource die Datei Resources.Designer.cs im Editor öffnen und dir die Property Settings ansehen. Du wirst merken, dass hier eine Klasse namens ResourceManager verwendet wird (auf die ich bereits im ersten Posting hingewiesen habe). Über den Aufruf ResourceManager.GetObject("Settings", resourceCulture) wird ein Objekt zurückgegeben, das anschließend in ein byte[]-Array umgewandelt wird.

     

    Aber der Zugriff auf die Ressource kann auch low-level und entsprechend performant (wenn z.B. mehrere Resourcen gleichzeitig extrahiert werden sollen) gestaltet werden:

    Assembly executingAssembly = this.GetType().Assembly;
    string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Settings.exe");

     

    string exeFileResourceName = "Settings";

    string applicationNamespace = "WindowsFormsApplication1";

    string propertiesNamespace = String.Format("{0}.Properties", applicationNamespace);

    string resourcesNamespace = String.Format("{0}.Resources", propertiesNamespace);

     

    string resgenExtension = "resources";

    string completeResourceName = String.Format("{0}.{1}", resourcesNamespace, resgenExtension);

     

    using (Stream resourceStream = executingAssembly.GetManifestResourceStream(completeResourceName)) {

        if(resourceStream != null) {

            ResourceReader reader = new ResourceReader(resourceStream);

     

            foreach (DictionaryEntry entry in reader) {

                if (entry.Key.ToString() == exeFileResourceName) {

                    byte[] fileBytes = (byte[])entry.Value;

                    File.WriteAllBytes(fileName, fileBytes);

                }

            }

        }

    }

     

    Wie Du siehst, muss der Ressourcenname aus mehreren Informationsteilen zusammengestellt werden (nochmals: s. Chris Sells Artikel oben). Der Ressourcen-Strom wird anschließend an einen ResourceReader weitergegeben, der die DictionaryEntry-Einträge durchsucht, den richtigen findet und das Byte-Array letztendlich auf die Festplatte speichert.

    Szenario B (s. Link in Stefans Posting):
    Wenn Du hingegen die ausführbare Datei über Projekt > Vorhandenes Element hinzufügen in dein Projekt eingefügt hast (und im Eigenschaftenfenster als Buildvorgang 'Eingebettete Ressource' ausgewählt hast!), kann die Ressource über einen voll qualifizierten Namen angesprochen werden, der sich wie folgt zusammensetzt:

    [Standardnamespace].[Relativer Projektpfad].[DateiName]

    D.h. wenn dein Standardnamespace (Projekt > Eigenschaften > Anwendung) z.B. WindowsFormsApplication1 lautet und Du die Datei im Projektordner EXE gespeichert hast, würde der Ressourcenname so aussehen:

    WindowsFormsApplication1.EXE.Settings.exe

    Und falls die ausführbare Datei im Projekt-Stammordner residiert:

    WindowsFormsApplication1.Settings.exe


    Gruß
    Marcel

    • Bearbeitet Marcel RomaModerator Mittwoch, 7. Dezember 2011 11:25 Text verschoben
    • Als Antwort markiert KK Senior Mittwoch, 7. Dezember 2011 18:38
    Dienstag, 6. Dezember 2011 21:42
    Moderator