NVIDIAのOptimusとPlayOnline Viewer

ThinkPad X60の熱問題に耐えられなくなり、ThinkPad T420を購入しました。届いたのでFF11をインストールしたのですが、PlayOnline Viewerが起動しない(原因不明のエラーにより「動作を停止しました」状態になる)という不具合に遭いました。まだ根本的には解決していないのですが、対症療法的なものを見つけたので、ここにメモしておきます。

こちらの記事によれば、PlayOnline Viewerが起動しないのはNVIDIAのOptimusに問題があるとのことです(ThinkPad T420固有の問題というわけではないらしい)。何が原因なのかわかりませんが、PlayOnline Viewerを起動するとNVIDIAのドライバ(nvumdshim.dll)でエラーが生じて、そのままハングアップしてしまうようです。このハングアップが厄介で、これまた理由は分からないのですが、シェルを巻き添えにしてしまいます。タスクマネージャすら応答しなくなりプロセスの終了もさせられなくなるので、Ctrl+Alt+Deleteでログオフを選ぶしかありません。

対症療法的な対策として、C:\Windows\SysWOW64\nvumdshim.dllを一時的にリネームするなどして除いておくというものがあります。前記DLLが存在しない状態ならばPlayOnline Viewerを起動することができるようになります(これまたこれまた理由が分かりません)。ただし、そのままではFF11が起動しなくなるので、PlayOnline Viewerが起動した後は元の状態に戻しておかなければなりません。

また、nvumdshim.dllを置き換えるという手段があります。古いドライバのDLLに置き換えることで、不具合を避けることができるとのことです。置き換えると、確かに、PlayOnline Viewerがエラーで停止することはなくなります。ただし、他に影響が生じない保証はありませんし、リンク先のファイル自体が安全である保証もありません(いちおうAvira Antivirusでスキャンしましたが何も検出されませんでした)。くれぐれも自己責任で試してみてください。また、既存のファイルはリネームするなどして保存しておくようにしましょう。何らかの問題が生じても、ファイルを元に戻せば復旧できるものと思われます。こちらの手段をとる場合、次のようなスクリプトを使う必要はありません。

ファイルを置き換えた場合、他のDirectX使用アプリケーションが正常に動作しなくなるおそれがあります。実際、Google EarthのDirectXモードは起動しませんでした(OpenGLモードならば起動できます)。

リネーム作業を毎回手動で行うのも大変なので、自動的に行うようスクリプトを組んでみました。処理系をインストールしなくても済むように、Windows Scripting Hostで書いています(ファイル名runpol.vbs)。なお、このスクリプトは異常系への対処がなされていないので、使用する場合は自己責任でお願いします。


ファイルを置き換える方法でPlayOnline Viewerを起動させるスクリプトは、次の通りです。

事前に、置き換えるファイルをC:\Windows\SysWOW64nvumdshim_pol.dllとして配置しておいてください。スクリプトは、リネームにより、このファイルをnvumdshim.dllと入れ替えてPlayOnline Viewerを起動します。起動後、もとの名前に戻します。理由はよく分かりませんが、このスクリプトでは、後に掲載する方法とは異なり、FF11から正常にシャットダウンを行うことができます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Dim currpath, polpath, temppath
 
Set fs = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
 
currpath = "C:\Windows\SysWOW64\nvumdshim.dll"
polpath = "C:\Windows\SysWOW64\nvumdshim_pol.dll"
temppath = "C:\Windows\SysWOW64\nvumdshim_temp.dll"
 
Dim polexists, tempexists
 
polexists = fs.FileExists(polpath)
tempexists = fs.FileExists(temppath)
 
If tempexists Then
  Set currfile = fs.GetFile(temppath)
  Set polfile = fs.GetFile(currpath)
Else
  If polexists Then
    Set currfile = fs.GetFile(currpath)
    Set polfile = fs.GetFile(polpath)
 
    ' POL起動前にDLLを入れ替える
    currfile.Name = "nvumdshim_temp.dll"
    polfile.Name = "nvumdshim.dll"
  Else
    WScript.Echo "入れ替えるDLLが見つかりません。"
    WScript.Quit
  End If
End If
 
' POLを起動する
shell.CurrentDirectory = "C:\Program Files (x86)\PlayOnline\SquareEnix\PlayOnlineViewer"
shell.Run "pol.exe", 1, true
 
' 入れ替えたDLLを元に戻す
polfile.Name = "nvumdshim_pol.dll"
currfile.Name = "nvumdshim.dll"

なお、このスクリプトをそのまま動かしても、管理者特権がないのでシステム領域にあるファイル名を変更することができず、動作しません。管理者権限でコマンドラインシェル(cmd.exe)を起動したうえで実行しなければなりません。wscript.exeへのショートカットを作っても、システムの一部を構成しているという理由により、管理者権限での実行を設定することができません。

これは、このようなスクリプトを実行ファイル(exeファイル)に変換するフリーソフトを通して実行ファイルに変換し、「管理者権限で実行」というプロパティを設定することで対処することができます。起動時に管理者権限への昇格が求められますが、それはPlayOnline Viewerを起動する場合も同じです。


以下は、nvumdshim.dllをリネームにより取り除くスクリプトです。

この方法には、ひとつ問題があります。FF11終了時にPlayOnline Viewerを通るのですが、ここでハングアップが生じてしまいます。これは変更したファイル名をPlayOnline Viewer起動後元に戻しても発生してしまうので、避けることができません(FF11を「シャットダウン」で終了させても発生します)。このハングアップも前述の通りエクスプローラを巻き込みます。そのため、他のアプリケーションを動かしていると強制終了させなければならない(Windowsからログアウトしなければならない)ことになるので注意が必要です。回避策があるのかどうかも不明です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Dim path, renamed
 
Set fs = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
 
path = "C:\Windows\SysWOW64\nvumdshim.dll"
renamed = 0
If fs.FileExists(path) Then
  Set file = fs.GetFile(path)
  file.Name = "_nvumdshim.dll"
  renamed = 1
End If
 
shell.CurrentDirectory = "C:\Program Files (x86)\PlayOnline\SquareEnix\PlayOnlineViewer"
shell.Run("pol.exe")
 
If renamed = 0 Then
  str = "POLが起動した後にOKを押してください。FF11起動に備えてnvumdshim.dllに戻します。"
Else
  str = "nvumdshim.dllをリネームしました。POLが起動した後にOKを押してください。FF11起動に備えてnvumdshim.dllに戻します。"
End If
 
WScript.Echo str
 
path = "C:\Windows\SysWOW64\_nvumdshim.dll"
renamed = 0
If fs.FileExists(path) Then
  Set file = fs.GetFile(path)
  file.Name = "nvumdshim.dll"
  renamed = 1
End If
 
If renamed = 0 Then
  str = "_nvumdshim.dllが見つかりませんでした。退避したnvumdshim.dllを元に戻しておいてください。"
Else
  str = "ファイル名をnvumdshim.dllに戻しました。"
End If
 
WScript.Echo str

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*


*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">