.NET Windowsサービスに大きな問題があります。非常に異なる構成の複数のサーバー上で動作します。このサービスは一部のサーバーでクラッシュする可能性があるようですが、他のサーバーでは安定しています。不安定性は最近導入されましたが、これまでのところ不明です。私たちはWindows 2003/Windows 2003 R2/Windows 2008を実行しているサーバーを持っています。そのほとんどは完全に更新されています。Windowsメッセージのディスパッチ中に.NET Windowsサービスがクラッシュする
異なるターゲットフレームワークバージョン(2.0/3.5/4.0)に対してサービスを構築しようとしましたが、違いはありません。不安定なサービスを持つマシンは、フレームワークのすべてのバージョンで不安定です。私は.NETフレームワークを修復しようとしましたが、違いはありません。私が見て分かる限り、サービス全体とその依存関係は管理されたコードになっています。
また、コマンドラインバージョンでserver-codeを実行しようとしました。これは安定しているようだ。これを回避策として使用しています。ただし、問題はユーザーアカウントに関連していません。サービスは通常、「ローカルサービス」として実行されます。私はコマンドラインバージョンを実行するために使用するアカウントであるローカル管理者アカウントの下で実行させようとしました。しかし、サービスはまだ不安定です。
これまでのところ、いずれかのサーバーで再現可能な状況を作成できました。 - サーバー上でサービスを開始します。 - 同じサーバー上の新しいRDPセッションでドメインユーザーとしてログオンします。 - 私たちのクライアントソフトウェアを起動します。クライアントソフトウェアは、そのセッションでTCPリモート処理を通じて私たちのサービスにアクセスします。 - クライアントとセッションを閉じます。 - サーバー上のドメインユーザーとの新しいRDPセッションを開きます。 - サービスの即時クラッシュ!
ドメインユーザーが新しいRDPセッションにログオンした時点でサービスがクラッシュすることに注意してください。私たちのクライアントソフトウェアは、その時点でそのセッションで実行されていません。最初のセッションでクライアントを開いてTCPリモート処理サービスにアクセスしないと、2回目のログオン中にサービスがクラッシュすることはありません。ローカル管理者としてセッションを開くと、サービスはクラッシュしません。
クラッシュするサービスにネイティブデバッガ(OllyDbg)を接続できました。アドレス0x4bcdcee9で実行しようとすると、アクセス違反でクラッシュします。そのアドレスは、すべてのサーバーと構成で同じです(イベントログに毎回そのアドレスが記載されています)。私はクラッシュスレッドのスタックを見てきました。スレッドはクラッシュの直前に作成されたようです。まず、Ole32.dllを読み込もうとします。これは、OLE32からいくつかのコードを実行し、その後、私は、これらの関数が呼び出されている参照してください。
- User32.SetTimer
- User32.GetMessageW
- User32.TranslateMessage
- User32.DispatchMessageW
クラッシュDispatchMessageWのどこかにあります。スタック上のDispatchMessageWの* MSG引数を見ることができます。これが渡されるようになっています
- のhWnd = 0x00090082
- メッセージ= 0X0000001E
- のwParam = 0x00000000の
- のlParam = 0x00000000の
私が試したスパイを++。しかし、それはWindowsサービスのhWndを検出していないようです。
サービスはこのメッセージを受け取り、パースしてディスパッチしようとするたびに、マップされていないメモリである0x4bc4cee9を呼び出してクラッシュします。
編集: Hansの示唆によれば、私はシステムを調査しました。私はサービスをデバッグしました。サービス実行可能ファイルに余分なサービスを追加して、ヘルパーサービスを開始し、デバッガをアタッチしてから、実際のサービスを開始することができました。このようにして、サービスのOnStartでもデバッグすることができます。 SetWindowsHookA、SetWindowsHookW、SetWindowsHookExA、SetWindowsHookExWにブレークポイントを設定しましたが、どれもヒットしませんでした!
EDIT 2:私はすべての私のノートをチェックして、私は私のノートにタイプミスがあったので、私は、間違った結論に飛びついたことがわかった:-Sとにかく、クラッシュのアドレスは0x4bc4cee9です。実行中のある時点で、msado15.dllがそこにロードされます。クライアントがサーバーから切断されると、デバッガに2つの管理対象例外があることがわかります。その後、ディスパッチャによって処理され、CoFreeUnusedLibraries()を呼び出すWM_Timerメッセージが表示されます。その結果、msado15.dllがアンロードされます。ディスアセンブラでmsado15.dllを開き、Microsoftからシンボルをロードしました。 DLLは、Microsoft Data Access Components(MDAC)2.8 SP1の一部です。バージョンは2.82.4795.0で、2011年1月にリリースされた最新バージョンであることを示しています.ADOConnectionおよびADORecordsetのAdvise()およびUnadvise()関数があります。 Advise()はInitAsyncEvents()を呼び出し、RegisterClassEx()を呼び出します。 RegisterClassEx()に渡されるWndProcは0x4bc4cee9にあるFireEventOnMainThread()です!私はそこに機能を見ることができます!オブジェクトが破棄されると、Unadvise()およびDestroyAsyncEvents()およびUnregisterClassEx()が呼び出される必要があります。しかし、どういうわけか、それは起こっていません。 DLLは、クラスの登録を解除する前にアンロードされます。その結果、次のイベントでクラッシュします。これは、何とか2つの管理例外に関連している可能性があります。私はさらに調査します。
スタックトレース:http://pastebin.com/dsSjMe4Y
ログイン:http://pastebin.com/qD2MXvHd
私は本当にこの問題では、いくつかの指導をお願い申し上げます。同様に、どのプロセスがこのメッセージを送信している可能性がありますか?サービスがこれを完全に間違って派遣するのはどうでしょうか?これを避ける方法は?
は、私は問題を発見し、 ヒースクリフ
非常に長い質問であり、情報のほとんどはすべて有用です。有益なことは、クラッシュと例外情報の時にコールスタックを持つことです。シンボルが正しくロードされていることを確認してください。 –
WM_TIMECHANGEはブロードキャストされたメッセージです。すべてのトップレベルウィンドウに移動します。あなたが1つを持っていたように聞こえて、ウィンドウプロシージャを持つDLLがうまくウィンドウを閉じることなくアンロードされました。 .NETのSystemEvents btwは、明示的に登録解除する必要がある静的イベントです。 –
@SevaTitovスタックトレースを追加しました。他のすべての情報は私にとって重要です。 – Heathcliff