macOSアプリを配布するdmgは、開くと、アプリとApplicationsフォルダのショートカットが並び、背景に説明の画像が表示されているものが多い。ユーザーは、アプリのアイコンをApplicationsにドラッグしてインストールできる。このレイアウトは、dmgの中の/Applicationsへのシンボリックリンクと、Finderのウィンドウ設定を保存する.DS_Storeで作る。
$ ln -s /Applications stage/Applications
ここでは、/Applicationsへのシンボリックリンクを入れる方法と、Finderにosascriptで背景画像とアイコンの配置を設定させる方法を紹介する。実行例はmacOS 27.0.1のもの。
- 親記事: 【dmg】作り方まとめ
dmgに入れるファイルを用意する
dmgに入れるファイルを、1つのフォルダ(ここではstage)にまとめる。アプリ、/Applicationsへのシンボリックリンク、背景画像を入れる.backgroundフォルダを用意する。
$ mkdir -p stage/.background
$ cp -R [アプリ名].app stage/
$ ln -s /Applications stage/Applications
$ cp [背景画像].png stage/.background/background.png
.で始まる.backgroundは隠しフォルダなので、Finderには表示されない。背景画像を、この隠しフォルダに置くと、ユーザーのウィンドウに画像ファイルが表示されない。
シンボリックリンクはdmgに保たれる
/Applicationsへのシンボリックリンクと隠しフォルダは、hdiutil createとdiskutil image create fromのどちらでも、そのままdmgに入る。
$ hdiutil create -volname "[ボリューム名]" -srcfolder stage -format UDZO -ov hd.dmg
$ diskutil image create from --volumeName "[ボリューム名]" stage di.dmg
$ diskutil image attach --readOnly --mountOptions nobrowse --mountPoint [マウントポイント] hd.dmg
$ ls -A [マウントポイント]
.background
Applications
Demo.app
$ readlink [マウントポイント]/Applications
/Applications
この時点でも、dmgを開くと、アプリとApplicationsが表示される。ただし、背景画像はなく、アイコンの位置も決まっていない。背景画像とアイコンの配置は、Finderの設定として、.DS_Storeに保存する必要がある。
背景画像を用意する
背景画像は、ウィンドウの大きさに合わせた画像を用意する。ここでは、600×400ピクセルの画像を使う。sipsで、画像の大きさを変更できる。
$ sips -z 400 600 [元の画像].png --out stage/.background/background.png
sips -zで変更するのは大きさだけで、DPIは元の画像から引き継がれる。
画像のDPIを72にする
Finderは、画像のDPI(解像度の情報)を見て、表示する大きさを決める。DPIが72であれば、1ピクセルが1ポイントで表示される。DPIが96の画像は、4分の3の大きさに縮小されて表示された。
sips -gで、画像のDPIを確認できる。
$ sips -g pixelWidth -g pixelHeight -g dpiWidth -g dpiHeight stage/.background/background.png
pixelWidth: 600
pixelHeight: 400
dpiWidth: 96.000
dpiHeight: 96.000
DPIが96の600×400ピクセルの画像を背景に指定すると、ウィンドウの左上に450×300ポイントで表示され、右側と下側に空白ができた。
$ sips -s dpiWidth 72 -s dpiHeight 72 stage/.background/background.png
DPIを72に変更した画像では、ウィンドウの幅いっぱいに、等倍で表示された。
Finderにレイアウトを設定させる
背景画像やアイコンの位置は、Finderのウィンドウの設定である。Finderに、AppleScriptでウィンドウの設定をさせる。設定は、dmgの中の.DS_Storeというファイルに保存される。
Finderから操作するため、書き込み可能なdmgを作り、Finderに見える形でマウントする。--mountOptions nobrowseは付けない。
$ hdiutil create -size 20m -fs APFS -volname "[ボリューム名]" -ov layout-rw
$ diskutil image attach layout-rw.dmg
マウントポイントを指定しないと、/Volumes/[ボリューム名]にマウントされる。ファイルをコピーする。
$ cp -R stage/[アプリ名].app "/Volumes/[ボリューム名]/"
$ ln -s /Applications "/Volumes/[ボリューム名]/Applications"
$ mkdir -p "/Volumes/[ボリューム名]/.background"
$ cp stage/.background/background.png "/Volumes/[ボリューム名]/.background/"
osascriptで、Finderにウィンドウの設定をさせる。
$ osascript <<'EOF'
tell application "Finder"
tell disk "[ボリューム名]"
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {200, 120, 800, 520}
set theViewOptions to the icon view options of container window
set arrangement of theViewOptions to not arranged
set icon size of theViewOptions to 96
set background picture of theViewOptions to file ".background:background.png"
set position of item "[アプリ名].app" of container window to {150, 200}
set position of item "Applications" of container window to {450, 200}
close
open
update without registering applications
delay 2
close
end tell
end tell
EOF
実行すると、Finderのウィンドウが開いて、数秒後に閉じる。AppleScriptの主な設定は、次のとおりである。
| 設定 | 内容 |
|---|---|
current view | アイコン表示にする |
toolbar visible・statusbar visible | ツールバーとステータスバーの表示 |
bounds | ウィンドウの位置と大きさ(左、上、右、下) |
arrangement | アイコンの整列(not arrangedは自動で整列しない) |
icon size | アイコンの大きさ |
background picture | 背景画像。dmgの中のパスを、:区切りで指定する |
position | 各アイテムの位置(左、上) |
disk "[ボリューム名]"で、Finderに操作させるボリュームを指定する。同じ名前のボリュームが、すでにマウントされていないことを確認してから実行する。
.DS_Storeに設定が保存される
AppleScriptが成功すると、ボリュームのルートに、.DS_Storeが作られる。
$ ls -la "/Volumes/[ボリューム名]/.DS_Store"
-rw-r--r-- 1 sue staff 10244 ... /Volumes/[ボリューム名]/.DS_Store
.DS_Storeの中には、ウィンドウの設定(bwsp)、アイコン表示の設定(icvp)、アイテムごとの位置(Iloc)が記録されていた。bwspは、次のような内容だった。
{'ShowStatusBar': False, 'ShowToolbar': False, 'ShowTabView': True, 'ContainerShowSidebar': False,
'WindowBounds': '{{200, 920}, {600, 400}}', 'ShowSidebar': False}
WindowBoundsの大きさ(600×400)は、AppleScriptのboundsと一致した。位置の値は、boundsで指定した上端(120)とは別の値(920)で記録された。
icvpには、アイコンの大きさ(iconSize: 96.0)と整列(arrangeBy: none)が記録されていた。背景は画像を示す値(backgroundType: 2)で、背景画像の参照も含まれていた。Ilocには、Applicationsの位置(450, 200)と、アプリの位置(150, 200)が記録されていた。
配布用のdmgに変換する
Finderの設定が終わったら、dmgをeject(マウントを解除)して、読み取り専用の圧縮した形式に変換する。
$ diskutil eject "/Volumes/[ボリューム名]"
$ diskutil image create from --format UDZO layout-rw.dmg layout-final.dmg
layout-final.dmg created
変換したdmgをマウントして確認すると、.DS_Storeが残っていた。
$ diskutil image attach --readOnly --mountOptions nobrowse --mountPoint [マウントポイント] layout-final.dmg
$ ls -la [マウントポイント]
drwxr-xr-x 3 sue staff 96 ... .background
-rw-r--r-- 1 sue staff 10244 ... .DS_Store
drwx------ 5 sue staff 160 ... .fseventsd
lrwxr-xr-x 1 sue staff 13 ... Applications -> /Applications
drwxr-xr-x 3 sue staff 96 ... [アプリ名].app
.fseventsdは、macOSがボリュームに自動で作るディレクトリである。このディレクトリも、dmgに入った。
参考: 【diskutil】image createでdmgを作る
実際の見た目を確認する
作成したdmgを、Finderで開く。
$ open layout-final.dmg
次の結果になった。
- 背景画像が表示され、
[アプリ名]が左、Applicationsが右に、指定した位置に並んだ - DPIが96の背景画像は、450×300ポイントに縮小され、右と下に空白ができた。DPIを72にすると、ウィンドウの幅いっぱいに表示された
- ツールバーは、消えなかった
ツールバーは、.DS_StoreにShowToolbar: Falseと記録されたが、macOS 27.0.1のFinderでは、表示されたままだった。
ウィンドウは、指定した大きさ(600×400)で、タイトルバーとツールバーを含んだ大きさだった。背景画像の縦は、その分だけ、ウィンドウに収まる範囲が小さくなる。背景画像の下側にアイコンの説明などを入れる場合は、ウィンドウの大きさと配置を確認して調整する。
署名と公証
レイアウトを設定したdmgも、署名と公証が必要である。署名と公証の手順は、別の記事で紹介している。
参考: 【notarytool】dmgを公証する (submit)
