「MSZIP」ない無圧縮 cab、ってなんやねんそれ (themepack の話)

これこそ「outdated」と言いたいところなのだが…。

今季アニメの覇権は「かげきしょうじょ!!」…じゃなくて。

昨日の話と同じく、mpplgen.py のさらなる応用として、Windows テーマパックビルダー、なんてことが出来ないかしら、と探ってみた話である。つまりデスクトップを渡辺さらさ色に染めたい、てわけだ。違うけど。

簡単に Windows テーマパックを自作出来るオンラインツールがある。こいつでさくっと作ってみるも、cab を展開してくれるもの持ってないなぁ…、と困ってたら、7zip が対応してた。ありがてー。んで、作られた .themepack を、ダブルクリックしてインストールするんではなくて、7zip で展開すると、こんな内容になってる:

 1 $ find t1627454199735  # windows-theme-creator で作ったのを 7zip で展開したフォルダ
 2 t1627454199735
 3 t1627454199735/DesktopBackground
 4 t1627454199735/DesktopBackground/0.jpg
 5 t1627454199735/DesktopBackground/1.jpg
 6 t1627454199735/DesktopBackground/2.jpg
 7 t1627454199735/DesktopBackground/3.jpg
 8 t1627454199735/nonnon2.theme
 9 $ cat t1627454199735/nonnon2.theme  # themeファイル
10 [Theme]
11 DisplayName=nonnon2
12 
13 [Control Panel\Desktop]
14 Wallpaper=DesktopBackground\0.jpg
15 TileWallpaper=0
16 WallpaperStyle=10
17 Pattern=
18 
19 [VisualStyles]
20 Path=%SystemRoot%\resources\themes\Aero\Aero.msstyles
21 ColorStyle=NormalColor
22 Size=NormalSize
23 ColorizationColor=0x6B74B8FC
24 Transparency=1
25 Composition=1
26 VisualStyleVersion=10
27 
28 [Slideshow]
29 Interval=1800000
30 Shuffle=1
31 ImagesRootPath=DesktopBackground
32 
33 [MasterThemeSelector]
34 MTSM=DABJDKT

テーマファイルの仕様はシンプルなものである。テーマパックファイルをダブルクリックしてインストールすると、実体とテーマファイルは「c:/Users/%USER%/AppData/Local/Microsoft/Windows/Themes」に配置され、テーマファイルも少し書き換えられて「ImagesRootPIDL なる謎仕様」が現れてビビるが、ドキュメントされている ImagesRootPath で書けばそれに置き換わるだけなので、ImagesRootPIDL については知る必要はない。

ちぅわけで、「テーマパックファイル自作はとっても簡単だ、ろう」と思うわけなのだが、やってみるとバカみたいな罠があるのであった。以下で出来るならなんも困らんかったのよね:

 1 # -*- coding: utf-8 -*-
 2 import msilib
 3 msilib.FCICreate(
 4     "nonnon3.themepack", [
 5         ("nonnon3.theme", "nonnon3.theme"),
 6         ("DesktopBackground/0.jpg", "DesktopBackground/0.jpg"),
 7         ("DesktopBackground/1.jpg", "DesktopBackground/1.jpg"),
 8         ("DesktopBackground/2.jpg", "DesktopBackground/2.jpg"),
 9         ("DesktopBackground/3.jpg", "DesktopBackground/3.jpg"),
10         ])

じっくりうまくいってる windows-theme-creator で作ったのと上の python で作ったのを比較してみるに、「圧縮方式」の差なのよね(→追記: 07-29 21時の追記参照):


どうやら「MSZip」になってると Windows は「テーマパックである」と認識してくれない。無論なぜこれが原因であるとわかったかというと、以下でうまくいったから:

 1 $ # 公式ドキュメントのみで MakeCAB の使い方を理解出来る人は天才。
 2 $ # これほど理解に苦労するツールもそうそうないわ。
 3 $ # https://ss64.com/nt/makecab.html でやっとわかる。
 4 $ # 必要なのは「ddfファイル」を作ってそれを渡すこと、である。
 5 $ cat aaa.ddf
 6 .OPTION EXPLICIT
 7 .Set MaxDiskSize=1073741824
 8 .Set CabinetNameTemplate=nonnon3.themepack
 9 .Set Cabinet=on
10 .Set Compress=off
11 "DesktopBackground\0.jpg" "DesktopBackground\0.jpg"
12 "DesktopBackground\1.jpg" "DesktopBackground\1.jpg"
13 "DesktopBackground\2.jpg" "DesktopBackground\2.jpg"
14 "DesktopBackground\3.jpg" "DesktopBackground\3.jpg"
15 "nonnon3.theme"
16 $ makecab -F aaa.ddf

うまくいった、の前に当然「うまくいかなかった」試行錯誤時間があるわけである。

ひとつに、ファイル名を与えるだけだと今の場合の「DesktopBackground」が作られないので「元ファイルと論理ロケーションのペア」を渡す必要があるのだが、ドキュメントに書かれてたからそうしてみたのではなくて、python での msilib.FCICreate のインターフェイスからの類推からやってみたらうまくいった、てだけ。もうひとつが MaxDiskSize で、これを制御しないと、デフォルトが「フロッピーディスク基準」なので、「3枚のフロッピーディスク」になる、たとえば。こりゃヒドい。して、最後に「Compress=off/Compress=on」の差が原因であると確定。

ちぅわけで、まぁ一応めでたく「makecab で作れば作れる」と。

にしても「無圧縮ねばなりません」てなんなのよ。どうも仕様的に MSZip 以外の圧縮が可能であるかのような記述をみかけたので、単に「MSZip がダメ」てことなのかもしれないよ、だとしたってさぁ…、納得できるか、これ?

なお、mpplgen.py に組み込んでない。今後組み込むかもわからん。msilib のでイケてたら組み込むつもりだったんだけどね、makecab 呼び出しを要するのはちょっとというかかなりイヤなので。


2021-07-29 21時追記:
Windows が themepack であると認識してくれない原因、圧縮方式ではなかった。パスデリミタがスラッシュだとダメ、つまり「DesktopBackground/0.jpg」としてると反応しない。

「C言語の影響を受けた言語」全てにおいてバックスラッシュが面倒なので、可能ならば私はいつでもスラッシュを使うようにしていて、Windows 生活でもざっくりおよそ約 99.732976372850390467284% くらいは問題ないのだが、これは問題ある数少ないおよそざっくり 0.26702362714961225% のほうだった。

なお、mpplgen.py に直接組み込むことはもうしないけれど、かわりに、単独のスクリプトは書いてみた:

入力はファイル名が列挙されたテキストファイルなのだが、このテキストファイルを mpplgen.py で作るというノリで考えると割とハッピーになれるかもしれない、て話。ちょっとコントロールは複雑だけど html からメディアを抽出する、とかも出来るからね、mpplgen.py。