BIN Ressource teilweise auslesen und in Datei schreiben



  • Hallo zusammen,
    ich möchte gerne ein Programm erstellen, welches eine Binary Ressource,
    die vorher vom User an die Datei "angehängt" wurde, als Datei schreibt.

    Im Grunde ist dies kein Problem, da ich bereits folgenden Code verwende:

    HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_BIN1), "BIN");
    HGLOBAL hResLoaded = LoadResource(NULL, hRes);
    DWORD dwResSize = SizeofResource(NULL, hRes);
    LPVOID pData = LockResource(hResLoaded);
    
    DWORD dwBytesWritten = 0;
    HANDLE hTemp = CreateFile("test.dll", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
    WriteFile(hTemp, pData, dwResSize, &dwBytesWritten, NULL);
    
    CloseHandle(hTemp);
    UnlockResource(hResLoaded);
    

    Nun kann es aber sein, dass der User vorher schon eine große Datei
    angehängt hat (vlt. ca. 50 MB).

    Nun meine Frage:
    Ist diese Möglichkeit des Schreibens der Datei eine Gute?
    Ich mache mir da nämlich Sorgen bezgl. des Arbeitsspeichers und ich weiß nicht
    genau, wie WriteFile(...) arbeitet; ich stelle mir das so vor, dass die Daten zunächst in den Arbeitsspeicher und dann geschrieben werden.

    Als ich zum Test mal eine 20MB Ressource anhing und diese schrieben lies, nahm
    mein Programm ein paar mehr Megabyte in Anspruch. Wenn nun ein User wenig
    Arbeitsspeicher zur Verfügung hat, möchte ich auf keinen Fall, dass das
    Programm den Rechner in die Knie zwingt 🙄

    Und meine zweite Frage: Wie wäre es denn schließlich doch möglich,
    die Größe des Buffers selbst zu bestimmen?

    praktisch so:

    while (dwBytesTotalRead < dwResSize)
    	{
    		(Jeweils immer z.B. 1000 Bytes oder so aus pData lesen)
    		WriteFile(...)
    		(mit Angabe der Buffergröße)
    		dwBytesTotalRead += dwBytesRead;
    	}
    
    Nur wie kriegt man das mit dem Auslesen einer bestimmten Anzahl von Bytes aus der Ressource hin?
    

    Hoffe, dass ihr mir irgendwie helfen könnt,

    Mfg
    crazychicken 😃



  • Ich glaube man kann das Handle (hResLoaded) einfach nach void* casten.


  • Mod

    Die EXE wird in jedem Fall in den Speicher geladen. In die Kniw wirst Du den Rechner damit aber sichelrich nicht zwingen, denn Windows geht damit sehr dynamisch um und wirft die EXE Teile, die gerade nicht benötigt werden (auch andere Programme) aus dem Speicher.

    Aber warum willst Du diesen Weg gegen, eine so große Ressource in Deine EXE einzubauen? Für die EXE ist es in jedem Fall ungünstig, oder soll das so was wie ein Installer werden?



  • Hallo,
    vielen Dank schonmal für eure Antworten 🙂
    Ja, es soll so etwas ähnliches wie ein Installer werden; genauer gesagt
    wie ein selbstextrahierendes Archiv - da bleiben mir ja leider nicht viele
    Möglichkeiten 😕

    Dass Windows damit sehr dynamisch umgeht, beruhigt mich 🙂 - dann wäre die
    oben stehende Möglichkeit also durchaus lauffähig, auch wenn der zur
    Vefügung stehende Arbeitsspeicher sehr begrenzt ist; oder sehe ich das falsch?

    Was mich trotzdem noch interessieren würde wäre, ob es denn möglich ist,
    nun eine Ressource (hier BIN) "stück für stück" auszulesen und in Buffer
    zwischenzuspeichern - oder ist dies gar nicht möglich?

    Mfg und thx :),
    crazychicken 😃


  • Mod

    Nein! Windows mappt die entsprechenden Teile der EXE in den Speicher. Was nicht heißt, dass diese sofortgeladen werden, sondern sie werden bei Zugriff über den Page Manager eingemappt.



  • Alles klar, vielen Dank 👍

    Eine Frage hätte ich da allerings noch:
    Wie funktioniert der Vorgang denn nun umgekehrt, also dass eine Datei
    gelesen wird, und diese als Ressource geschrieben wird?

    Ich dachte mir, mit folgendem Code, welcher auch einwandfrei
    funktioniert, wäre dies problemlos möglich:

    HANDLE hFile;
    DWORD dwFileSize, dwBytesRead;
    LPBYTE lpBuffer;
    
    hFile = CreateFile("C:\\hallo.exe", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE != hFile)
    {
    	dwFileSize = GetFileSize(hFile, NULL);
    	lpBuffer = new BYTE[dwFileSize];
    	if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
    	{
    		HANDLE hResource;
    		hResource = BeginUpdateResource("C:\\test.exe", FALSE);
    		if (NULL != hResource)
    		{
    			if (UpdateResource(hResource, "BIN", MAKEINTRESOURCE(500), 0, (LPVOID) lpBuffer, dwFileSize) != FALSE)
    			EndUpdateResource(hResource, FALSE);
    		}
    	}
    
    	delete [] lpBuffer;        
    	CloseHandle(hFile);
    }
    

    Aber auch hier stell ich mir wieder die Frage mit dem Arbeitsspeicher;
    bei dem Vorgang "bläht" sich dieser nämlich so groß wie die Dateigröße auf
    - was ja durchaus logisch ist.

    Aber ist die Möglichkeit "elegant"? Mir fällt da keine andere Möglichkeit ein,
    die Daten als Ressource zu speichern.

    thx,
    crazychicken 😃


  • Mod

    Daten als Ressource zu Speichern ist in Zeiten von Vista Blödsinn.
    Im Normalfall hast Du kein Schreibrecht auf Deine EXE!



  • Martin Richter schrieb:

    Daten als Ressource zu Speichern ist in Zeiten von Vista Blödsinn.
    Im Normalfall hast Du kein Schreibrecht auf Deine EXE!

    Ja, dass die Speicherung von Dateien als Ressource keine elegante Möglichkeit
    ist, Daten zu speichern, ist mir durchaus bewusst. Allerdings habe ich, wie schon
    in einem früheren Beitrag erwähnt, vor, eine Art Installer, bzw. Entpackungs-
    programm zu schreiben. Desweiteren habe ich den Code nur als Beispiel in diesen
    Thread gestellt - die EXE greift nicht auf sich selbst zu, sondern öffnet die
    Anwendung "test.exe", der die Datei "hallo.exe" als Ressource angehängt wird.
    Die aktuelle Anwendung, aus der der Code stammt, hat mit beiden Anwendungen hier
    sonst nichts zu tun:

    <<Hauptanwendung>> greift auf -> <<test.exe>> zu und hängt -> <<hallo.exe>> an

    Du schreibst zwar, dass das Speichern als Ressource in Zeiten von Vista Blödsinn
    ist, doch ich wüsste doch mal gerne, welche Möglichkeiten es dann noch gebe, um
    Daten so zu speichern, dass sie sich in einer Anwendung befinden und entpackt
    werden können - das man also nur von einer Anwendung ausgeht.

    Mein Projekt (Packen von Dateien und Entpacken von Dateien u. Ressourcen,
    habe ich soweit fertig; jedoch fehlt nur noch das Speichern von Dateien als
    Ressource - als Ressource, da mir keine andere Möglichkeit bekannt ist -

    und da wüsste ich wirklich gerne, ob es eine elegantere Lösung gibt, als die
    komplette Datei in lpBuffer zwischenzuspeichern.

    Vielen Dank,
    crazychicken



  • Der Thread ist zwar schon etwas älter, aber mich würde auch mal interessieren, welche Möglichkeiten es unter Vista gibt. Ich hab gerade auch ne Anwendung geschrieben, die mit Ressourcen arbeitet - unter XP läuft es einwandfrei, aber unter Vista halt nicht...


  • Mod

    Pff...Vista schrieb:

    Der Thread ist zwar schon etwas älter, aber mich würde auch mal interessieren, welche Möglichkeiten es unter Vista gibt. Ich hab gerade auch ne Anwendung geschrieben, die mit Ressourcen arbeitet - unter XP läuft es einwandfrei, aber unter Vista halt nicht...

    Alle meine Programm arbeiten mit Resourcen! Aber alle funktionieren auch unter Vista!
    Fang einen neuen Thread an und beschreibe bitte etwas detailierter was Du meinst und wo Du Probleme hast.

    Grundsätzich Schmink es Dir ab die EXE im Programmverzeichnis zu manipulieren. Das geht unter Vista nur noch wenn das Programm evelvated läuft.


Anmelden zum Antworten