2022/08/12(金) [n年前の日記]
#1 [pygame][windows] スクリーンセーバと多重起動抑止
Windows10 x64 21H2上で、Python + pygame を使ってスクリーンセーバ(.scr)を作れないものかと実験しているのだけど、なかなか難しいことがちょっとだけ分かってきた。多重起動を抑止する処理が重要になってくるんだなと…。
◎ プレビューモードの問題。 :
Windows用のスクリーンセーバは、スクリーンセーバ設定画面のプレビュー窓の中に表示させるために、コマンドラインオプションとして「/p xxxx」を指定して実行される場合があるのだけど。この呼び出しがとにかく多い。
とにかく、何かしらちょっと操作する度に、Windows はスクリーンセーバを /p xxxx 付きで実行するので…。もし、多重起動を抑止する処理を何も入れてないと、そのスクリーンセーバのプロセスが3つも4つも大量に走っている状態になる…。
例えばそのスクリーンセーバが、プレビュー窓に対して、何かしらのアニメーションを延々描画し続けるような作りだと…。
各プロセスが、「俺がこの窓に描き込むぞ」「いや、俺が描き込む」「いやいや、俺が」「いや待て。ここは拙者が」「僕も描くよ」「私だって」てな状態になって…。プレビュー窓内のアニメーションが、それはもうグチャグチャな状態に…。動作確認中、その奪い合いぶりを目にしてかなり慌ててしまった。見るからにヤバイ。
そんなわけで、/p xxxx 付きで実行された場合は、多重起動抑止処理が絶対に必要になるのだなと分かってきた…。
ただ、この件については、プレビュー窓内でアニメーションをさせようとするからおかしなことになるような気もする。
例えば、/p xxxx で実行された際は、プレビュー窓内に画像1枚だけを描画して即座に終了する作りにすれば、プロセスが大量に発生して残り続けることも避けられるのではなかろうか。そういう作りなら、多重起動抑止の処理も不要かなと想像しているのだけど、さてどうだろう。
- スクリーンセーバの設定画面を開いて、そのスクリーンセーバが選択済みなら、/p xxxx 付きで呼ばれる。
- リストから選択した際も、/p xxxx で呼ばれる。
- 「設定」ボタンをクリックして、設定ダイアログを表示した後にも呼ばれる。
- 「プレビュー」ボタンをクリックしてフルスクリーン表示をして、そこから抜けた際にも呼ばれる。
とにかく、何かしらちょっと操作する度に、Windows はスクリーンセーバを /p xxxx 付きで実行するので…。もし、多重起動を抑止する処理を何も入れてないと、そのスクリーンセーバのプロセスが3つも4つも大量に走っている状態になる…。
例えばそのスクリーンセーバが、プレビュー窓に対して、何かしらのアニメーションを延々描画し続けるような作りだと…。
各プロセスが、「俺がこの窓に描き込むぞ」「いや、俺が描き込む」「いやいや、俺が」「いや待て。ここは拙者が」「僕も描くよ」「私だって」てな状態になって…。プレビュー窓内のアニメーションが、それはもうグチャグチャな状態に…。動作確認中、その奪い合いぶりを目にしてかなり慌ててしまった。見るからにヤバイ。
そんなわけで、/p xxxx 付きで実行された場合は、多重起動抑止処理が絶対に必要になるのだなと分かってきた…。
ただ、この件については、プレビュー窓内でアニメーションをさせようとするからおかしなことになるような気もする。
例えば、/p xxxx で実行された際は、プレビュー窓内に画像1枚だけを描画して即座に終了する作りにすれば、プロセスが大量に発生して残り続けることも避けられるのではなかろうか。そういう作りなら、多重起動抑止の処理も不要かなと想像しているのだけど、さてどうだろう。
◎ 待ち時間の問題。 :
もう一つ問題がある。Windows用スクリーンセーバの作成方法について書いてある記事を眺めてたら、ちょっと怖いことが書いてあった。
例えば、スクリーンセーバの待ち時間を10分に設定してあって、かつ、何の操作もしてない状態がずっと続いたら…。Windowsは、スクリーンセーバが実行されていようといまいと、10分置きにスクリーンセーバの実行を指示するそうで。
その話が本当ならヤバイ。試しに、先日作成した動作チェック用の .scr を使って、待ち時間を1分にして様子を伺ってみたら、たしかに1分間隔でスクリーンセーバが何度も何度も実行されていた…。
_Windows用スクリーンセーバの呼び出し動作をPythonで確認 - mieki256's diary
そんなわけで、/s をつけてフルスクリーン表示を要求された際も、多重起動抑止処理が絶対に必要になりそうだなと。
ちなみに、自分が今まで作成したスクリーンセーバモドキは、そういう処理を一切入れてなかったので…。これは非常にマズイなと今頃になって気づかされた…。あくまで、モドキでしかなかった…。
例えば、スクリーンセーバの待ち時間を10分に設定してあって、かつ、何の操作もしてない状態がずっと続いたら…。Windowsは、スクリーンセーバが実行されていようといまいと、10分置きにスクリーンセーバの実行を指示するそうで。
その話が本当ならヤバイ。試しに、先日作成した動作チェック用の .scr を使って、待ち時間を1分にして様子を伺ってみたら、たしかに1分間隔でスクリーンセーバが何度も何度も実行されていた…。
_Windows用スクリーンセーバの呼び出し動作をPythonで確認 - mieki256's diary
[2022/08/12 00:03:28] preview , [C:\WINDOWS\system32\01_scrsavchk.scr /p 262910] [2022/08/12 00:04:40] fullscreen , [C:\WINDOWS\system32\01_SCR~1.SCR /s] [2022/08/12 00:05:43] fullscreen , [C:\WINDOWS\system32\01_SCR~1.SCR /s] [2022/08/12 00:06:46] fullscreen , [C:\WINDOWS\system32\01_SCR~1.SCR /s] [2022/08/12 00:07:49] fullscreen , [C:\WINDOWS\system32\01_SCR~1.SCR /s] [2022/08/12 00:08:53] fullscreen , [C:\WINDOWS\system32\01_SCR~1.SCR /s] [2022/08/12 00:09:56] fullscreen , [C:\WINDOWS\system32\01_SCR~1.SCR /s] [2022/08/12 00:10:04] preview , [C:\WINDOWS\system32\01_scrsavchk.scr /p 1049354]
そんなわけで、/s をつけてフルスクリーン表示を要求された際も、多重起動抑止処理が絶対に必要になりそうだなと。
ちなみに、自分が今まで作成したスクリーンセーバモドキは、そういう処理を一切入れてなかったので…。これは非常にマズイなと今頃になって気づかされた…。あくまで、モドキでしかなかった…。
◎ 多重起動抑止の種類。 :
多重起動の抑止処理は、スクリーンセーバ1つにつき1種類で十分、というわけでもないっぽい。
というのも、スクリーンセーバ設定画面のプレビュー窓にスクリーンセーバが表示されている状態で、フルスクリーン表示のスクリーンセーバが走る場面もあるそうで…。
その場合、既にプレビュー窓でプロセスが走っているから、フルスクリーン表示用のプロセスは走ってくれないことになってしまう。「プレビュー」ボタンをいくらクリックしても、何の変化も起きない状態になる。
つまり、プレビューモード用と、フルスクリーン表示用で、別々に多重起動抑止処理を入れておかないといけないようだなと…。
というのも、スクリーンセーバ設定画面のプレビュー窓にスクリーンセーバが表示されている状態で、フルスクリーン表示のスクリーンセーバが走る場面もあるそうで…。
その場合、既にプレビュー窓でプロセスが走っているから、フルスクリーン表示用のプロセスは走ってくれないことになってしまう。「プレビュー」ボタンをいくらクリックしても、何の変化も起きない状態になる。
つまり、プレビューモード用と、フルスクリーン表示用で、別々に多重起動抑止処理を入れておかないといけないようだなと…。
◎ 多重起動抑止の方法。 :
多重起動抑止処理はどうやって作ればいいのか少しググったけれど、Windowsの場合は Mutex なるものが使えるらしい。
他にも、ロックファイルを作成して、ロックファイルが存在するなら既にプロセスが走ってるから後続は起動させないというやり方もあるらしいけど。もし、ロックファイルを作ったプロセスが異常終了してしまうと、ロックファイルが残り続けて、その後ずっとプロセスが走らなくなる問題もあるそうで。
そんなわけで、Mutex なるソレを Pythonから利用する方法について調べ始めているところ。ctypes というモジュールを使えば実現できるっぽいけど…。
他にも、ロックファイルを作成して、ロックファイルが存在するなら既にプロセスが走ってるから後続は起動させないというやり方もあるらしいけど。もし、ロックファイルを作ったプロセスが異常終了してしまうと、ロックファイルが残り続けて、その後ずっとプロセスが走らなくなる問題もあるそうで。
そんなわけで、Mutex なるソレを Pythonから利用する方法について調べ始めているところ。ctypes というモジュールを使えば実現できるっぽいけど…。
[ ツッコむ ]
以上です。