3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

リモートデスクトップサーバからネットワークドライブ経由でexeを実行するとアプリケーションが落ちる時がある

以下のような環境でアプリケーションがクラッシュすることが有りました。

リモートデスクトップサーバーにて複数ユーザーで同一のexeを実行。
・そのexeは共有フォルダに存在し、UNCではなくネットワークドライブ経由でアクセス。
・環境は共有フォルダ側がWindows Server2016,RDSサーバ側がWindows Server2008 R2。

調査すると、MSサポート:アプリケーションがクラッシュしたり、他のユーザーが Windows Server 2012 と R2 または Windows Server 2008 と R2 でのリモート デスクトップ セッションをログオフした場合に応答しなくなります。という記事を見つけました。

端的に言うと、Windows Server2012以前の仕様(という名のバグ?)で、解決にはWindows Server 2016が必要なようです。

さて、再現方法ですが、以下のようにすると自分の環境では現象が発生しました。

ユーザAログイン 
  ↓      ユーザBログイン
 exe実行        ↓
  │        exe実行
  │         ↓
  ↓        exe終了
 exe終了      
           exe実行
 exe実行        │
  │         ↓
  │        exe終了
  ↓        ログオフ
 exe触るとクラッシュ

現象発生時、リモートデスクトップサーバ側のイベントログには以下のようなエラーが出力されます。

ログの名前:         Application
ソース:           Application Error
日付:            2018/04/18 10:18:54
イベント ID:       1000
タスクのカテゴリ:      (100)
レベル:           エラー
キーワード:         クラシック
ユーザー:          N/A
コンピューター:       xxxx

障害が発生しているアプリケーション名: hoge.exe、バージョン: 1.1.0.000、タイム スタンプ: 0x5ab3237d
障害が発生しているモジュール名: MSVBVM60.DLL、バージョン: 6.0.98.15、タイム スタンプ: 0x4a5bda6c
例外コード: 0xc0000006
障害オフセット: 0x0000b3bd
障害が発生しているプロセス ID: 0x6790
障害が発生しているアプリケーションの開始時刻: 0x01d3d6b31dfed5ab
障害が発生しているアプリケーション パス: Z:\hoge.exe
障害が発生しているモジュール パス: C:\Windows\system32\MSVBVM60.DLL
レポート ID: 7550130b-42a6-11e8-9164-005056a82bed

------------------------------------------------------------
ログの名前:         Application
ソース:           Application Error
日付:            2018/04/18 10:18:54
イベント ID:       1005
タスクのカテゴリ:      (100)
レベル:           エラー
キーワード:         クラシック
ユーザー:          N/A
コンピューター:       xxxx

次のいずれかの理由によりファイル  にアクセスできません:  ネットワーク接続、このファイルの保存先ディスク、またはこのコンピューターにインストールされている記憶域 ドライバーに問題があります。または、ディスクが見つかりません。 このエラーによりプログラム 総合福祉システムメニュー は終了しました。

プログラム: テストプログラム
ファイル: 

エラー値は [追加データ] セクションに一覧表示されます。
ユーザー操作
1. このファイルをもう一度開きます。 この状況は、プログラムを再実行するときに修復される一時的な問題である可能性があります。
2. このファイルにまだアクセスできず、
     ファイルがネットワーク上にある場合は、 ネットワーク管理者がネットワークに問題がないこと、およびサーバーにアクセスできることを検証する必要があります。
    - ファイルが、フロッピー ディスクや CD-ROM などのリムーバブル ディスクにある場合は、ディスクがコンピューターに完全に挿入されていることを確認します。
3. CHKDSK を実行してファイル システムをチェックおよび修復します。CHKDSK を実行するには、[スタート] ボタンをクリックし、[ファイル名を指定して実行] をクリックし、「CMD」と入力して、[OK] をクリックします。コマンド プロンプトで「CHKDSK /F」と入力してから、Enter キーを押します。
4. 問題が解決しない場合は、バックアップ コピーからファイルを復元します。
5. 同じディスク上の他のファイルが開くかどうかを確認します。開かない場合は、そのディスクが壊れている可能性があります。ハード ディスクの場合は、管理者またはコンピューター ハードウェア ベンダーに連絡して サポートを受けます。

追加データ
エラー値: C00000C4
ディスクの種類: 0

イベントID1000に出てくる例外コード: 0xc0000006 はSTATUS_IN_PAGE_ERRORという意味だそうです。メモリ操作に関するエラーですが、exe自体にアクセス出来ない時にも出るようですね。(exeにアクセスできなくなり、exeの内容をメモリに読み込もうとしてエラー)

イベントID1005に出てくるエラー値はNTSTATUSエラーコードであり、NTSTATUSエラーコード一覧によるとC00000C4 は「STATUS_UNEXPECTED_NETWORK_ERROR/予期しないネットワーク エラーが発生しました。」との意味のようです。
ディスクの種類 の意味はちょっと調べても出てこず不明でした。

原因は、MSサポートの記事に書かれてますが、クライアント側となるターミナルサーバーにて、ネットワークドライブ経由でアプリケーションを開くとOSによってファイル制御ブロック(FCB)が作成されます。(FCBはOSがメモリにロードされたプログラムファイルにアクセスするためのハンドル)
FCBは最初のユーザ(2008R2の場合は最後のユーザ)にょって所有されています。
FCBを所有しているユーザーがログオフすると、FCBが削除されます。
これにより、共有していた他のユーザーがアクセスできなくなります。

回避策としては、共有フォルダでなくローカルにexeを配置し実行するようにとのことだそうです。 まぁMSもネットワーク越しのアプリケーション実行は推奨していないようですし。。とはいえ、ちょっとしたアプリケーションならいちいちローカルに持ってくるのは面倒なんですねー。

参考:
MSサポート:アプリケーションがクラッシュしたり、他のユーザーが Windows Server 2012 と R2 または Windows Server 2008 と R2 でのリモート デスクトップ セッションをログオフした場合に応答しなくなります。
Win 2008 Terminal Server Network App Crashing
突然「例外コード: 0xc0000006=STATUS_IN_PAGE_ERROR」で落ちたとき
Application error on Windows Server 2008 64-bit SP2