2

すべての印刷機能を実行する DLL を作成しました。印刷プレビュー、印刷、および PDF の生成を行うことができます。

現在、この DLL の特定の使用パターンがあり、その後 DLL は適切にアンロードできません。その結果、メイン プログラムを終了すると、メイン プログラムは消えますが終了せず、プ​​ロセスを手動で強制終了する必要があります。

原因は、一部の GDI リソースが適切に「閉じられていない」ことにあると思います (これを言うとき、GDI に関する無知の深さから言います)。GDI リソースを直接処理するのではなく、さまざまな Delphi コンポーネントを使用するときに GDI リソースが使用されます。

このような問題を見つけて修正する方法についてのヒントはありますか? GDIView を使用して、プログラムを終了しようとした後も GID リソースが残っていることを確認しましたが、これらの Windows/カーネル ハンドルを基礎となる Delphi コードに関連付ける方法がわかりません。プログラムの実行中にさまざまな時点で GIDView リストを提供できます。

ありがとう!

ジョン (デルファイ 2007)


私は提案された提案に返信しましたが、誰も私の回答に返信しませんでした。結局、私はあきらめました。問題を回避する方法として、自分のプロセスだけでなく、同じ名前の他のすべてのプロセスも強制終了する自殺ルーチンを作成することになりました。ばかばかしいやり過ぎですが、他に選択肢がないように思えました。どこかで見つけたフリーウェアの ProcessInfo 機能を使用しています。

procedure KillNamedProcesses(pName : String);
// used to clean up programs that hang as a result of DLLs not unloading
   var
      ProcessInfo : TProcessInfo;
      ProcessName : String;
      i : INTEGER;
      currentPID : cardinal;
   BEGIN
   currentPID := GetCurrentProcessID;
   pName := UpperCase(pName);
   ProcessInfo := TProcessInfo.Create(nil);

   // kill all old processes (not our process)
   for i := 0 to ProcessInfo.RunningProcesses.Count - 1 do begin
      ProcessName := ProcessInfo.RunningProcesses[i].ExeFile;
      IF (UpperCase(ProcessName) <> pName) THEN CONTINUE;
      IF (currentPID <> ProcessInfo.RunningProcesses[i].ProcessID) then
         ProcessInfo.RunningProcesses[i].TerminateProcess;
      END;
   // kill the last one (ourselves)
   for i := 0 to ProcessInfo.RunningProcesses.Count - 1 do begin
      ProcessName := ProcessInfo.RunningProcesses[i].ExeFile;
      IF (UpperCase(ProcessName) <> pName) THEN CONTINUE;
      ProcessInfo.RunningProcesses[i].TerminateProcess;
      END;
   ProcessInfo.Free;
   END; // KillNamedProcess
4

1 に答える 1

5

プロセスを閉じるために GDI リソースを返す必要はありません。当然、それらを返却する必要がありますが、それによって終了が妨げられることはありません。DLL のアンロードでデッドロックが発生したようです。また、DLL がアンロードに失敗するため、当然、すべての GDI リソースを解放することはできません。

これをデバッグするには、デッドロックのデバッグが必要になります。これについて一般的なアドバイスをするのはかなり難しいです。残念ながら、あなたは古いバージョンの Delphi を使用しています。最新の Delphi デバッガーは、待機チェーン トラバーサルをサポートし、デッドロックのデバッグをかなり簡単にします。私があなただったら、アプリがデッドロック状態になったときに、事後分析のデバッグを行うと思います。私はすべてのスレッドのスタック トレースを見て、それを使用して、無期限にブロックするものが何であるかを特定します。プログラムがデッドロック状態にある場合、Process Explorer と map2dbg を使用して意味のあるスタック トレースを取得します。

于 2012-04-27T02:56:20.193 に答える