none
「最適解像度」に戻されたくない…! RRS feed

  • 質問

  • 画面解像度をXGA固定で使用するアプリケーションを作っております。

    というと誤解を招くかもしれませんが、アプリケーションの機能は解像度の固定それ自体です。プロジェクター用なのです。

     

    パソコンの画面解像度がXGAでないものを使っている場合、画面が一度暗転・ロック※すると、画面表示が1600*900など、パソコン側のネイティブな解像度に戻ってしまい、現在使用しているプロジェクターでは、出力ができなくなってしまうため、このアプリケーションが必要なのです。

    ※ロック状態になること/放置してスリープされ、ロック状態に至ること/UACのダイアログで暗転、のいずれの場合でも同様のことが起こります。

     

    現在の状況はお粗末というか、応急処置レベルのもので、ディスプレイの解像度が何らかの原因で変わった場合、それを検知してから元に戻すことしかできておりません。2回解像度変更が変わるので、恥ずかしながら、遅くて目障りです。

     

    そこで以下の質問をさせていただきたく思いました。

    ・画面解像度の変更を(自作アプリ以外に)許可しないことはできるのでしょうか。

    ・正直どのアプリケーションがロック時等に画面解像度を戻しているかわかりません。

     画面解像度がどのプロセスから変更されたかのログを取れないのでしょうか。

    ・もし、ロック時等に解像度を変えているのは標準ディスプレイドライバやシステムである

     可能性が高い、ということであれば、レジストリキーの変更などでそれを止められないでしょうか。

     

    皆様ご多忙かと存じますが、ご教授いただければ幸いです。



    • 編集済み Maghmag 2012年10月13日 13:07
    2012年10月13日 3:55

回答

  • その後、ちょっと分かったことがありましたので、追記しておきます。

    Win 7 から CCD (Connecting and Configuring Displays) という API セットが追加されているようで、Win8 ではこっちの API のみを使ってディスプレイ解像度の変更処理が行われているようです。

    ----------------------------------------------------------
    Connecting and Configuring Displays
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff539590(v=vs.85).aspx

    CCD Summaries and Scenarios
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff539372(v=vs.85).aspx

    Connecting and Configuring Displays Functions
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff539596(v=vs.85).aspx
    ----------------------------------------------------------

    コントロール パネルからの "画面の解像度" で解像度変更した際に、Video Driver に渡される I/O Control の挙動を、Win7 と Win8 でそれぞれトレースしてみたところ、Win7 では SetDisplayConfig() でリクエストを発行したあとに ChangeDisplaySettingsW() / ChangeDisplaySettingsExW() もコールし、同じ I/O Control Code を2度処理させているのに対し、Win8 では SetDisplayConfig() API だけのリクエストとなっているようでした。
    もしかしたら Maghmag さんの問題は、この挙動の違いに起因しているのかも。。。。と思います。

    Maghmag さんの作成されたアプリでは、解像度の固定を ChangeDisplaySettings() / ChangeDisplaySettingsEx() API で実現されていると推測しておりますが、CCD API は使っていないのでは?
    もしそうだとしたら、Win8 の場合に限り、SetDisplayConfig() も発行するように処理を追加すれば、もしかしたら問題現象を改善できるかも。

    • 回答の候補に設定 佐伯玲 2012年10月25日 4:19
    • 回答としてマーク Maghmag 2012年10月30日 10:26
    2012年10月23日 8:24

すべての返信

  • 誰もコメントしないようなので、とりあえず。。。。

    > ・画面解像度の変更を(自作アプリ以外に)許可しないことはできるのでしょうか。
    不可能ではないと思いますけど、とっても面倒だと思います。
    とりあえず思いつくのは API Hook ですが、他にも方法はあるかもしれません。

    > ・正直どのアプリケーションがロック時等に画面解像度を戻しているかわかりません。
    >   画面解像度がどのプロセスから変更されたかのログを取れないのでしょうか。
    実際に調査したわけではないので、単なる推測ですが。。。
    explorer シェルか winlogon サービス辺りの可能性が高いのでは。。。と思います。
    (XP と Vista/7 で挙動が異なるのであれば、winlogon プロセスの可能性の方が高いかも。)
    どのような目的でログを採取されたいのかは存じませんが、調査目的であるならば、WinDBG をカーネル デバッグ モードで接続して、以下の API にブレークポイントをセットしておけば、特定できるかもしれません。

    user32!ChangeDisplaySettingsA
    user32!ChangeDisplaySettingsW
    user32!ChangeDisplaySettingsExA
    user32!ChangeDisplaySettingsExW

    試しに、Hyper-V の Win7 x86 ターゲット環境に対して上記 API エントリにブレークポイントをセットして、"画面の解像度" にて解像度を変更してみたところ、explorer プロセスから user32!ChangeDisplaySettingsExW がコールされていました。
    ただ、PC をロックしても上記 API 群はコールされてきませんでした。(解像度が変わる現象も確認できませんでした。)


    > ・もし、ロック時等に解像度を変えているのは標準ディスプレイドライバやシステムである
    >   可能性が高い、ということであれば、レジストリキーの変更などでそれを止められないでしょうか。
    US のフォーラムに下記投稿がありました。(試していませんが。。。)

    ---------------------
    Windows 7 changes screen resolution on boot-up from what I had saved
    http://answers.microsoft.com/en-us/windows/forum/windows_7-hardware/windows-7-changes-screen-resolution-on-boot-up/13c17468-0d70-4827-a559-dca0fa558a69
    ---------------------

    ただ上記スレッドでの内容は、レジストリ設定で直接解像度の変更が可能であることを示すだけで、その方法がホントに適切であるか。。。という話とは別問題であると思います。

    以上、参考になりましたら幸いに存じます。

    2012年10月17日 11:02
  • 折角ご回答いただいていたのに返信が遅れてしまいすみません。

    まず、レジストリキーは同じものがありませんでした。しかし、メインディスプレイを指していると思われるレジストリ部分の中に、Attach.RelativeX、Yがあり、XGAと異なる数値でしたので、変更してみました。しかし効果はありませんでした。

    実のところ、この症状はXPからWindows7までのどれでも体験したことがない現象なのです。8になって初めて現れました。WinlogonなのかExplorerなのかはよくわかりません…ということで、人生で初めてのWinDBGでした。

    しかし、シンボルファイルの読み込みまではできたものの、ローカルデバッグは、Operation not supported by current debuggee error in 'bp user32!ChangeDisplaySettingsA'という空しいエラーのためにまだ行えておりません。何から何まで申し訳ないのですが、よい方法があればご教授いただけると幸いです。

    非常に無知で申し訳ないのですが、APIHookはExplorerシェルなどからのコールも拾えるのでしょうか。キーボードしか拾ったことがないので、考えたことがありませんでした…

    2012年10月20日 15:19
  • ご質問されている現象は Win8 だけだったんですね。。。てっきり、Win7 で起きているのだと勘違いしておりました。

    > まず、レジストリキーは同じものがありませんでした。
    レジストリの変更で試すとしたら、"DefaultSettings.XResolution" や "DefaultSettings.YResolution" も明示的に指定する必要があるのかもしれませんが、このレジストリ値は Win7 までの情報しかないので、Win8 でどうなるのかは正直分かりません。
    (話を混乱させて申し訳ありませんでした。)


    > しかし、シンボルファイルの読み込みまではできたものの、ローカルデバッグは、
    > Operation not supported by current debuggee error in 'bp user32!ChangeDisplaySettingsA'と
    > いう空しいエラーのためにまだ行えておりません。
    もしかして、ユーザ モード デバッグを実施されているのでは?
    先の返信にも記載しましたが、カーネル モード デバッグでないと、ディスプレイの解像度変更を行っているプロセスの特定は難しいと思います。
    (ユーザ モード デバッグでは、あらかじめ指定した任意のプロセスのみがデバッグ対象となるので、それ以外のプロセスから解像度変更のリクエストが発行されている場合、ユーザ モード デバッグは意味を持ちません。)
    試しに Win8 x86 環境で、Explorer プロセス内の先に示した API にブレークポイントをセットし、コントロール パネルから "画面の解像度" を変更してみましたが、それら API にはブレークインしてきませんでした。(手順は前回の返信のときに Win7 で試したものと同じです。)
    なので、Win8 での解像度変更は、先に示した API 以外の方法で実現しているのかも。。。
    Win8 で提供されている user32.dll の中を調べたら、以下の2つのルーチンが新たに追加されているようでした。

    ☆ user32!ChangeDispSettingsNotificationA
    ☆ user32!ChangeDispSettingsNotificationW

    もしかしたら、そこらへんも関係しているのかもしれませんが、Win8 でこれら API がどのようなタイミングでコールされてくるのかは、真剣にデバッグしないとなんとも言えません。
    お役に立てず申し訳ありません。

    > APIHookはExplorerシェルなどからのコールも拾えるのでしょうか。
    ちゃんと実装すれば出来るはずです。
    ただし、先の返信でも示したように、いろいろと面倒だと思います。
    実際、セキュリティ ソフトをインストールした状態での explorer プロセスの状態を見ると、ユーザ モード空間にその 3rd ベンダ製のモジュールが多数ロードされているのが確認できますし、適当なタイミングでブレークインさせると、それら 3rd ベンダ製モジュールが提供するルーチンが介在したコール スタックも見えますので、出来ないことは無いと思っています。
    Google や Being 等で、"Windows API Hook" などのキーワードで検索すればいろいろと情報が見つかると思いますので、そちらの情報を参考にされると良いと思います。
    ただ、Metro 対応のプロセスで出来るのかは確認していません。(もしかしたら、別途 Win7 等とは異なる対応が必要になるのかも。。。)

    参考になりそうもない情報ばかりで、申し訳ありません。。。。


    • 編集済み お馬鹿 2012年10月22日 11:03 誤字修正
    2012年10月22日 10:41
  • その後、ちょっと分かったことがありましたので、追記しておきます。

    Win 7 から CCD (Connecting and Configuring Displays) という API セットが追加されているようで、Win8 ではこっちの API のみを使ってディスプレイ解像度の変更処理が行われているようです。

    ----------------------------------------------------------
    Connecting and Configuring Displays
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff539590(v=vs.85).aspx

    CCD Summaries and Scenarios
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff539372(v=vs.85).aspx

    Connecting and Configuring Displays Functions
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff539596(v=vs.85).aspx
    ----------------------------------------------------------

    コントロール パネルからの "画面の解像度" で解像度変更した際に、Video Driver に渡される I/O Control の挙動を、Win7 と Win8 でそれぞれトレースしてみたところ、Win7 では SetDisplayConfig() でリクエストを発行したあとに ChangeDisplaySettingsW() / ChangeDisplaySettingsExW() もコールし、同じ I/O Control Code を2度処理させているのに対し、Win8 では SetDisplayConfig() API だけのリクエストとなっているようでした。
    もしかしたら Maghmag さんの問題は、この挙動の違いに起因しているのかも。。。。と思います。

    Maghmag さんの作成されたアプリでは、解像度の固定を ChangeDisplaySettings() / ChangeDisplaySettingsEx() API で実現されていると推測しておりますが、CCD API は使っていないのでは?
    もしそうだとしたら、Win8 の場合に限り、SetDisplayConfig() も発行するように処理を追加すれば、もしかしたら問題現象を改善できるかも。

    • 回答の候補に設定 佐伯玲 2012年10月25日 4:19
    • 回答としてマーク Maghmag 2012年10月30日 10:26
    2012年10月23日 8:24
  • Win8であると明記しておらず、わかりにくくてすいませんでした。
    DefaultSettings.XResolution,YResolutionは存在しますが、またまた違う場所です。
    HKLMのなかにいっぱいあります。
    Attach.Relativeとセットで置かれている感じで、ここら辺はご教授いただいたリンク先と
    変わりません。
    しかし、書き換えてもやはり解像度固定はできませんでした。
    固定できないというのはちょっと語弊があるかもしれませんん。
    コンパネから画面の解像度を変更しようとするとき、XGA以外選べないようにはなっているんです。
    しかし、Win32叩く系のソフトではちゃんと変えられますし、勿論今回問題となっている、システム?による変更は容赦ありません。

    WinDbgはおかげさまで思うように動きましたが、結局手がかりはありませんでした。
    UIに絡んでそうなDLLにいろいろブレークポイント作ってみたりもしましたが、
    だめなようです…
    8特有の、なにか解像度がらみの事情があるのかもしれませんね。

    とりあえず時間はあるので、APIHookを頑張ってみようと思います。
    沢山のアドバイスありがとうございました。

    2012年10月23日 13:25
  • ななな、なんですってー

    そういうところを調べるべきだったのですね。Windows7からのAPIというとLocationAndSensorしか知りませんでした…勉強不足でした。わざわざ検証までしていただき、ありがとうございます。

    確かに私のアプリではCCDAPIを利用しておりません。ご指摘の通りChangeDisplaySettings/Exを利用しております。

    該当マシンはBIOSレベルのセキュリティを施してもらっているののアップデートと、ついでに諸々検査をしていただけるとかで、明朝から旅立ってしまうのですけれど、今晩実装できたら今晩、できなかったら来週試してみようと思います。とても助かります。ありがとうございます。

    2012年10月23日 13:36
  • ありがとうございましたI

    ご教授されたとおりで、戻されないようになりましたので、

    マークさせていただきます。

    2012年10月30日 10:26