Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi [gelöst] Henne Ei Problem - eigene EXE löschen (https://www.delphipraxis.net/134972-%5Bgeloest%5D-henne-ei-problem-eigene-exe-loeschen.html)

moelski 2. Jun 2009 13:40


[gelöst] Henne Ei Problem - eigene EXE löschen
 
Moin !

Mein eigener Installer wird langsam rund doch ich bin gerade mal wieder auf ein Problem gestoßen ...
Und zwar habe ich im Anwendungsverzeichnis meinen Uninstaller (Uninstall.exe) liegen. Der löscht auch alles was ich ihm aufgetragen habe, aber er kann sich nicht selber löschen - der Zugriff wird in dem Fall verweigert.

Kann mir jemand einen Tip geben wie ich das nun hinbekomme das ich den Uninstaller auch mit löschen kann?

Namenloser 2. Jun 2009 13:42

Re: Henne Ei Problem - eigene EXE löschen
 
Das Thema gab es hier shcon öfter mal. Meistens kam dabei heraus, dass es am einfachsten ist, eine temporäre BAT-datei zu erstellen, die zuerst das Programm löscht und anschließend sich selbst - Batchdateien können das nämlich im Gegensatz zu kompilierten Programmen.

moelski 2. Jun 2009 13:45

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Zitat:

eine temporäre BAT-datei zu erstellen
Und wie wäre dann der logische Ablauf? Ich starte meinen Unistaller und der Startet dann die BAT?
Oder direkt die BAT starten ?

p80286 2. Jun 2009 13:45

Re: Henne Ei Problem - eigene EXE löschen
 
hallo Moelski,

hatten wir das nicht schonmal?
sich selbst löschen kann die EXE nicht, das ginge nur über eine Batchdatei:
Delphi-Quellcode:
Uninstaler
del Uninstaler.exe
natürlich mit den richtigen Laufwerken/Verzeichnissen garniert.

Gruß
K-H

ich bin nicht schnell genug!!!

Meflin 2. Jun 2009 13:51

Re: Henne Ei Problem - eigene EXE löschen
 
Es gibt auch eine WinAPI-Funktion, mit der man Dateien zum Löschen markieren kann. Diese werden dann beim Herunterfahren (oder Neustarten) gelöscht.

Angel4585 2. Jun 2009 13:55

Re: Henne Ei Problem - eigene EXE löschen
 
versuch mal
1. Programm starten
2. Alte Datei umbenennen
3. Neue Datei erstellen
4. Programm beenden
5. Neues Programm starten
6. Umbenannte Datei löschen

moelski 2. Jun 2009 13:57

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Zitat:

1. Programm starten
2. Alte Datei umbenennen
3. Neue Datei erstellen
4. Programm beenden
5. Neues Programm starten
6. Umbenannte Datei löschen
Wie soll das funktionieren? In dem Fall bekomme ich ja die "neue Datei" nicht gelöscht.

Angel4585 2. Jun 2009 14:41

Re: Henne Ei Problem - eigene EXE löschen
 
Achso, meinte damit, dass beim nächsten Programmstart die Datei gelöscht wird, hab den Anfangstext nicht richtig gelesen, dacht es geht um ne Live Update Funktion...

Und wenn du die Datei nicht nur umbenennst, sondern verschiebst?
Was muss denn sein damit man eine exe nicht löschen kann, exklusiver Zugriff auf die Datei?
Wer hat den Zugriff und kann man den exklusiven Zugriff aufheben?

wicht 2. Jun 2009 15:56

Re: Henne Ei Problem - eigene EXE löschen
 
Wenn der Uninstaller in C:\Programme\MyApp\uninstall.exe wohnt, könnte er sich ins Temp-Verzeichnis kopieren am Ende der Deinstallation, die Kopie ausführen und den Pfad des Original-Uninstallers mitgeben (ParamStr(1)). Die Kopie wartet, bis das Original beendet ist, löscht es dann (und das Verzeichnis MyApp) und legt für sich selbst dann mit MoveFileEx() das Löschen beim Neustart fest.
Ist auch nicht 1A, aber schöner als frickeleien mit Batch-Dateien, wie ich finde.

Aphton 2. Jun 2009 16:08

Re: Henne Ei Problem - eigene EXE löschen
 
Probiers mal mit ...
Delphi-Quellcode:
function DeleteSelf(): Boolean;
var
  F    : File of Byte;
  FP,
  Params: String;
const
  B : String =
    ':loop'#13#10+
    'del /F "%s"'#13#10+
    'if EXIST "%s" goto loop'#13#10+
    'del /F %s';
begin
  Result := False;
  FP     := ExtractFilePath( ParamStr(0) );
  {$i-}
  AssignFile( F, FP + '_.bat' );
  Rewrite( F );
  Params := Format( B, [ParamStr(0), ParamStr(0), FP + '_.bat'] );
  BlockWrite( F, Params[1], Length(Params) );
  CloseFile( F );
  {$i+}
  if not( IOResult = ERROR_SUCCESS ) then
    Exit;
  Result := ShellExecute( 0, 'open', pChar( FP + '_.bat' ), nil, nil, 0 ) > 32;
end;

moelski 2. Jun 2009 16:48

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Das geht schon ganz gut. Aber hat immer noch einen Haken ... Das Verzeichnis bleibt stehen.
Ich habe mal versucht das hier noch an die BAT anzuhängen:
Delphi-Quellcode:
             'cd ..'                  + #13#10+
             'RD "' + ParamStr(0) + '"' + #13#10 +
aber das bringts nicht.

In Summe schaut das nun so:
Delphi-Quellcode:
  BatText := ':loop'                  + #13#10+
             'ping localhost'         + #13#10+ 
             'del /F "%s"'            + #13#10+
             'if EXIST "%s" goto loop' + #13#10+
             'del /F "%s"'            + #13#10+
             'cd ..'                  + #13#10+
             'RD "' + ExtractFilePath(Application.ExeName) + '"';
Den Ping habe ich reingenommen damit die CPU Last im Rahmen bleibt.
Aber das RD zeigt keine Wirkung.

EDIT:
'RD "' + ParamStr(0) + '"' War natürlich ein Fehler. Geht aber dennoch nicht.

Aphton 2. Jun 2009 16:54

Re: Henne Ei Problem - eigene EXE löschen
 
Warum ParamStr(0) ?
Bei folgender Anwendung - test.exe, die sich in C: befindet, liefert ParamStr(0) folgendes zurück:
C:\test.exe - RD aber hingegen löscht nur Ordner..

Da ist was schiefgelaufen ;)

MfG

moelski 2. Jun 2009 16:57

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Drum hab ich ja auch sofort mein Post korrigiert auf ExtractFilePath(Application.ExeName) :wink:

Aber es geht auch damit ned.

mkinzler 2. Jun 2009 16:59

Re: Henne Ei Problem - eigene EXE löschen
 
Zitat:

Drum hab ich ja auch sofort mein Post korrigiert auf ExtractFilePath(Application.ExeName) Wink
Wobei man statt Application.Exename natürlich ParamStr(0) nehmen könnte

moelski 2. Jun 2009 17:01

Re: Henne Ei Problem - eigene EXE löschen
 
Ah jetzt verstehe ich das ...

Wenn ich die Batch lösche von der Platte, dann kann der Command Prozessor auch nicht mehr die nächsten Befehle lesen und gibt den Fehler aus "Die Batchdatei kann nicht gefunden werden.".

Also müsste man die Batch im Programm Root ablegen (c:\programme z.B.) und von dort laufen lassen. Und erst ganz zum Schluss die Batch löschen ...

mkinzler 2. Jun 2009 17:09

Re: Henne Ei Problem - eigene EXE löschen
 
Wo diese genau liegt sollte egal sein. Hauptsache du hast dort Schreibrechte und deren Löschung ist der letzte Schritt

Satty67 2. Jun 2009 17:11

Re: Henne Ei Problem - eigene EXE löschen
 
Zitat:

Zitat von moelski
Also müsste man die Batch im Programm Root ablegen (c:\programme z.B.) und von dort laufen lassen.

Auch wenn zu erwarten ist, das ein User mit Admin-Rechten deinstalliert, muss das nicht sein.

Vielleicht die Batch-Datei in den Temp-Ordner... dort wird sie dann irgendwann auch gelöscht, wenn sie durch einen Fehler als Leiche zurück bleibt.

moelski 2. Jun 2009 17:17

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Hmm das geht aber dennoch nicht. Das Verzeichnis bleibt:
Delphi-Quellcode:
function DeleteSelf(): Boolean;
var
  F      : File of Byte;
  FP,
  Params : String;
  BatText : String;
begin
  BatText := ':loop'                  + #13#10+
             'ping localhost'         + #13#10+ 
             'del /F "%s"'            + #13#10+
             'if EXIST "%s" goto loop' + #13#10+
             'RD "' + ExtractFilePath(ParamStr(0)) + '"' + #13#10 +
             'del /F "%s"'            ;

  Result := False;
  FP     := 'C:\Program Files\'; //ExtractFilePath( ParamStr(0) );
  {$i-} 
  AssignFile( F, FP + '_.bat' );
  Rewrite( F );
  Params := Format( BatText, [ParamStr(0), ParamStr(0), FP + '_.bat'] );
  BlockWrite( F, Params[1], Length(Params) );
  CloseFile( F );
  {$i+} 
  if not( IOResult = ERROR_SUCCESS ) then
    Exit;
  Result := ShellExecute( 0, 'open', pChar( FP + '_.bat' ), nil, nil, 1 ) > 32;
end;
Ich habe das Verzeichnis für die BAT mal hart kodiert.
Aber das Verzeichnis bleibt bestehen wenn ich es aus dem Programm raus starte.
Starte ich die Batch alleine, geht es sauber.
Merkwürdig ...

Satty67 2. Jun 2009 17:37

Re: Henne Ei Problem - eigene EXE löschen
 
Also der andere hier vorgeschlagene Weg würde ich bevorzugen... Also den Uninstaller ins Temp-Verzeichnis kopieren und mit zu löschendem Pfad als Parameter aufrufen. Du hättest wesentlich mehr Kontrolle über den Löschvorgang.

Den Uninstaller im Temp-Verzeichnis dann mit DeleteSelf löschen... wenn das schief geht, liegen die "Reste" am richtigen Ort.

wicht 2. Jun 2009 18:05

Re: Henne Ei Problem - eigene EXE löschen
 
Hmm.. hat das mit dem MoveFileEx() denn irgendwelche Nachteile oder so? Wenn ich das mit der .bat sehe da bekomme ich fast - entschuldigung - das Grauen...

Und was mir noch einfällt, auf keinen Fall den Programm-Ordner einfach so löschen. Man sollte erst vergleichen, ob Dateien im Programmverzeichnis liegen, die der Benutzer nachträglich angelegt hat (nicht von dem Installer installiert). Da habe ich mir mit einer eigenen Deinstall-Routine selbst schon mal stark ins Knie geschossen...

moelski 2. Jun 2009 18:24

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Delphi-Quellcode:
hat das mit dem MoveFileEx() denn irgendwelche Nachteile
Ja, funktioniert nicht unter 98.
Aber 98 brauchen wir (leider) noch.

Zitat:

das Grauen...
Os schon richtig, aber das Thema ist auch leider nicht so trivial :cry:

Zitat:

auf keinen Fall den Programm-Ordner einfach so löschen
Nuja ... Wenn User im Programmordner Dateien ablegen, dann sollte man nur noch das Beileid aussprechen :stupid:
Aber ich gebe dir Recht. So eine Überprüfung könnte noch Sinn machen. Aber nicht bevor ich dieses Problem im Griff habe ..

Satty67 2. Jun 2009 18:31

Re: Henne Ei Problem - eigene EXE löschen
 
Zitat:

Zitat von moelski
Wenn User im Programmordner Dateien ablegen, dann sollte man nur noch das Beileid aussprechen

Du verwendest Delphi7 und siehst ja daran, was früher gängige Praxis war. Aber sehe auch, das aktuelle Uninstaller nichts löschen, was deren Installationsprogramm nicht selber reinkopiert hat.

Man bekommt dann immer die nette Meldung "Es konnte nicht alles gelöscht werden", womit der Ordner gemeint war, der nicht leer geworden ist.

wicht 2. Jun 2009 19:37

Re: Henne Ei Problem - eigene EXE löschen
 
Alles klar, das mit Win98 ist ein Argument. Bin ich froh, damit nichts mehr am Hut haben zu müssen.


Und weil Win98 eh lumpig ist, kann man dann auch den Uninstaller einfach im Temp-Ordner rumliegen lassen..

hoika 2. Jun 2009 20:04

Re: Henne Ei Problem - eigene EXE löschen
 
Hallo,

der Link unten zeigt c++-Quellcode zum Löschen der eigenen Exe.
Inwiefern das auch unter Win98 schon geht, weiss ich nicht.

DeleteMe.cpp

Heiko

Fridolin Walther 3. Jun 2009 02:22

Re: Henne Ei Problem - eigene EXE löschen
 
Zitat:

Zitat von hoika
der Link unten zeigt c++-Quellcode zum Löschen der eigenen Exe.
Inwiefern das auch unter Win98 schon geht, weiss ich nicht.

Das geht nicht mal unter allen Windows NT Varianten ;).

Zitat:

Zitat von moelski
Delphi-Quellcode:
hat das mit dem MoveFileEx() denn irgendwelche Nachteile
Ja, funktioniert nicht unter 98.
Aber 98 brauchen wir (leider) noch.

Das ist nicht dein Ernst, oder? Stimmt zwar, daß MoveFileEx unter Windows 9x nicht den MOVEFILE_DELAY_UNTIL_REBOOT Parameter implementiert, aber es ist ja nicht so als würde es unter Windows 9x keinen Mechanismus dafür geben: Nämlich wininit.ini.

In einigen Zeilen Code hat man dann in Windeseile einen Wrapper geschrieben:
Delphi-Quellcode:
function GetWindowsFolder: string;
const
  MAX_PATH_NTFS = 32767;
var
  CharArray : array[0..MAX_PATH_NTFS] of char;
begin
  FillChar(CharArray, SizeOf(CharArray), 0);
  if GetWindowsDirectory(CharArray, MAX_PATH_NTFS) > 0
    then Result := IncludeTrailingPathDelimiter(CharArray)
    else Result := '';
end;

function IsWindowsNT : boolean; inline;
begin
  Result := GetVersion and $80000000 = 0;
end;

function GetShortFilename(Filename: string) : string;
var
  ShortFilename : array[0..MAX_PATH] of char ;
begin
  if GetShortPathName(PChar(Filename), @ShortFilename, MAX_PATH) > 0
    then Result := ShortFilename
    else Result := Filename;
end;

function DeleteFileOnReboot(Filename : string) : boolean;
begin
  if IsWindowsNT
    then Result := MoveFileEx(PChar(ParamStr(0)), nil, MOVEFILE_DELAY_UNTIL_REBOOT)
    {
     FIXME:
     Prinzipiell können mehrere NUL Werte existieren. WritePrivateProfileString würde dann den jeweils ersten immer wieder überschreiben.
     Entsprechend wäre der 100% saubere Weg einen eigenen kleinen Parser für die wininit.ini zu bauen, der die rename Section sucht
     und die eigenen Einträge hinten dran hängt.
    }
    else Result := WritePrivateProfileString('rename', 'nul', PChar(GetShortFilename(Filename)), PChar(GetWindowsFolder + 'wininit.ini'));
end;
Wenn man dann noch das Verzeichnis entfernen will, bietet sich der bereits oft zitierte Trick mit der temporären Datei an. Sowas könnte dann z.B. so aussehen:
Delphi-Quellcode:
program DeleteMe;

{$APPTYPE CONSOLE}

uses
  SysUtils, windows;

function GetWindowsFolder: string;
const
  MAX_PATH_NTFS = 32767;
var
  CharArray : array[0..MAX_PATH_NTFS] of char;
begin
  FillChar(CharArray, SizeOf(CharArray), 0);
  if GetWindowsDirectory(CharArray, MAX_PATH_NTFS) > 0
    then Result := IncludeTrailingPathDelimiter(CharArray)
    else Result := '';
end;

function GetTempFolder : string;
const
  MAX_PATH_NTFS = 32767;
var
  CharArray : array[0..MAX_PATH_NTFS] of char;
begin
  FillChar(CharArray, SizeOf(CharArray), 0);
  if GetTempPath(MAX_PATH_NTFS, @CharArray) > 0
    then Result := IncludeTrailingPathDelimiter(CharArray)
    else Result := '';
end;

function GetTemporaryFilename : string;
var
  CharArray : array[0..MAX_PATH] of char;
begin
  FillChar(CharArray, SizeOf(CharArray), 0);
  if GetTempFileName(PChar(GetTempFolder), 'Del', 0, @CharArray) <> 0
    then Result := CharArray
    else Result := '';
end;

function GetShortFilename(Filename: string) : string;
var
  ShortFilename : array[0..MAX_PATH] of char ;
begin
  if GetShortPathName(PChar(Filename), @ShortFilename, MAX_PATH) > 0
    then Result := ShortFilename
    else Result := Filename;
end;

function IsWindowsNT : boolean; inline;
begin
  Result := GetVersion and $80000000 = 0;
end;

function DeleteFileOnReboot(Filename : string) : boolean;
begin
  if IsWindowsNT
    then Result := MoveFileEx(PChar(ParamStr(0)), nil, MOVEFILE_DELAY_UNTIL_REBOOT)
    {
     FIXME:
     Prinzipiell können mehrere NUL Werte existieren. WritePrivateProfileString würde dann den jeweils ersten immer wieder überschreiben.
     Entsprechend wäre der 100% saubere Weg einen eigenen kleinen Parser für die wininit.ini zu bauen, der die rename Section sucht
     und die eigenen Einträge hinten dran hängt.
    }
    else Result := WritePrivateProfileString('rename', 'nul', PChar(GetShortFilename(Filename)), PChar(GetWindowsFolder + 'wininit.ini'));
end;

procedure ExecuteFile(Filename, Parameters : string);
var
  StartupInformation  : TStartupInfo;
  ProcessInformation  : TProcessInformation;
begin
  writeln('Temporaere Datei erstellt: ', Filename);
  FillChar(StartupInformation, SizeOf(TStartupInfo), 0);
  FillChar(ProcessInformation, SizeOf(TProcessInformation), 0);
  StartupInformation.cb := SizeOf(TStartupInfo);

  CreateProcess(nil, PChar('"' + Filename + '" ' + Parameters), nil, nil, false,
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInformation,
    ProcessInformation);
end;

procedure CreateAndRunCopyOfMyself();
var
  RandomFilename      : string;
begin
  RandomFileName := GetTemporaryFilename;
  if RandomFilename <> ''
    then
      if CopyFile(PChar(ParamStr(0)), PChar(RandomFilename), false)
        then ExecuteFile(RandomFilename, '"' + ParamStr(0) + '"')
        else DeleteFile(PChar(RandomFilename));
end;

procedure DeleteMyOldSelfAndMe();
begin
  if FileExists(ParamStr(1))
    then
      repeat
        writeln('Versuche alte Datei zu entfernen ...');
        Sleep(1000);
      until DeleteFile(PChar(ParamStr(1)));
  // Prinzipiell könnte man jetzt auch das Verzeichnis entfernen nur so nebenbei ...
  if DeleteFileOnReboot(ParamStr(0))
    then writeln('Alte Datei entfernt und mich selbst fuer Entfernung bei Reboot eingetragen.')
    else writeln('Alte Datei entfernt, aber ich selbst bin noch da: ', ParamStr(0));
end;

begin
  if ExtractFileExt(ParamStr(0)) = '.tmp'
    then DeleteMyOldSelfAndMe()
    else CreateAndRunCopyOfMyself;
  Writeln('Enter um die Anwendung zu beenden');
  Readln;
end.
Die Anwendung kopiert sich selbst in den Temp Ordner, ruft dann seine Kopie auf mit dem Originalnamen als Parameter. Danach versucht die Kopie das Original zu löschen. Sobald das geschehen ist, fügt es sich selbst zum Löschen bei Reboot hinzu. Prinzipiell kann man dann sobald die Original Datei gelöscht ist, auch das Verzeichnis entfernen indem man den Code in DeleteMyOldSelfAndMe an der Kommentarstelle erweitert.

Prinzipiell könnte man auch Code in eine fremde Anwendung injezieren um die eigene Anwendung zu löschen. Das käme komplett ohne Temporäre Dateien oder ähnliches aus. Allerdings ist es je nach System relativ schwer zu implementieren. Davon abgesehen kreischen die ganzen HIPS und Behaviour Blocker immer gleich rum, wenn man Code Injection durchführt. Weiß nicht ob das entsprechend für Dich eine Option wäre.

Achja: Ich behaupte übrigens, daß es keine Installationsaufgabe gibt, die man nicht mit einem der gängigen Installer Tools lösen kann. Entsprechend find ich es sinnbefreit einen womöglich dritt- oder viertklassigen Installer selbst zu bauen, wenns teilweise extrem leistungsfähige Open Source Projekte gibt (InnoSetup, NSIS um nur zwei zu nennen, von komerziellen Lösungen mag ich gar nicht erst anfangen).

Zu guter letzt weise ich darauf hin, daß ich der Übersicht halber nur rudimentäres Fehlerhandling implementiert hab. Bevor man den Code benutzt, sollte man ihn um entsprechendes Fehlerhandling erweitern.

moelski 3. Jun 2009 07:14

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Danke für den Code. Werde ich doch gleich mal testen.

Zitat:

Ich behaupte übrigens, daß es keine Installationsaufgabe gibt, die man nicht mit einem der gängigen Installer Tools lösen kann
Habe ja nie etwas Gegenteiliges behauptet :wink:
Wir hatten zu Beginn Innosetup und danach AKInstallerMSI. Und du hast vollkommen Recht das wir damit alles lösen können.

OT ein
Wir wollten aber einen Installer der genau auf unsere Bedürfnisse zugeschnitten ist. Nämlich:
- Installation / Update über Web
- Installation / Update über Resourcen ZIP
- Installation direkt auf USB Stick (bedarf ein paar extra Schritte)
- sehr einfaches Handling

Ich denke das unser Installer genau das erfüllt :) Und wir haben einen Installer wo wir die Quellcodes von Anfang an kennen und nach unseren Vorstellungen anpassen können. Mag sein das diese Aufgaben mit anderen Installern ebenfalls lösbar sind, aber nun ist er eh bald fertig und wie gesagt er macht genau das was wir brauchen. Nicht mehr und nicht weniger.
OT aus

moelski 3. Jun 2009 08:48

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

So code mal getestet und funzt soweit ganz gut. Aber das Löschen des Verzeichnisses bereitet noch ein Problem.

Wenn ich die Anwendung absolut starte (aus dem Verzeichnis heraus oder per Link), dann wird das Verzeichnis nicht gelöscht.
Starte ich die Anwendung relativ also z.B. "Neuer Ordner\Project1.exe" dann klappt auch das Löschen des Verzeichnisses.

Finde ich etwas merkwürdig, denn erst wird das Verzeichnis geleert und dann versucht ja die zweite Instanz das Verzeichnis zu entfernen. Mir ist nicht ganz klar warum das in die Hose geht. :gruebel:

Satty67 3. Jun 2009 08:57

Re: Henne Ei Problem - eigene EXE löschen
 
Vielleicht vorm Ordner löschen auch noch etwas warten (auch wenn das im Vergleich zur funktionierenden Methode unlogisch wäre) und den Fehler beim Ornder löschen genauer auswerten (beschreiben)... wenn es denn einen gibt.

moelski 3. Jun 2009 09:07

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

"Warten" habe ich auch schon probiert. Bringt aber nichts.
Muss mal sehen ob ich das Problem näher eingrenzen kann.

hoika 3. Jun 2009 09:24

Re: Henne Ei Problem - eigene EXE löschen
 
Hallo,

vielleicht solltest du vor dem Löschen per

SetCurrentDirectory

mal aus deinem Exe-Verzeichnis rausgehen (z.B. ins Temp).


Heiko

moelski 3. Jun 2009 09:31

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Zitat:

SetCurrentDirectory
Treffer - versenkt :-D

Ok so geht es nun. Werde nun mal auf verschiedenen Systemen testen.

hoika 3. Jun 2009 10:30

Re: Henne Ei Problem - eigene EXE löschen
 
Hallo,

ich will einen Keks ;)

Du kannst ja zum Schluss die fertige Lösung posten.


Heiko

moelski 3. Jun 2009 10:33

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

Ja das kann ich gerne machen.
Will aber erst noch ein bisserl Testen.

moelski 4. Jun 2009 07:27

Re: Henne Ei Problem - eigene EXE löschen
 
Moin !

So hier mal die Lösung in komplett...
Ich nutze die DSiWin32 und habe Teile aus dem Orginalcode 0xF30FC7 ersetzt.
-> http://17slon.com/gp/gp/dsiwin32.htm

An dieser Stelle nochmal herzlichen Dank an 0xF30FC7 und hoika für die entsprechenden Infos. :thumb:

Evtl. wäre das ja was für die Codelib?


Delphi-Quellcode:
program DeleteMe;

{$APPTYPE CONSOLE} 

uses
  SysUtils,
  windows,
  DSiWin32 in '..\DSiWin32.pas';

function GetShortFilename(Filename: string) : string;
var
  ShortFilename : array[0..MAX_PATH] of char ;
begin
  if GetShortPathName(PChar(Filename), @ShortFilename, MAX_PATH) > 0 
    then Result := ShortFilename
    else Result := Filename;
end;

function DeleteFileOnReboot(Filename : string) : boolean;
begin
  if DSiIsWinNT then
    Result := MoveFileEx(PChar(ParamStr(0)), nil, MOVEFILE_DELAY_UNTIL_REBOOT)
    { 
     FIXME:
     Prinzipiell können mehrere NUL Werte existieren. WritePrivateProfileString würde dann den jeweils ersten immer wieder überschreiben.
     Entsprechend wäre der 100% saubere Weg einen eigenen kleinen Parser für die wininit.ini zu bauen, der die rename Section sucht
     und die eigenen Einträge hinten dran hängt.
    } 
  else
    Result := WritePrivateProfileString('rename', 'nul', PChar(GetShortFilename(Filename)), PChar(DSiGetWindowsFolder + '\wininit.ini'));
end;

procedure ExecuteFile(Filename, Parameters : string);
var
  StartupInformation  : TStartupInfo;
  ProcessInformation  : TProcessInformation;
begin
  writeln('Temporaere Datei erstellt: ', Filename);
  FillChar(StartupInformation, SizeOf(TStartupInfo), 0);
  FillChar(ProcessInformation, SizeOf(TProcessInformation), 0);
  StartupInformation.cb := SizeOf(TStartupInfo);

  CreateProcess(nil, PChar('"' + Filename + '" ' + Parameters), nil, nil, false,
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInformation,
    ProcessInformation);
end;

procedure CreateAndRunCopyOfMyself();
var
  RandomFilename      : string;
begin
  RandomFileName := DSiGetTempFileName('LV_', DSiGetTempPath);
  WriteLn('RandomFileName : ' + RandomFileName);
  if RandomFilename <> ''
    then
      if CopyFile(PChar(ParamStr(0)), PChar(RandomFilename), false)
        then ExecuteFile(RandomFilename, '"' + ParamStr(0) + '"')
        else DeleteFile(PChar(RandomFilename));
end;

procedure DeleteMyOldSelfAndMe();
begin
  if FileExists(ParamStr(1))
    then
      repeat
        Sleep(1000);
        writeln('Versuche alte Datei zu entfernen ...');
        WriteLn(ParamStr(1));
      until DeleteFile(PChar(ParamStr(1)));
  WriteLn('lösche ... ' + ExtractFilePath(ParamStr(1)));
  DSiRemoveFolder(ExtractFilePath(ParamStr(1)));
  if DeleteFileOnReboot(ParamStr(0))
    then writeln('Alte Datei entfernt und mich selbst fuer Entfernung bei Reboot eingetragen.')
    else writeln('Alte Datei entfernt, aber ich selbst bin noch da: ', ParamStr(0));
end;

begin
  WriteLn('Starte ...');
  WriteLn(ParamStr(0));    WriteLn(ParamStr(1));
  if LowerCase(ExtractFileExt(ParamStr(0))) = '.tmp' then begin
    WriteLn('-> Temp Version gestartet');
    SetCurrentDirectory(PChar(DSiGetTempPath));
    DeleteMyOldSelfAndMe();
  end else begin
    WriteLn('-> Orginal Version gestartet');
    CreateAndRunCopyOfMyself;
  end;

  Writeln('Enter um die Anwendung zu beenden');
  Readln;
end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz