Entwickler-Ecke

Dateizugriff - TeilProgramm aus eigentlicher EXE übernehmen


IhopeonlyReader - Mi 06.06.12 15:55
Titel: TeilProgramm aus eigentlicher EXE übernehmen
Guten Tag,
ich habe mal eine Frage, kann man einen ganz simplen installer selbst bauen?
Ich weiß, dass man andere Programme in das eigentliche Programm einbinden kann.
Kann ich zum Beipsiel Programm A in Programm B einfügen (oder mit beigelegter DLL) und dann mit Programm B das Programm A hiergendwo hinkopieren?
Also ich möchte ein einen Installer haben, der die Dateien einfach nur aus "sich selbst" herauszieht.
Bei *txt, *.bat etc. da habe ich das bisher so gemacht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
F: TextFile;
begin
  AssignFile(F, ExtractFilePath(Application.ExeName)+'Beispiel.txt');     
  Rewrite(F);
  Append(F);
  Writeln(F, 'Zeile1'+slinebreak+
             'Zeile2'+slinebreak
              +slinebreak+
             'Zeile4'+slinebreak+
             'Zeile5 (und immer so weiter)');
  CloseFile(F);
end;

(natürlich mit einem sinnvollerem Textinhalt :D);
So konnte ich sozusagen eine TextDatei in mein Programm einfügen und, falls sie nicht existiert, wiedererstellen.
aber wie geht das mit anderen Dateien,z.B. *.Exe Datei?

Freu mich auf eure Antworten :)


Nersgatt - Mi 06.06.12 16:04

Das geht natürlich, ich weiß nur nicht wie.
Du kannst Dir aber mal InnoSetup (Setupgenerator) anschauen. Das ist in Delphi geschrieben worden und der Quellcode ist meines Wissens nach verfügbar.


IhopeonlyReader - Mi 06.06.12 16:37

user profile iconNersgatt hat folgendes geschrieben Zum zitierten Posting springen:
Das geht natürlich, ich weiß nur nicht wie.
Ah ja:D...

Den Quellcode habe ich jetzt leider noch nicht gefunden :(
Kennt vielleicht jemand eine direkte Möglichkeiten? Oder hat jemand direkt ne Unit zur Hand ?

Wäre sehr froh drum, da es nervt, alles immer zu Zip-Kompirmieren und dann nen ganzen Ordner immer zu haben.
Ich würde am liebsten NUR eine EXE haben, die dann entsprechend alles nutzt/ wenn etwas notwendiges nicht vorhanden ist, es erstellt wird. :)


jaenicke - Mi 06.06.12 18:07

Dabei vergisst du aber, dass ein Programm im eigenen Ordner in der Regel keine Schreibrechte hat. Das macht so wenig Sinn. Du könntest die Dateien natürlich in die Anwendungsdaten legen.
Anhängen könntest du die Daten in Ressourcen, die du mit in die .exe einkompilierst und mit TResourceStream wieder ausliest.

Sinnvoller ist aber schlicht ein Setup mit InnoSetup zu erstellen und alternativ eben ein Zip-Archiv anzubieten. Das ist viel einfacher und weniger fehleranfällig...


gerd8888 - Mi 06.06.12 20:21

Hallo,

du sagst ein ganz simpler Installer.
Das einfachste ist es, alles von Windows machen zu lassen.
Also Du kannst den Ordner einfach rüberziehen (copy paste) oder das Programm macht das für dich.

(Das so zu machen, dass Delphi dir die einzelnen Dateien rüberkopiert ist ein Haufen Arbeit)

Ich habe das Programm selbst geschrieben. Vielleicht ist es das, was Du suchst?


Nur noch eine kleine Anmerkung.
pFrom := PChar(szSource+ #0);
pTo := PChar(szDestination+ #0);
Doktor da nicht rum, das stimmt so alles!


IhopeonlyReader - Mi 06.06.12 20:22

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dabei vergisst du aber, dass ein Programm im eigenen Ordner in der Regel keine Schreibrechte hat.
Das ist mir ehrlichgesagt neu..
Wenn die Exe z.B. in einem Ordner auf dem Desktop liegt, dann kann sie dort doch Dateien erstellen??? Mit AssignFile etc. hat das auf jeden Fall bis jetzt immer gut funktioniert...


jaenicke - Mi 06.06.12 21:26

Auf dem Desktop ja, aber was haben da Programme zu suchen? :shock:
Die gehören unter c:\programme usw. und da hat man als Nicht-Admin keine Schreibrechte.
Mehr dazu:
http://www.delphi-library.de/viewtopic.php?p=548600


IhopeonlyReader - Mi 06.06.12 21:34

Auch nicht, wenn man das ganze mit Savedialog und so machen würde?... dann hat der user ja den Befehl hervorgerufen..

aber wir weichen vom Thema ab! Wie ist es möglich die Datei so einzubinden, dass man sie "extrahieren" kann?


jaenicke - Mi 06.06.12 21:52

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Auch nicht, wenn man das ganze mit Savedialog und so machen würde?... dann hat der user ja den Befehl hervorgerufen..
Dann weißt du aber nicht mehr wo du die Datei später wiederfindest...
Deshalb gibt es ja das Anwendungsdatenverzeichnis, damit Programme dort Dateien ablegen können.

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
aber wir weichen vom Thema ab! Wie ist es möglich die Datei so einzubinden, dass man sie "extrahieren" kann?
Wie ich schon geschrieben habe:
Als Ressource einbinden (.rc Datei erstellen, mit brcc32.exe kompilieren und mit {$R ...} einbinden, siehe Suche bei Google DELPHI RESSOURCE) und dann mit TResourceStream auslesen.


IhopeonlyReader - Mi 06.06.12 22:45

user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,

du sagst ein ganz simpler Installer.
[...]
(Das so zu machen, dass Delphi dir die einzelnen Dateien rüberkopiert ist ein Haufen Arbeit)

Ich habe das Programm selbst geschrieben. Vielleicht ist es das, was Du suchst?

Naja, ehrlich gesagt, leider Nein. Ich muss sagen es ist sehr gut programmiert, allerdings möchte ich, dass falls die daten NICHT existieren, sie erzeugen und dass ist in diesem Fall nicht möglich


IhopeonlyReader - Mi 06.06.12 23:27

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
und dann mit TResourceStream auslesen.

ich habe die .Res ensprechend eingebunden... hat alles geklappt, (mit BildDateien weiß ich jetzt, ´wie ich diese jetzt lade)
Ich weiß jetzt nur nicht, wie ich die Datei jetzt irgendwo speichern kann/ auslesen kann. Deine Aussage mit TResourceStream habe ich probiert, aber ich glaube da hab ich was falsch gemacht...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var Datei: TResourceStream;
begin
  try
    Datei:= TResourceStream.Create(HInstance, 'Beispiel.res''Musik1');
    Datei.SaveToFile('C:\Users\BENUTZERNAME\Desktop\Test.mp3');
  finally
    Datei.Free;
  end;
end;


Edit: Der Inhalt der Beispiel.rc Datei ist:
Musik1 MP3 "C:\Users\BENUTZERNAME\Desktop\MeineMusikDatei.mp3"

die wurde dann entsprechend zur Beispiel.res compiliert und eingebunden


jaenicke - Mi 06.06.12 23:31

Schau dir einmal in der Hilfe die Parameter des Konstruktors an...
http://docwiki.embarcadero.com/Libraries/de/System.Classes.TResourceStream.Create
Der Dateiname der Ressourcendatei vor dem Kompilieren ist zur Laufzeit vollkommen egal, da der nicht gespeichert wird. Der Konstruktor bekommt stattdessen den Namen der Ressource und deren Typ, so wie du ihn in der .rc Datei angegeben hast.

Zudem benutzt du den Ressourcenschutzblock falsch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
a := TSomething.Create;
try
  ...
finally
  a.Free;
end;


IhopeonlyReader - Mi 06.06.12 23:45

Würdest du bitte ein genaues Beispiel vorzeigen?
Ich verstehe nicht genau was ich falsch gemacht habe...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var Datei: TResourceStream;
begin
Datei := TResourceStream.Create(HInstance,'Beispiel.res' , PChar(1));
try
Datei.SaveToFile('C:\Users\Benutzername\Desktop\Test.mp3');
finally
Datei.Free;
end;
das habe ich geändert. Aber es klappt trotzdem nicht, es wird
1. gesagt die Resource wurde nicht gefunden
2. DIE resoucre ist 100% da (auch mit ExtractFilePath(Application.Exename)+'Beispiel.res' hat es nicht geklappt) ebenso ohne Endung nicht :(

Und:

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Der Dateiname der Ressourcendatei vor dem Kompilieren ist zur Laufzeit vollkommen egal, da der nicht gespeichert wird. Der Konstruktor bekommt stattdessen den Namen der Ressource und deren Typ, so wie du ihn in der .rc Datei angegeben hast.

ok... aber wie muss ich das dann aufrufen?


jaenicke - Mi 06.06.12 23:48

Wie wäre es mit dem Namen und dem Typ, den du da geschrieben hast? :zwinker:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  Datei: TResourceStream;
begin
  Datei := TResourceStream.Create(HInstance, 'Musik1''MP3');
  try
    Datei.SaveToFile('C:\Users\Benutzername\Desktop\Test.mp3');
  finally
    Datei.Free;
  end;


IhopeonlyReader - Mi 06.06.12 23:55

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Wie wäre es mit dem Namen und dem Typ, den du da geschrieben hast? :zwinker

ahhh :D :Danke:
Ich glaub, einfach immer nur Typ, Dateiname, und sonst irgendetwas zu schreiben verwirrt mich immoment nur noch :D
KLARE Beispiele (wie du es im letzen Beitrag gegeben hast) denke ich sind die sinnVOLLSTEN! Hierdurch versteht man es nicht falsch, und es lässt sich leicht auf das eigene Project anwenden (übernehmen) :)
Vielen Dank..

hier nochmal die Lösung kurz zusammengefasst:
- eine *.rc datei erstellen und zu *.res compilieren lassen ( http://board.raidrush.ws/showthread.php?t=512194 )
- res einbinden und so wie es im letzen beitrag geschrieben wurde speichern lassen ;)
(Am besten bei Datei.Savetofile den Pfad mit einem Savedialog etc. auswählen, da es sonst ein konstanter Pfad ist und dieser überschrieben wird ;) (beachtet die Endung der zu speichernden Datei)
- Programm starten :) und testen ob alles klappt


DonManfred - Mo 11.06.12 07:25

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Auch nicht, wenn man das ganze mit Savedialog und so machen würde?... dann hat der user ja den Befehl hervorgerufen..


Falsch. Der User hat es initiiert aber die ausführende Instanz ist dein Programm. Und das hat, unter Windows Vista/7, in C:\Programme keine Schreiberlaubnis.

Du könntest das umgehen indem Du dein Programm auf einem anderen Laufwerk installierst. Ansonsten bleibt Dir halt nur der Ordner AppData...


Der Weg über Resourcedateien:

1. test.rc erstellen

Quelltext
1:
#1 FILE "D:\BeKa.Source\BeKa.exe"                    


2. test.rc compilieren

Quelltext
1:
brcc32.exe test.rc -fo D:\BeKa.Source\test.res                    


3. test.res in DPR einbinden

Quelltext
1:
{$R D:\BeKa.Source\test.res}                    


4. Datei zur Laufzeit extrahieren

Quelltext
1:
SaveResource(1,installpath+'BeKa.exe');                    


wobei die 1 in SaveResource dem Eintrag #1 in der RC-Datei entspricht...