2009-08-23 10 views
17

Napisałem jakiś program w Delphi i kiedy uruchamiam go z dysku na kluczu. W pewnym momencie wymagane jest odłączenie dysku na klucz podczas działania aplikacji. Jeśli zrobię to na komputerze z co najmniej 1 gb pamięci RAM, wszystko jest w porządku. Kiedy robię to na maszynie z 512 MB, otrzymuję zewnętrzny wyjątek C0000006. Jeśli się nie mylę, to dlatego, że system operacyjny próbuje odczytać kolejną linię kodu, ale nie może znaleźć dla niej zasobu (co oznacza, że ​​aplikacja nie została załadowana do ramka), co jest absurdem, ponieważ jest to aplikacja o wielkości 500kb.Wyjątek zewnętrzny C0000006

Jak mogę to rozwiązać? lub przynajmniej obsłużyć ten wyjątek w bardziej elegancki sposób? (Ponieważ nie mogę go złapać, ponieważ jest to wyjątek zewnętrzny).

Aha, a moja aplikacja Delphi to aplikacja konsolowa pod Windows XP.

+3

0xC0000006 i inne wyjątki są wymienione tutaj: http://www.support.tabs3.com/main/R10309.htm –

Odpowiedz

14

To jest . Oznacza to, że program ładujący system operacyjny nie mógł wyświetlić niektórych danych wymaganych do uruchomienia aplikacji, prawdopodobnie z powodu błędu we/wy lub innego błędu. Ponieważ usuwasz dysk, miałoby to sens.

Być może zestaw roboczy (zbiór często używanych stron pamięci) w celu stosowania pozwolono rosną wystarczająco duże na maszynach 1GB taki sposób, że odwołanie się do dysku, aby przeładować strony nie było konieczne, ale to nie było sprawa na 512MB maszynach?

Proponuję spróbować skopiować plik wykonywalny do tymczasowej lokalizacji i rozpocząć ją stamtąd, prawdopodobnie z opóźnionym usunięciem; lub użyć innego mechanizmu, aby zagwarantować wsparcie na dysku dla wszystkich stron pamięci dotykane przez aplikację w trakcie normalnego użytkowania i uniknąć tego błędu w przypadku ciśnienia pamięci, gdzie system operacyjny będzie przyciąć zestaw roboczy uruchomionych procesów.

+1

Gdzie to sprawdziłeś, aby dowiedzieć się, jaki to jest błąd? –

+4

Kody EXCEPTION_ w winbase.h; na ogół są synonimami odpowiednich kodów NTSTATUS z winnt.h. –

33

Co trzeba zrobić, to powiedzieć okien załadować cały program do pamięci, niż pozostawienie go do żądania strony ładują się, gdy musi. Zrobiłem to z powodzeniem dla aplikacji uruchamianych z dysku CD. W tej chwili nie mam kodu, ale pamiętam, że znalazłem wskazówki, jak to zrobić w źródle dla fantastycznego programu instalacyjnego Open Source Inno Setup.

Edit: Faktycznie, po wykonaniu trochę badań, można użyć dyrektywy kompilatora Delphi powiedzieć okien załadować cały plik wykonywalny. Działa to, jeśli masz Delphi> 2006. To spowoduje, że nigdy nie otrzymasz wyjątku zewnętrznego.

Umieść ten wiersz w pliku projektu aplikacji:

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP} 

Mówi okna wykonywalny będzie używany z nośników wymiennych, więc załadować plik wykonywalny do pamięci (lub pliku wymiany). Wtedy nie musisz się martwić o takie rzeczy, jak kopiowanie pliku do urządzenia w pierwszej kolejności, itp.

Dla Delphi < 2006, możesz przejść ścieżką wymuszania wczytywania pliku wykonywalnego. Istnieje przykład jak to zrobić w C++ here (chyba znaleźć sposób na zmianę flagi nagłówka PE po raz łącza, który wydaje się być skomplikowane)

N @

+0

Cool hack. Dzięki za czystą końcówkę. –

+0

Przenieśmy się przez tę odpowiedź, wyszukując w Google dokładnie ten problem. Twoje zdrowie! – HMcG

+0

Gdzie w pliku projektu powinno to być? –

4

Ci się @Barry, polecam sprawdzenie rodzaj napędu woluminu, z którego uruchamiany jest twój plik wykonywalny; jeśli jest odpinany dysk (i brakuje „już w temp” parametr wiersza poleceń) skopiowania pliku wykonywalnego (i każdy z jego zależnościami) do folderu użytkownika %TEMP% a następnie ponownie uruchom go stamtąd z dodatkowym parametrem wiersza poleceń do wskazania "już w temp.".

  1. Tworzenie każdy plik tymczasowy przy użyciu File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose) (lub jedną z FileStream konstruktorów, które przyjmuje parametr FileOptions), ale upewnij się, aby zawiesić na zwróconej File przykład aż po druga kopia jest uruchomiona (np a List<File>).
  2. Skopiuj zawartość każdego pliku.
  3. Uruchom plik wykonywalny z folderu tymczasowego.
  4. Zadzwoń pod numer Close() dla każdej z instancji File zapisanych powyżej.
  5. Zamknij oryginalny plik wykonywalny.

W ten sposób pliki zostaną zamknięte bez względu na to, który proces zostanie zakończony jako pierwszy, a wolumin źródłowy może zostać usunięty wcześniej.

0

Ten wyjątek C0000006 występuje często również wtedy, gdy oprogramowanie jest uruchamiane z dysku sieciowego. Aby uniknąć tego problemu, można połączyć flagę

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP} 

z następującym flagi:

IMAGE_FILE_NET_RUN_FROM_SWAP = $0800; 

{$SetPEFlags $0C00} 
1

Rozwiązanie

uses Windows; 
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP} 

jest dostępna dla Delphi od wersji 6.