スキップしてメイン コンテンツへ

 none
VistaでSystemParametersInfoの結果が即時有効とならない RRS feed

  • 質問

  • C#にてスクリーンセーバーの設定を書き換えて即時有効としたいので、以下のようなプログラムを書きました。
    (スクリーンセーバーのインストーラを作成しています。)
    下記アプリを実行すると、XP環境では実行後にしばらく待つとスクリーンセーバーが起動するのですが、
    Vista環境では実行されません。(XP、Vistaともに同じスクリーンセーバーの設定から実行しています)

    ※コントロールパネルからスクリーンセーバーの設定を見ると、きちんと設定変更はされています。
     その状態からスクリーンセーバー起動までの待ち時間のみを変更して適用すると、スクリーンセーバー
     は起動されます。

    Vista環境では、特別な手法が必要なのでしょうか。ご存知の方おられましたら、お教えいただけますでしょうか。

            [DllImport("user32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, IntPtr pvParam, SPIF fWinIni);

            [Description("SPI_(System-wide parameter - Used in SystemParametersInfo function )")]
            public enum SPI : uint
            {
                SPI_SETSCREENSAVEACTIVE = 0x0011
            }

            public enum SPIF
            {
                None = 0x00,
                /// <summary>Writes the new system-wide parameter setting to the user profile.</summary>
                SPIF_UPDATEINIFILE = 0x01,
                /// <summary>Broadcasts the WM_SETTINGCHANGE message after updating the user profile.</summary>
                SPIF_SENDCHANGE = 0x02,
                /// <summary>Same as SPIF_SENDCHANGE.</summary>
                SPIF_SENDWININICHANGE = 0x02
            }

            public override void Commit(System.Collections.IDictionary savedState)
            {
                base.Commit(savedState);

                RegistryKey rgk = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
                rgk.SetValue("SCRNSAVE.EXE", Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\testscr.scr");
                rgk.Close();

                SystemParametersInfo(SPI.SPI_SETSCREENSAVEACTIVE, 1, IntPtr.Zero, SPIF.SPIF_UPDATEINIFILE | SPIF.SPIF_SENDCHANGE);
            }

    2009年5月10日 13:35

回答

すべての返信

  • その方法はスクリーンセーバーの変更方法として正式なものではないはずです。そう動くならそうなのでしょう。
    ところで、あなたの作成したアプリケーションに対して、利用者が「レジストリを書き換えたが即時反映されない/うまく動かない」と言ってきたらどう思いますか? ちゃんと設定ダイアログから操作してください、とか思いませんか?
    2009年5月10日 22:24
  • 返信ありがとうございます。

    スクリーンセーバーのインストーラを作成する上で、インストールしたスクリーンセーバーを即時有効としたいのです。
    user32.dll の SystemParametersInfo 関数で第4引数にSPIF_SENDCHANGEを指定してスクリーンセーバーを設定することにより、
    設定を即時有効とできる認識です。

    上記手法がNGなのであれば、上記APIの使用以外でスクリーンセーバーの設定&即時有効となる手法がありましたら、お教えいただけると
    幸いです。
    2009年5月11日 2:34
  • SPIF_SENDCHANGEが有効なのはSPI_SETSCREENSAVEACTIVEの値だけ であり、書き換えたレジストリが有効になるとはどこにも書かれていません。でんでんさんの妄想です。

    書き換えているレジストリについて調べたところ、You can access this function with the command line rundll32.exe desk.cpl,InstallScreenSaver file , where file is the name of a screen saver executable file. とだけありました。
    試しに実行してみましたが、コントロールパネルが開きデフォルト値として選択されているまでに留まっていました。

    昨今スクリーンセーバーの仕様の弱点を突いたウィルスが多数存在します。プログラムからユーザー操作なしにスクリーンセーバーの変更を行うのはOSとして認めない方向で変更されたのではないでしょうか?
    • 回答としてマーク でんでん 2009年5月15日 17:42
    2009年5月11日 4:23
  • またまたご回答ありがとうございます!

    スクリーンセーバーの設定画面を表示するだけにすることとしました。

    2009年5月15日 17:42