2021/12/31(金)Windowsのウィンドウ再配置問題を切替器で打開する

2021/12/31 16:47 PC(全般)

概要

よく知られている問題として、Windowsにはウィンドウの再配置問題がある。

HDMI・DisplayPortでモニタを接続している際に、モニタの電源を切ったりケーブルの挿抜を行うとOS側がこれを検知する。
この時、マルチディスプレイ(拡張)で使用している場合は、接続が生きている側のモニタにウィンドウが再配置されてしまう。

この問題を切替器で解決したので下記にあらましを記載する。

問題の内容

上でケーブルの挿抜と書いたが、物理的なスイッチ(あるいは相当)を行う切替器でも発生する。
ソース1,2とモニタを繋げている切替器で、ソース1&モニタ→ソース2&モニタと切り替えた場合ソース1側では挿抜検知となる。

この問題PnPの仕様としてはごく自然だが、日常的にはこの仕様が邪魔になることが多い。

初めてモニタを繋いだ時・構成を変えた時には有用だが、接続モニタの切り替えや電源OFFを日常的に行う運用をする場合はかなり煩わしいことになる。

特に、資料閲覧や動画視聴などいずれかのディスプレイのウィンドウ配置を決めて使用しているユーザにとってはかなり痛い。
こういった用途の場合、左右のディスプレイの解像度や縦横配置を揃えていない場合も多く、再配置によるウィンドウの乱れ方が大きい。

OS側

Windowsには現状この問題の挙動を変える方法が存在していない認識。
WindowsのInside Previewにこの問題のパッチが来ているという話があるが、完全な機能ではないと言われている。リリース時期も(リリースされるかも)不明。

PersistentWindows, MonitorKeeperなどウィンドウの位置を記憶・復帰するツールは多数あるが、アプリケーションごとの仕様・使い方・権限などの違いにより完璧な動作は難しい。
ヒューリスティック的な挙動にならざるを得ない。

モニタ側

さて、この問題はOS側以外にモニタ・ドライバの作りや設定によって挙動がある程度変わる。

モニタでは、EIZOのモニタはこの問題に対応するためにCompatible Modeというモードを備えている。
EIZO以外に明示的にこの機能を謳っているモニタは発見できていない。

この設定を変えるとモニタの電源を切った際にモニタ側が切断信号をOS側に送らなくなる。
電源を切るケースについてはモニタを選ぶことで対応可能である(EV2495で確認)。

ただし、EIZOはこういったOSDの機能では優秀なものの、パネル周りはピンキリで価格も割高。
EV2495についてもオレンジや水色でかなり不快な縦線が見えるパネルが使用されていたりする(EV2456から継続している問題なので、EV2456 縦縞などで検索するとサンプルがでてくる)。

モニタの選択肢があまりに少ないのは辛いので、できればモニタに依存しない対応方法にしたい。

グラボ側

グラフィックボード(おそらくドライバの作り)も影響するようだ。

私の場合、今年の8月にRadeon HD6450からRyzen 5700Gの内蔵GPUに変更した。
同じRadeon系列であるにも関わらず、HD6450では発生しなかった再配置問題が5700Gだと発生するように。
しかもHDMI・DisplayPort問わず発生する。

体験する前までこの問題はDisplayPort限定と認識していたため、かなり想定外だった。

実質同一チップメーカーでも発生するしないがある上、グラボの機能として有無を探すのがすごく難しい。

グラボでなんとかするのもつらそうなので、グラボに依存しない対応方法にしたい。

課題と制約

あわせて、モニタの接続周りでいくつか課題を抱えていたのでそれもいっぺんに解決してしまいたい。

・ゲーム機をつなぎたいがモニタ側にHDMI端子が足りない
・モニタ側の接続切り替え操作が機種によっては操作しづらいので簡単に操作できるようにしたい。最近のモニタではボタンが背面にあるものすらある。
・リモートワークをする機会が多く、私用PCと業務PC(ノート)をいずれもモニタに繋ぐ。素早く切り替えられるようにしたい。

構成的な制約は以下の通り。

・モニタは2枚(Display1~2)。一旦ともにWUXGA横配置とする。機種・解像度・縦横配置は自由に変更可能にしたい。

・PC1(私用PC)。2枚のディスプレイにつなぎ、メイン・拡張で使用。絶対に再配置されたくない。ほぼサーバなので恒常的に起動状態。

・PC2(業務PC)。ノート。2枚のディスプレイにつなぎ、メイン・拡張で使用。本体モニタは使用しない。業務時間中は再配置されたくない。業務が終われば電源OFF・ケーブル取り外しで、業務開始時に再配置されるのは特に問題ない。

・Switch。Switchにこだわらずゲーム機など、モニタ1枚を使用するHDMI機器を最大2台くらい繋げられると理想。

つまりソースが5~6本、シンクが2本。これを上手く接続したい。

対応手段

課題を整理すると、PCとモニタの間になにか問題を解決するための仲介役が必須になるようだ。

EDID保持・固定などで調べるといくつか製品が見つかる。

大まかに2系統あるようだ。

・アダプタ(ドングル):HDMI->HDMIかDP->DP。HDMIのソース側の電源で動く。
アダプタの機能として、モニタ側の電源OFFをソース側に伝えない。モニタのEDIDを学習してそれをソース側に伝える、もしくは設定した固定EDIDをソース側に伝える。製品ごとの固定EDIDを持つものも(この場合、モニタの解像度ごとにアダプタが必要)。
amazonで売っている製品名不明のものや、同人ハードのDPHPDMAなど。

・切替器:HDMIのものが多くDPのものは少なかったり高かったり。外部電源が必要。
切替器の機能として、モニタ側の電源OFFをソース側に伝えない。モニタのEDIDを学習してそれをソース側に伝える、もしくは設定した固定EDIDをソース側に伝える。
TESmartの切替器など。

これを組み合わせて問題を何とかする。

実構成

いろいろ考えた挙げ句、TESmartの切替器を軸に以下の構成に落ち着いた。

 +----------+             +----------+
 | Display1 |             | Display2 |
 +----+-----+             +----+-----+
      |                        |
      +-------+           +----+
              |           |
         +----+-----------+---+          +----------+
         |  OUT1        OUT2  |          |          |
         |                    |          |      +---+------------+
         |  TESmart           |          |      |  OUT1          |
         |   TES-HMA0402A1U   |          |      |                |
         |                    |          |      |  SANWA SUPPLY  |
         | IN1  IN2  IN3  IN4 |          |      |   SW-HD31ML    |
         +--+----+----+----+--+          |      |                |
            |    |    |    |             |      | IN1  IN2  IN3  |
   +--------+    |    |    +-------------+      +--+----+--------+
   |             |    +-+                          |    |
   |    +--------+--+   |                          |    +--------+
   |    | BENFEI    |   |                          |             |
   |    |  DP->HDMI |   |    +------------+    +---+--------+    |
   |    +---+-------+   |    | Plugable   +----+ PCduoduo   |    |
   |        |           |    |  UGA-4KDP  | DP |  DP->HDMI  |    |
   |        |DP         |    +-+----------+    +------------+    |
   |        |           |      | USB                             |
+--+--------+---+    +--+------+-----+                           |
| HDMI     DP   |    | HDMI   USB    |                      +----+-----+
|               |    |               |                      | Nintendo |
|      PC1      |    |  PC2(Laptop)  |                      |  Switch  |
|               |    |               |                      +----------+
+---------------+    +---------------+

以下に、接続している機器についての詳細を記載する。

TESmart TES-HMA0402A1U
4入力2出力のHDMI切替器。切替器の電源が生きている間は切断信号をソース側に伝達しない。OUTにつないだモニタ側のEDIDを記憶し、IN側によしなに流してくれるようだ。細かい挙動を突き詰めていないが不満に感じるポイントがない。切り替えはモニタ側でやるより早いケースが多いと思う。物理ボタンはOUTに対してIN1~4をローテーションで切り替えるボタンが2つ(OUT1, OUT2用)。物理ボタンだと一発で指定ソースを選べないが、リモコンが付属しておりそちらではソースを直接指定できる。6入力だったら最高だった。現状のゲーム機器等のコネクタを考えるとDPではなくHDMI切替器である必要がある。

BENFEI DP->HDMIアダプタ
amazonで売っている安売りのDisplayPort→HDMI変換アダプタ。製品名不明で、別ブランドから同じ形のものがたくさん出ている。かなりの曲者で、3台入手したうち2台はPlugable UGA-4KDPからの変換に使うとNo Monitor 640x480固定になってしまう(EDIDが取れない?)。インピーダンスがばらついてるとか、チップが変わったとかそういうもののような気がする。PC1のDisplayPortにつなぐ分にはいずれも問題なかった。
この手の変換アダプタは国内サプライメーカーで販売しているものも中身同じだったりして、金を出せば失敗しないかというとなんとも言えないのが辛い。

Plugable UGA-4kDP
もともとモニタに空いているポートがDisplayPortしかなかったのでこれを使用していた。新構成でも流用。

DisplayLinkのチップを使用しており、挙動はやや怪しい(たまに止まる)。
DisplayLinkは製品の質でユーザからの不満が多い印象もあるが、現状USB単独でモニタを増やせる機器(チップ)自体があまり選択肢がない。その中ではPnPでドライバが入るのでDisplayLinkの信用度はけっこうある。

PCduoduo DP->HDMIアダプタ
amazonで売っている安売りのDisplayPort→HDMI変換アダプタ。製品名不明で、別ブランドから同じ形のものがいくつか出ている。BENFEIで2連続失敗したので購入。こいつはPlugableにつないでも問題なかった(EDIDをちゃんと取れた)。

SANWA SUPPLY SW-HD31ML
以前から使っていた切替器。TESmart切替器と合わせて、6入力を実現するために使用。IN切り替えがローテーションではなく直接ボタンでやれるのが良い。内部的には物理切替器とほぼ同じなので、この切替器につないだ機器は再配置問題が発生し得る。一緒に使う可能性がない機器の組み合わせ、もしくはモニタ1枚を使用する機器をつなぐ。

ついでにHDMIケーブルをすべて、細い割に不具合もなさそうなELECOMのCAC-HD14USシリーズで統一。

ケーブルの取り回しも楽になって(本数は増えたが)楽になった。

結果

メリット

・再配置問題を気にせずにモニタの電源を切れる。

・モニタの切り替えで本体操作不要。リモコンですばやく楽に。どのように切り替えても、PC1では再配置問題は発生しない。

・HDMIを軸に統一したので配線の考え方がシンプルに。HDMIに変換してHDMIで配線すればよい。ケーブルの流用が効くし、取り回しも楽。

・これからは、モニタはHDMI一口あれば何を買っても大丈夫。モニタ購入時に端子の個数・形状を気にしなくてよい。またウィンドウ再配置問題の対応(EIZOのCompatible Mode相当)も気にしなくてよい。

・これからは、PC1用のグラボはHDMIもしくはHDMIに変換できるコネクタ(DVIかDisplayPort)が計2個あれば何を買っても大丈夫。グラボ購入時にウィンドウ再配置問題を気にしなくてよい。

デメリット・課題

・ケーブルが増えた

・SW-HD31MLにつないでいる機器は再配置問題が発生しうる。今の用途だと回避しなくても不満がないが、回避したいとなるとTESmart切替器2台以上の組み合わせか50k以上する業務用機器になるかも

・TESmart切替器の消費電力(測っていない)

・TESmart切替器が単一障害点になってしまうので、今後故障時に同等製品がないと(あるいはやたらと高くなってたりすると)死ぬ。

余談

そのうちUSB-C(DP Alt)だらけになってしまいそうな気がするが、Windows側がなんとかしないとデイジーチェーンだろうが何だろうがこの問題は改善しない(はず)。

しばらくこの構成でつなぎつつ、OS側が何とかしてくれるのを期待したい。
結局、OS側ではなんともならずDP時代にはTESmartのDP切替器を使ってそうな気もする。

2021/09/19(日)pycronが動かない

2021/09/19 25:39 PC(全般)
Windowsのタスクスケジューラにどうも馴染めないので、pycronというWindows用cron実装ソフトを利用している。

システムをクリーンインストールした際に、pycronが動かなくなってしまったのでその解決方法についてメモ。

なお、かなり古いソフトで公式サイトも消失している。
同名のソフトやライブラリもあって検索がまともに機能しない。
なかなかに厳しい。

問題は、pycronを標準のc:\Program Files (x86)\pycronなどにインストールした場合に発生する。
サービスとして起動したpycronが一切のタスクを実行しない。

原因はpycronサービスがcron設定ファイルcrontab.txtを読めていないから。
これはWindowsのVirtualStore機能でハマりが発生している。

pycronは、付属のcrontab.txt Editor(GUIのcrontab編集ツール)でcrontab.txtを作ったり、スクリプトのテスト実行ができる。
便利なのだが、これが問題を起こす。

crontab.txt Editorを非管理者権限で動かして設定を保存すると、自動的にWindowsのVirtualStore機能が働き、

C:\Users\********\AppData\Local\VirtualStore\Program Files (x86)\pycron

にcrontab.txtを出力する。

しかし、pycronはデフォルトで、pycron.exeと同一ディレクトリにcrontab.txtが存在する想定で動く。

サービスとして動くpycron.exeはローカルシステムアカウント(SYSTEM)で動くため、
c:\Program Files (x86)\pycron\crontab.txt
を直接読みに行き、crontab.txtが存在しないので動かないという事象になる。

混乱を招くポイントとして、非管理者権限で動かしたファイラーなどからは、
c:\Program Files (x86)\pycron
の中身は、実際のディレクトリ内容にVirtualStoreディレクトリの内容を上書きしたような状態で表示される。
同一名ファイルが有る場合でも、VirtualStore側が優先ということ。

ログファイルについても、crontab.txt Editorでテスト実行をするとまずVirtualStore側にpycron.logが出力される。
サービスのpycron.exeはc:\Program Files (x86)\pycron\pycron.logを出力するので、
手順と閲覧方法によってはVirtualStore側に隠されてしまってサービスのログファイルが見えないことになったりする。

なお、管理者権限で動かしたプログラムからは、素のc:\Program Files (x86)\pycronの内容が見える。

解決手段は下記どれか。
a) Program Files (x86)以外にインストールする
b) crontab.txt Editorを管理者権限で実行して、c:\Program Files (x86)\pycronにcrontab.txtを出力する
c) pycron.cfgを書いて、VirtualStore側のcrontab.txtを読むようにする
d) crontab.txtを手動でVirtualStore側からc:\Program Files (x86)\pycronにコピー

ただ、a)以外は、crontab.txt Editorの実行権限を間違えるたびにトラブルになりそうなのがなんとも嫌。
なので、a)案を採用した。

タスクスケジューラはcronと比べUIや設定オプションの煩雑さの割に、スケジュールの細かいコントロールができないのが不満。
WSLを使えばよいのだろうが、こっちはこっちでHyper-Vとサードパーティ仮想化ソフトの共存が難しい問題がある。
VMWareやVirtualBox資産が結構あるので切り替えが難しい。

ここらへんあと2,3年の技術進化で共存なり寄せなりスッキリできるようになるんじゃないかと期待してるけど、
今のところはpycronで凌ぐ方向で。

2021/07/17(土)debianのexim3で外部メール送信できるようにする

2021/07/17 20:56 PC(Linux)
もともと自宅サーバではqmailやsendmailを動かしていたのだが、Debian 8.0(jessie)切替時にさっぱり切ってしまった。

現状exim4が動いているのだが、外部にメール送信ができない。

zabbixとかは独自にSMTPサーバが登録できるのでごまかしていたが、
ここ来て流石にサーバ内からメールを投げたいケースが出てきた。

ということで、外部にメール送信できるようにする

基本的に下記の手順通りでよし。

Exim4/外部SMTPサーバー経由でメールを送信したい(Debian) - Void of Knowledge

mailコマンドで送信できることを確認。
echo "test" | mail -s "test title" -r from@example.com to@example.com
今度時間あるときに転送周りとcronメールも整理しよう。

2021/07/17(土)WebサーバをHTTPSに対応させる

2021/07/17 19:42 PC(Linux)
時間がないのでメモだけ。

最近はLet's Encryptの証明書発行もかなり簡単にやれるというので、当サイトもついに対応することにした。

基本的には下記のやり方通り。

Debian9 + Apache に"Let's Encrypt"をセットアップしてみた!! : プログラミング Tips

ただし、certbotコマンドについてはサブドメインがあるので、
#certbot certonly --webroot -w /var/www/html -d dt8.jp www.dt8.jp
とした。

また、SSLCipherSuiteの設定は息が長くなるよう、
mod_sslで使用するSSLCipherSuiteの設定を詰めてみる '20 - Qiita
に従った。

ローカルからのアクセスでhttps://~が表示されることを確認。

問題なさそうなので、ファイアウォール設定を変更しIPv4 ポート443の外部アクセスを開けた。

/etc/iptables/rules.v4
を編集して、
#netfilter-persistent reload
サーバ入れ替えた際に、かなり雑に作業をしてしまったのでiptablesの管理方法をちゃんと定義できてない。
年末までになんとかしよう。

SSL Server Testで、一応A判定が出ていることを確認。
https://www.ssllabs.com/ssltest/analyze.html?d=www.dt8.jp

さらに証明書更新したら、自動的にサーバを再起動してメールを送る設定にする。

/etc/letsencrypt/renewal-hooks/

に適当なシェルを作成し、
#!/bin/bash
/usr/sbin/apache2ctl restart
/bin/echo "証明書を更新し、Webサーバを再起動しました。" | /usr/bin/mail -s "証明書更新・Webサーバ再起動通知" -r mailaddress@example.com mailaddress@example.com
とか書く。

クリティカルなサービスがないので完全自動で良いし、restartで安全に。
当たり前だが、落とせないサービスならこんな事やってはいけない。

念の為動作テストする。
#certbot renew --force-renewal
証明書の期限更新~Webサーバの再起動~メール送信の一連の処理が行われることを確認。
更新制限があるので、何度もテストすのはNG。

あとは、サイト内にhttp://~から書いているところがあるかもしれないので、気づいたら直す。
そもそもリニューアルを予定しているのでちまちまやってく。

半年以上安定したら、mod_rewriteでhttp→httpsに振るようにしたい。

[2021/10/14追記]
上の手順で十分だと思っていたら、3ヶ月後の証明書更新が見事に失敗していた。

/var/log/letsencrypt/letsencrypt.logに出力されたエラー内容は、下記。

certbot.errors.MissingCommandlineFlag: Missing command line flag or config entry for this setting:
Select the webroot for dt8.jp:
Choices: ['Enter a new webroot', '/var/www/html']

(You can set this with the --webroot-path flag)

2021-10-13 17:06:46,513:ERROR:certbot.renewal:All renewal attempts failed. The following certs could not be renewed:
2021-10-13 17:06:46,514:ERROR:certbot.renewal:  /etc/letsencrypt/live/dt8.jp/fullchain.pem (failure)
dt8.jpのエントリがないと言われる。
あれ、そうなのか… force-renewalが成功したのはなんでだろう。

/etc/letsencrypt/renewal/dt8.jp.conf
の、
[[webroot_map]]
に、
www.dt8.jp と同じ内容で、dt8.jpの行を追加。
#certbot renew --dry-run
したら通るようになったので次のcronを待って、証明書が更新されることを確認した。
OK キャンセル 確認 その他