Delphiでいくつかのプログラムを作成し、ディスクオンキーから実行しているとき。ある時点で、アプリケーションの実行中にディスクオンキーを取り外す必要があります。少なくとも1 GBのRAMが搭載されたコンピューターでこれを行うと、すべてが問題ありません。 512MBのマシンでこれを行うと、外部例外C0000006が発生します。私が誤解していないのは、OSが次のコード行を読み取ろうとしているのに、そのリソースが見つからない(つまり、アプリケーションがRAMにロードされなかった)ためです。
どうすればこれを解決できますか?または、少なくともこの例外をよりエレガントな方法で処理しますか? (それは外部の例外なのでそれをキャッチすることができないので)。
ああ、私のDelphiアプリケーションはWindows XPのコンソールアプリケーションです。
あなたがする必要があるのは、必要なときにロードページを要求するのではなく、プログラム全体をメモリにロードするようにWindowsに指示することです。 CDから実行されているアプリケーションに対して、これを正常に実行しました。私は現在コードを持っていませんが、素晴らしいオープンソースインストールプログラムInno Setupのソースでそれを行う方法のヒントを見つけたことを思い出します。
編集:実際、少し調べた後、Delphiコンパイラディレクティブを使用して、Windowsに実行可能ファイル全体をロードするように指示できます。これは、Delphi> 2006の場合に機能します。これにより、外部例外が発生しないという効果があります。
次の行をアプリケーションプロジェクトファイルに追加します。
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
これは、実行可能ファイルがリムーバブルメディアから使用されることをウィンドウに通知するため、実行可能ファイルをメモリ(またはスワップファイル)にロードします。その後、最初にファイルをマシンにコピーするなどのことを心配する必要はありません。
編集2:現在Delphi 7にアクセスしており、他の人が指摘しているように、これがDelphi 7(およびおそらくDelphi 6)でも機能することを確認できます)次のコードで:
const
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
Delphi <6の場合、実行可能ファイルを強制的にページインするパスをたどることができます。C++で実行する方法の例があります here (PEヘッダーを変更する方法が見つからない限り)リンク時のフラグ。複雑に見えます)
N @
それはEXCEPTION_IN_PAGE_ERROR
。これは、おそらくI/Oエラーまたはその他のエラーが原因で、OSローダーがアプリケーションの実行に必要な一部のデータをページインできなかったことを意味します。ディスクを削除するので、それは理にかなっています。
おそらく、アプリケーションのワーキングセット(頻繁に使用されるメモリページのセット)を1GBマシンで十分に大きくできるため、ディスクを使用してページをリロードする必要はありませんでしたが、512MBマシンではそうではありませんでした。 ?
実行可能ファイルを一時的な場所にコピーして、そこから開始することをお勧めします。削除が遅れる可能性があります。または、他のメカニズムを使用して、通常の使用時にアプリケーションがアクセスするすべてのメモリページのディスク上のバッキングを保証し、OSが実行中のプロセスのワーキングセットをトリミングするメモリ不足の場合にこのエラーを防止します。
@Barryと同様に、実行可能ファイルが実行されているボリュームのドライブタイプを確認することをお勧めします。それがリムーバブルドライブである場合(および「一時的にすでに」コマンドラインパラメーターがない場合)、実行可能ファイル(およびその依存関係のいずれか)をユーザーの_%TEMP%
_フォルダーにコピーし、追加のコマンドを使用してそこから再起動します。 「temped in temp」を示す行パラメータ。
File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose)
(またはFileStream
パラメーターを受け取るFileOptions
コンストラクターの1つ)を使用して各一時ファイルを作成しますが、返されたFile
を必ず確認してくださいインスタンスまでafter 2番目のコピーが起動されます(例:_List<File>
_)。File
インスタンスのそれぞれでClose()
を呼び出します。この方法では、最初に終了するプロセスに関係なくファイルが閉じられ、ソースボリュームをより早く削除できます。
ソリューション
uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
バージョン6以降のDelphiで使用できます。
この例外C0000006は、ソフトウェアがネットワークドライブから実行されている場合にも発生します。その問題を防ぐために、フラグを組み合わせることができます
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
次のフラグで:
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEFlags $0C00}
Delphiの動作バージョン MSJからのRunImageLocally があり、実行可能ファイル/ dllが強制的にページインされます。これにより、ネットワークまたはリムーバブルメディアから実行しているときのC0000006エラーを防ぐことができます...
https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr で確認してください。