8

メイン アプリケーション exe がアップデータ exe を起動し、コマンド ラインで自分自身にハンドルを渡すセルフ アップグレード プロセスを実装しています。次に、アプリケーション exe は ExitProcess を呼び出して終了し、アップデーターは渡されたハンドルで WaitForSingleObject を呼び出して、アプリケーション exe が終了するのを待ちます。

WaitForSingleObject は待機します。アプリケーションが ExitProcess を呼び出すまで、アップデーターは停止します。

ただし、アップデーターが新しいバージョンでアプリケーション dll を上書きしようとすると、ファイルがロックされたエラーが発生することがあります。これは、アップデーターの現在のバージョンが回復不能なエラーとして処理し、終了します。この「問題」を回避するには、任意の sleep(100) を含めるだけで十分なようですが、そのようなコードは本当に嫌いです。本当に嫌い。

dll ファイルをロックするのに十分なほどメイン アプリケーションがまだ生きている間に、プロセス ハンドルにシグナルを送ることができるというのは、私には非常に奇妙に思えます。

4

6 に答える 6

2

別の回答が指摘しているように、プロセスが実行を停止するとプロセス ハンドルが通知され、オペレーティング システムが DLL を解放するのに少し時間がかかる場合があります。

Sleep(100) に依存することは悪い考えです。次のようなループで DLL の上書きをラップする必要があります。

BOOL UpdateDll(LPCTSTR dll_name, WHATEVER whatever) {
  int tries = 150;
  while (tries--) {
    if (TryUpdateDll(dll_name, whatever))
      return TRUE;
    Sleep(200);
  }
  return FALSE;
}

これにより、DLL を 30 秒間アンロードしようとし続け、その後あきらめます。システムの負荷が高い場合でも 30 秒で十分ですが、アップデーターが永久にハングすることはありません。(UpdateDll が FALSE を返す場合は、問題のある DLL の名前を示す意味のあるエラー メッセージをユーザーに提示してください。)

COM をいじっている場合は、終了する前に CoFreeUnusedLibraries を呼び出すことも役立つ場合があります。( http://msdn.microsoft.com/en-us/library/ms679712.aspx )率直に言って、プロセスが終了した後でも COM が DLL を保持するかどうかはわかりませんが、安全を確保することをお勧めします。

要するに、Win32 API には奇妙な点がたくさんあるということです。受け入れ可能な解決策を見つけることができる限り、すべてのケースに対処する必要はありません。明らかに Sleep(100) が壊れる可能性がありますが、30 秒のポーリング ループは許容できるようです。

于 2009-03-10T01:24:03.777 に答える
0

使用しているDLLのいずれかがスレッドを使用している場合、それらを明示的にアンロードしないと、十分な速度で終了(または結合)されない可能性があります。もちろん、LoadLibraryを使用して明示的にロードした場合に発生します。

こちらをご覧ください:http: //msdn.microsoft.com/en-us/library/ms682596 (VS.85).aspx

具体的にはこの行:

...プロセスが終了するか、FreeLibrary関数を呼び出し、参照カウントがゼロになると、DLLがアンロードされます。TerminateProcessまたはTerminateThread関数の結果としてプロセスが終了した場合、システムはDLLエントリポイント関数を呼び出しません。

于 2009-03-09T07:45:10.827 に答える
0

その時点で、DLL が他のプロセスによってロックされている可能性があります。これをテストする 1 つの方法は、これが発生したときに DLL に保持されているもののレポートを生成することです。

于 2009-01-28T07:35:23.243 に答える
0

可能な修正...使用中のdllを置き換えることはできませんが、名前を変更することはできます。したがって、置き換える必要がある dll があるが、何らかの理由で使用されている場合は、その名前を .delete などに変更します。更新を行ってから、メイン プログラムで .delete ファイルを検索し、起動時にそれらを削除します。

-ドン

于 2009-03-09T20:04:38.240 に答える
0

約 6 か月前に、ウイルス対策ソフトウェアでこれらの発疹が見られました。AV なしで試してみてください。少なくとも、AV が最新であることを確認してください。

于 2009-03-06T02:47:05.983 に答える