エラー COMException (0x800703FA) 発生に関する原因と対処策について (イベント ID 1530 関連)

こんにちは、SharePoint サポートの森 健吾 (kenmori) です。今回の投降では、以下に記載している COMException (0x800703FA) について、他サイトに記載されているよりも少しだけ深くお話しますので、問題解決にお役立ていただければと思います。

 

出力されるエラー

System.Runtime.InteropServices.COMException (0x800703FA): CLSID {BDEADF26-C265-11D0-BCED-00A0C90AB50F} を含むコンポーネントの COM クラス ファクトリを取得中に、次のエラーが発生しました: 800703fa。

 

1.   発生シナリオと対処策について

影響箇所としては COM の仕組みを使用するサービス アプリケーション全体であり、この現象が発生するとバックエンド サービスの機能が全く使用できなくなります。

実際にお問い合わせを経験しているのはSearch Service Application, Excel Service, PowerPoint Service などがあり、これらのサービスが影響を受けてしまった場合、結果的にクロールや検索、Office Web Apps、Excel Service を使用したブラウザによるファイルを表示することができなくなるため、システムの稼働に影響する状況を招きます。

また、カスタム コードがサービス アプリケーションやそれに依存するインスタンス (例. コンテンツ ソース etc.) を生成する際にも現象発生する場合があります。
急に発生すると慌てることになりますが、対処策はありますので速やかに対処しましょう。

 

対処策

1) gpedit.msc を実行します。
2) 画面左のツリーより "コンピュータの構成" - "管理用テンプレート" - "システム" と展開し、[ユーザー プロファイル] を選択します。
3) "ユーザーのログオフ時に強制的にユーザー レジストリをアンロードしない" を "有効" に設定し、[OK] をクリックします。
4) サーバーを再起動します。

- 補足
   グループ ポリシーにてポリシーを管理している場合は、ドメイン コントローラ上でグループ ポリシー エディターを開き、上述の設定を変更ください。

おそらく、多くのブログ等で上記までの情報を記載している状況です。それでも回避はできますので問題ないかと思いますが、運用環境においては原因や対処策が実際に発生している現象と合致しているかなどの認識を合わせる必要があることを想定しております。

以下に本現象の原因について、開発者ではない管理者の方々が疑問を払しょくできるレベルを目指し少しだけ詳細に記載します。

 

2.   COMException (0x800703FA) の発生原因を理解する

アプリケーションがあらかじめ前処理にて取得し正常に操作を完了できたレジストリ ハンドルを使って、再度同じハンドルを使ってレジストリ キーにアクセスする際に対象のキーそのものが削除されてしまっていることを認識した際に 0x800703FA (ERROR_KEY_DELETED) は一般的に発生するエラーです。

Windows API の観点から補足すると、Windows API を使用してプログラミングを実装する際の一般的な流れは、以下のような流れになります。

1)   Windows が保持するリソースをアクセスするためのハンドルを取得する。
2)   ハンドルを使用して Windows リソースを操作する。

ハンドルという用語を理解するために、文字通り車と車のハンドルを想像してください。Windows プログラミングではハンドルを取得した上であらためて Windows リソースをコントロールするようなコードになります。

この現象は 1) で過去に取得していたレジストリ キーを、2) で操作しようとした際に対象のキーが消えてしまっているという現象です。つまり、ハンドルだけ残されて車が盗まれたような状況です。なぜ消えてしまったと認識しているのでしょうか。これを理解するためには、Windows のユーザー プロファイルを少し理解する必要があります。

 

3.   Windows のユーザー プロファイルについて

Windows ユーザー プロファイルには、一般的にユーザーが端末に最初にログインした際に生成されるユーザーごとのリソースが含まれます。代表的な例として、%systemdrive%\users フォルダ配下に存在する各ユーザーのフォルダ (MyDocuments や Desktopを含む) や、レジストリ (HKEY_CURRENT_USER) があります。

これらのリソースは、ユーザーの対話的なログオンや該当ユーザーのプロセスがプロファイル ロードを要求した際にワークステーションのメモリ上にマッピングされ、使用できる状態になります。
上記の前提をもとに特筆すべきこととして、Windows Server 2008 から、ユーザー プロファイルのロードが抑制され、さらに強制的にアンロードするような動作も追加されました。
これは、かねてから以下のような状況が報告されていたことに起因します。

(1) バックグラウンド サービスを含むプロセス内にてユーザー プロファイルのロードがシステム リソースの使用率を高めること
(2) アカウントのログオフ時に競合が発生することがある (前回のセッションがプロファイルのアンロード先のディスクをロックし、次回のログオンがその情報をディスクから読み込めず、キャッシュから制限付きでロードされてしまうなど)

(1)   についてはあらかじめバックエンドのシステムがプロファイルをロードしないようにすることで対処できます。プロファイルをロードしないような設定は IIS のアプリケーション プールの設定等にも追加されています。
また、運用的にもバックグラウンド サービスが LOCALSERVICE や NETWORKSERVICE などのようなアカウントを使用すれば、これらのアカウントはプロファイルを持たない特殊なユーザーであるため問題を回避できます。ただし、SharePoint のような AD にアクセスするなどの特別な要件がある場合は、ドメイン ユーザーの権限でサービスを動作させる必要があるため、プロファイルを持たないこれらのアカウントをサービスの実行アカウントに指定することが現実的ではありません。そのため、SharePoint は本現象の影響を受けることがやむを得ない条件に該当します。

(2)   については今回の投稿にて記載した通りユーザー プロファイルを適時アンロードすることで対処できます。
このアンロードについては、以下のようなイベントログが出力されたタイミングで実行されます。プロセス内でプロファイルに対する参照がなくなったタイミングで実行されます。ただし、そのタイミングで他プロセスがユーザー
プロファイル リソース内のハンドル (レジストリ ハンドル等) を保持している場合は、その後のアプリケーションの動作に影響を与えてしまう動作となります。

イベント ID : 1530
レベル: 警告,
ソース : Microsoft-Windows-User Profiles Service,
イベント ID : 1530,
タスク カテゴリ : なし,
"レジストリ ファイルは他のアプリケーションまたはサービスで使用されています。ファイルはすぐにアンロードされます。レジストリ ファイルを保持しているアプリケーションまたはサービスはこれ以降正しく機能しない可能性があります  
詳細 - 
4 user registry handles leaked from
\Registry\User\S-1-5-21-574761793-3042057060-3609535109-1106_Classes:Process
2884 (\Device\HarddiskVolume1\Windows\System32\inetsrv\w3wp.exe) has opened key
\REGISTRY\USER\S-1-5-21-574761793-3042057060-3609535109-1106_CLASSESProcess
2884 (\Device\HarddiskVolume1\Windows\System32\inetsrv\w3wp.exe) has opened key
\REGISTRY\USER\S-1-5-21-574761793-3042057060-3609535109-1106_CLASSESProcess
5828 (\Device\HarddiskVolume1\Windows\System32\inetsrv\w3wp.exe) has opened key
\REGISTRY\USER\S-1-5-21-574761793-3042057060-3609535109-1106_CLASSESProcess
5828 (\Device\HarddiskVolume1\Windows\System32\inetsrv\w3wp.exe) has opened key
\REGISTRY\USER\S-1-5-21-574761793-3042057060-3609535109-1106_CLASSES"

上述の回避策 "ユーザーのログオフ時に強制的にユーザー レジストリをアンロードしない" を “有効” にした場合は、強制的にアンロードしない代わりに以下のようなイベントログが出力されるよう変更になります。

イベント ID : 1517
レベル : 情報,
ソース : Microsoft-Windows-User Profiles Service,
イベント ID : 1517,
タスク カテゴリ : なし,
"ログオフ時にアプリケーションまたはサービスがレジストリをまだ使用している間に、Windows はユーザー S-1-5-21-574761793-3042057060-3609535109-1106 のレジストリを保存しました。ユーザーのレジストリによって使用されたメモリは解放されていません。レジストリは使用されなくなったときにアンロードされます。ユーザー アカウントとしてサービスを実行していることが原因と考えられます。 LocalService または NetworkService アカウントでサービスを構成してみてください。

イベント ID : 1512
レベル : 情報,
ソース : Microsoft-Windows-User Profiles Service,
タスク カテゴリ : なし,
"レジストリ ファイルをアンロードできません。レジストリに使用されたメモリが解放されていません。ユーザー アカウントとしてサービスが実行されていることが原因と考えられます。LocalService または NetworkService アカウントでサービスを実行してみてください。
詳細 - このメディアは書き込み禁止になっています。

この設定を、SharePoint サーバー端末に対して実施することによるリスクは極めて低く、これまでに問題は報告されておりません。
ただし、万が一繰り返しログオン時にキャッシュから制限付きでプロファイルがロードされてしまうような事象が SharePoint サーバー端末で頻発する場合には、システムでプロファイルをロックしてしまう処理が存在する等異なる問題が発生している可能性がありますので別途対処が必要となります。

 

タイトル : イベント ID: 1530 Windows Vista または新しいコンピューター上のアプリケーション ログに記録されることがあります。
アドレス : https://support.microsoft.com/kb/947238

4.   COM + コンストラクタについて

最後にレジストリとサービスの関係について少しだけ説明します。SharePoint の一部のサービス アプリケーションは COM を使用したインスタンスの生成を使用しているようです。COM クラス ファクトリを使用する場合、レジストリの HKEY_CLASSES_ROOT (HKCR) 配下のエントリを読み込んで該当のCOM サーバー (例. mssearch.exe など) に接続する動作となります。

HKEY_CLASSES_ROOT について

このキー配下の情報は、実は HKEY_CURRENT_USER (HKCU) と HKEY_LOCAL_MACHINE (HKLM) 配下の情報がマージされる形で表示されています。この HKEY_CLASSES_ROOT 配下のキーにアクセスすると、プロファイルがロードされている場合は優先的に HKEY_CURRENT_USER\Software\Classes 配下のキーにアクセスし、プロファイルがアンロードされているときには HKEY_LOCAL_MACHINE\Software\Classes 配下のキーにアクセスする動作となります。

タイトル : HKEY_CLASSES_ROOT Key
アドレス : https://msdn.microsoft.com/en-us/library/ms724475(VS.85).aspx

例えば、プロファイルがロードされていた状態でw3wp.exe 内で HKCU キー配下のレジストリ キーのハンドルを保持していた場合、OWSTIMER.EXE の再起動のタイミングなどで該当ユーザーのプロファイルの実態がアンロードされ、該当ユーザーのレジストリ HKCU キー配下の情報などがディスクに保存されてメモリ マッピングから削除される状態を想定します。

この場合、w3wp.exe 内で保持しているハンドルを持って再度サービス アプリケーションを起動するための処理を行った場合、HKLM 配下にキーが存在したとしても HKCU 配下のキーが削除されていると判断されエラーが発生する動作となります。

これは、HKCR レジストリ キーを指定して取得する際に、その時はプロファイルが正常にロードされていたことから、HKCU キーにアクセスしてレジストリ情報を取得するようにハンドルが作られているからです。

 

5.   まとめ

イベント ID 1530 が発生している場合、実影響が出ていないとしてもポリシーを変更して、現象発生を防ぐ措置を実施しておくことが得策と考えます。
是非とも上述の情報を運用においてお役立ていただけますと幸いです。