wake-up-neo.com

Externe Ausnahme C0000006

Ich habe ein Programm in Delphi geschrieben, und wenn ich es von einer Festplatte auf einem Schlüssel starte. Irgendwann muss ich die Festplatte vom Schlüssel trennen, während die Anwendung ausgeführt wird. Wenn ich dies auf einem Computer mit mindestens 1 GB RAM mache, ist alles in Ordnung. Wenn ich dies auf einer Maschine mit 512 MB mache, erhalte ich eine externe Ausnahme C0000006. Wenn ich mich nicht irre, liegt dies daran, dass das Betriebssystem versucht, die nächste Codezeile zu lesen, aber die Ressource dafür nicht finden kann (was bedeutet, dass die Anwendung nicht in den RAM geladen wurde), was absurd ist, weil es sich um eine 500-KB-Anwendung handelt.

Wie kann ich das lösen? oder zumindest mit dieser Ausnahme auf eine elegantere Weise umgehen? (Da ich es nicht fangen kann, da es eine externe Ausnahme ist).

Oh, und meine Delphi-Anwendung ist eine Konsolenanwendung unter Windows XP.

20
Luke

Was Sie tun müssen, ist, Fenstern mitzuteilen, dass sie Ihr gesamtes Programm in den Speicher laden sollen, anstatt zuzulassen, dass Seiten geladen werden, wenn dies erforderlich ist. Ich habe dies erfolgreich für Anwendungen gemacht, die von einer CD ausgeführt werden. Ich habe den Code momentan nicht bei mir, aber ich erinnere mich daran, dass ich im Quellcode für das fantastische Open-Source-Installationsprogramm Inno Setup Hinweise gefunden habe.

Edit: Nach ein wenig Recherche können Sie eine Delphi-Compiler-Direktive verwenden, um Windows anzuweisen, die vollständige ausführbare Datei zu laden. Dies funktioniert, wenn Sie über Delphi> 2006 verfügen. Dies hat den Effekt, dass Sie niemals die externe Ausnahme erhalten.

Fügen Sie diese Zeile in Ihre Anwendungsprojektdatei ein:

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

Dies teilt Windows mit, dass die ausführbare Datei von Wechselmedien verwendet wird. Laden Sie die ausführbare Datei in den Arbeitsspeicher (oder die Auslagerungsdatei). Dann müssen Sie sich keine Gedanken darüber machen, wie das Kopieren der Datei zuerst auf den Computer usw.

Edit 2: Ich habe derzeit Zugriff auf Delphi 7 und kann, wie von anderen angemerkt, bestätigen, dass dies auch mit Delphi 7 (und wahrscheinlich Delphi 6) mit folgendem Code funktioniert:

const
  IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

Für Delphi <6 können Sie den Pfad zum Erzwingen der Auslagerung der ausführbaren Datei aufrufen. Es gibt ein Beispiel, wie dies in C++ here getan wird (es sei denn, Sie finden eine Möglichkeit, die PE-Header-Flags nach dem Link zu ändern Zeit, die kompliziert erscheint)

N @

37
Nat

Das ist EXCEPTION_IN_PAGE_ERROR. Dies bedeutet, dass der OS-Loader einige Daten nicht abrufen konnte, die für die Ausführung der Anwendung erforderlich sind, möglicherweise aufgrund eines E/A-Fehlers oder eines anderen Fehlers. Da Sie die Diskette entfernen, ist das sinnvoll.

Möglicherweise durfte der Arbeitssatz (der Satz häufig verwendeter Speicherseiten) für die Anwendung auf 1-GB-Computern so groß werden, dass ein erneuter Ladevorgang auf die Festplatte nicht erforderlich war. Dies war jedoch bei 512-MB-Computern nicht der Fall ?

Ich würde vorschlagen, die ausführbare Datei an einen temporären Ort zu kopieren und von dort aus zu starten, möglicherweise mit verzögertem Löschen. oder verwenden Sie einen anderen Mechanismus, um die Sicherung auf der Festplatte für alle Speicherseiten zu gewährleisten, die bei normaler Verwendung von der Anwendung berührt werden, und diesen Fehler zu vermeiden, wenn Speicherdruck herrscht, wo das Betriebssystem die Arbeitsabläufe der laufenden Prozesse trimmt.

16
Barry Kelly

Wie @Barry würde ich empfehlen, den Laufwerkstyp des Volumes zu überprüfen, von dem aus Ihre ausführbare Datei ausgeführt wird. Wenn es sich um ein entfernbares Laufwerk handelt (und es fehlt ein Befehlszeilenparameter "in temp"), kopieren Sie die ausführbare Datei (und ihre Abhängigkeiten) in den Ordner %TEMP% des Benutzers und starten Sie sie von dort aus mit einem zusätzlichen Befehlszeilenparameter "bereits in temp".

  1. Erstellen Sie jede temporäre Datei mit File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose) (oder einem der FileStream-Konstruktoren, der einen FileOptions-Parameter verwendet), achten Sie jedoch darauf, die zurückgegebene File-Instanz beizubehalten, bis after die zweite Kopie gestartet wird (z ein List<File>).
  2. Kopieren Sie den Inhalt jeder Datei.
  3. Starten Sie die ausführbare Datei aus dem temporären Ordner.
  4. Rufen Sie Close() für jede der oben gespeicherten File-Instanzen auf.
  5. Beenden Sie die ursprüngliche ausführbare Datei.

Auf diese Weise werden die Dateien geschlossen, unabhängig davon, welcher Prozess zuerst abgeschlossen wird, und das Quell-Volume kann früher entfernt werden.

4
devstuff

Die Lösung 

uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}

ist für Delphi seit Version 6 verfügbar.

1
Moje Meno

Diese Ausnahme C0000006 tritt auch häufig auf, wenn Ihre Software von einem Netzlaufwerk ausgeführt wird. Um dieses Problem zu vermeiden, können Sie die Flagge kombinieren 

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

mit der folgenden Flagge:

IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;

{$SetPEFlags $0C00}
0
GHN

Es gibt eine Delphi-Arbeitsversion von RunImageLocally von MSJ , die das Ausführen der ausführbaren Datei/DLL erzwingt. Dadurch können C0000006-Fehler beim Ausführen über ein Netzwerk oder Wechseldatenträger verhindert werden.

Überprüfen Sie es unter https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr

0
phs.bnu