コマンドラインツールを使用してMac OS X用の見栄えの良いDMGを作成するにはどうすればよいですか?


212

Macアプリケーション用の素敵なインストーラーを作成する必要があります。事前定義されたサイズ、レイアウト、背景画像を備えたディスクイメージ(DMG)にしたい。

これをプログラムでスクリプトで実行し、既存のビルドシステムに統合する必要があります(インストーラーのみを作成するため、実際にはパックシステムのようです。ビルドは個別に行われます)。

私はすでに「hdiutil」を使用してDMGの作成を行っていますが、アイコンのレイアウトを作成して背景のビットマップを指定する方法はまだわかりません。


1
これは別の質問のための何かではありませんか?
Lenar Hoyt、2011

回答:


199

多くの調査の結果、私はこの答えを思いついたので、参考のために、これを自分の質問の答えとしてここに置きます。

  1. [システム環境設定]> [ユニバーサルアクセス]で[支援デバイスのアクセスを有効にする]がオンになっていることを確認します。AppleScriptが機能するために必要です。この変更後に再起動が必要になる場合があります(Mac OS X Server 10.4ではそれ以外の方法では機能しません)。

  2. R / W DMGを作成します。結果よりも大きくする必要があります。この例では、bash変数「size」にはKBのサイズが含まれており、「source」bash変数内のフォルダーの内容がDMGにコピーされます。

    hdiutil create -srcfolder "${source}" -volname "${title}" -fs HFS+ \
          -fsargs "-c c=64,a=16,e=16" -format UDRW -size ${size}k pack.temp.dmg
    
  3. ディスクイメージをマウントし、デバイス名を保存します(この操作後、数秒間スリープを使用することをお勧めします)。

    device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \
             egrep '^/dev/' | sed 1q | awk '{print $1}')
    
  4. 背景画像(PNG形式)をDMGの「.background」というフォルダーに保存し、その名前を「backgroundPictureName」変数に保存します。

  5. AppleScriptを使用して視覚スタイルを設定します(.appの名前はbash変数 "applicationName"にある必要があり、必要に応じて他のプロパティの変数を使用します):

    echo '
       tell application "Finder"
         tell disk "'${title}'"
               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 {400, 100, 885, 430}
               set theViewOptions to the icon view options of container window
               set arrangement of theViewOptions to not arranged
               set icon size of theViewOptions to 72
               set background picture of theViewOptions to file ".background:'${backgroundPictureName}'"
               make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
               set position of item "'${applicationName}'" of container window to {100, 100}
               set position of item "Applications" of container window to {375, 100}
               update without registering applications
               delay 5
               close
         end tell
       end tell
    ' | osascript
    
  6. 権限を適切に設定し、圧縮して解放することにより、DMGをフィニアライズします。

    chmod -Rf go-w /Volumes/"${title}"
    sync
    sync
    hdiutil detach ${device}
    hdiutil convert "/pack.temp.dmg" -format UDZO -imagekey zlib-level=9 -o "${finalDMGName}"
    rm -f /pack.temp.dmg 
    

Snow Leopardでは、上記のAppleScriptはアイコンの位置を正しく設定しません-Snow Leopardのバグのようです。回避策の1つは、アイコンを設定した後で単にclose / openを呼び出すことです。つまり、

..
set position of item "'${applicationName}'" of container window to {100, 100}
set position of item "Applications" of container window to {375, 100}
close
open

1
優れた。それに関する2つの質問:1 sleep.画像をマウンディングした後に推奨します。どのぐらいの間?プロセスの完了を確定的に待つことはできませんか?delay 5AppleScriptでも同じです。私はそれらの非常に悪い経験があったので、そのような恣意的な待ち時間に常に警戒しています。2.ステップ6で、sync2回電話をかけます。なぜですか。
Konrad Rudolph、

「アプリケーションを登録せずに更新」コマンドの完了を確定的に待機する方法が見つかりませんでした。「hdiutil attach」後にスリープが必要かどうかはわかりませんが、ドキュメントを確認する必要があります(man hdiutil)。同期は1回だけ呼び出す必要があります。古き良きSunOSの時代から、私は古い習慣から2回呼び出しています。
Ludvig A. Norin

1
これにより、applescriptはマウスやキーボードの入力やその他の多くのことをシミュレートできます。
Ludvig A. Norin

1
「アプリケーションを登録せずに更新」の行でタイムアウトになるまでスクリプトがハングアップする場合、ステップ1は実行されていません(または元に戻されました)。私はこれを難しい方法で見つけました。
Jay Maynard K5ZC、2012年

AppleScriptにはイジェクトがあり、chmodを実行しようとする前に実行されます。ディスクが取り出されたため、chmodは失敗します。
Trejkaz 2013年

56

カスタム背景、カスタムアイコンの配置、ボリューム名を使用して、ファンシーDMGを作成するcreate-dmgという小さなBashスクリプトがあります。

何年も前に、当時経営していた会社のために構築しました。それ以来、それは他の人々の貢献で生き残り、伝えられるところによればうまく機能します。

Node.jsに基づいたよりモダンでアクティブな作業のように見えるnode-appdmgもあります。同様にそれをチェックしてください。


7
bashスクリプトへのリンクが壊れています。github.comの要旨に入れてもらえますか?ありがとう
dquimper

create-dmgはアイコンをうまく配置しません。この機能が必要な場合は、使用しないでください。
laike9m

1
@ laike9m最後に触れてから5年以上になります。私は、DMGがMacソフトウェアを配布するための最良の方法であるとは本当に考えていません。ですから、他の人の貢献で生き残ります-うまくいけば、誰かがアイコンの問題も理解するでしょう。
Andrey Tarantsov 2015

3
@Zmeyユーザーとしては、zipファイルの方がはるかに好きです。/Applicationsアプリがからの実行を検出した場合の自動コピーのボーナスポイント~/DownloadsJohn Gruberによるこの古い記事も参照してください。
Andrey Tarantsov 2016


37

そこに行かないでください。長期のMac開発者として、私はあなたに保証することができます。実際にうまく機能している解決策はありません。私は非常に多くの解決策を試しましたが、それらはすべてあまり良くありません。問題は、Appleが実際に必要なデータのメタデータ形式を文書化していないことだと思います。

これが私が長い間それを非常にうまくやっている方法です:

  1. 予想されるバイナリとreadmeなどの追加ファイルを保持するのに十分な大きさの新しいDMG、writeable(!)を作成します(スパースが機能する場合があります)。

  2. DMGをマウントし、Finderで手動で、またはそれを行うのに適したツールを使用してレイアウトを指定します(優れたツールについては、下部にあるFileStormリンクを参照してください)。背景画像は通常、DMGの非表示フォルダー(「.something」)に配置した画像です。アプリのコピーをそこに配置します(どのバージョンでも、古いバージョンでもかまいません)。必要な他のファイル(エイリアス、readmeなど)をコピーします。古いバージョンでも問題ありません。アイコンのサイズと位置が適切であることを確認してください(IOW、DMGを希望どおりにレイアウトします)。

  3. DMGを再度マウント解除します。これで、すべての設定が保存されます。

  4. 次のように機能するDMG作成スクリプトを記述します。

    • DMGをコピーするため、元のDMGに再度触れることはありません。
    • コピーをマウントします。
    • すべてのファイルを最新のファイルに置き換えます(たとえば、ビルド後の最新のアプリ)。コマンドラインでmvまたはdittoを使用するだけです。そのようなファイルを置き換えると、アイコンは同じままで、位置は同じままですが、ファイル(またはディレクトリ)の内容以外はすべて同じままです(少なくとも、通常はこのタスクで使用するdittoを使用します)。 。もちろん、背景画像を別の画像に置き換えることもできます(同じサイズであることを確認してください)。
    • ファイルを置き換えた後、スクリプトでDMGコピーを再度マウント解除します。
    • 最後にhdiutilを呼び出して、書き込み可能なDMGを圧縮された(そして書き込み不可能な)DMGに変換します。

この方法は最適に聞こえないかもしれませんが、私を信じて、それは実際には本当にうまく機能します。元のDMG(DMGテンプレート)をバージョン管理(例:SVN)のもとに置くことができるため、誤って変更/破棄した場合でも、問題のないリビジョンに戻ることができます。XMGプロジェクトにDMGテンプレートを追加し、DMGに属する他のすべてのファイル(readme、URLファイル、背景画像)をすべてバージョン管理下に置いてから、ターゲット(「Create DMG」という名前の外部ターゲットなど)を作成できます。上記のDMGスクリプトを実行し、古いメインターゲットを依存ターゲットとして追加します。スクリプトで$ {SRCROOT}を使用してXcodeツリーのファイルにアクセスでき(常に製品のソースルートです)、$ {BUILT_PRODUCTS_DIR}を使用してビルド製品にアクセスできます(常にXcodeがビルド結果を作成するディレクトリです) 。

結果:実際には、Xcodeはビルドの最後にDMGを生成できます。リリースの準備ができているDMG。このようにリリースDMGを非常に簡単に作成できるだけでなく、コマンドラインからxcodebuildを使用して(必要に応じて自動化されたナイトリービルドなど)、自動化されたプロセスで(必要に応じてヘッドレスサーバーで)実際に作成できます。

テンプレートの初期レイアウトに関しては、FileStormはそのための優れたツールです。それは商用ですが、非常に強力で使いやすいです。通常のバージョンは20ドル未満なので、非常に手頃な価格です。たぶん、FileStormを自動化してDMGを作成できます(例:AppleScriptを使用)。これを試したことがないかもしれませんが、完璧なテンプレートDMGが見つかったら、リリースごとに更新するのは本当に簡単です。


3
いくつかの理由で、私はすでにこの方法でそれを行うという考えを捨てました。そのうちの2つは次のとおりです。インストーラーの内容は製品によって異なります。パックマシンにインストールされているソフトウェアとスクリプトにのみ依存したいと考えています。新しい製品を追加するための単一の最小限の手動ルーチンです。
Ludvig A. Norin

これは私たちと同じシナリオです。私たちは12以上の製品を持っています。それぞれ完全に異なるDMGがあります。製品ごとに1つのテンプレートDMGを作成するのは1回限りのタスクであり、数分かかります。そして、「インストーラー」とはどういう意味ですか?PKG / MPKGインストールパッケージ?
Mecki

それは同じシナリオではありません。私たちは頻繁に製品を追加しますが、すぐに通知します。最小限の手動ルーチンとは、製品に名前と他のいくつかの属性を与えるスクリプトを実行することを意味します。これ以外にも、そのようなソリューションを使用しないことを決定した理由があります。
Ludvig A. Norin

パックプロセスはビルドプロセスから分離されています。これは、さまざまな人がさまざまなタイミングで行うためです。パックプロセスでは、Windows、Windows CE、Symbian、AIX、Linux、Solaris用のインストーラーも作成されます。
Ludvig A. Norin

hdutilではなく、hdiutilを参照している可能性があります。
IvanVučica、2009

25

この回答を提供することにより、この質問を最新のものにします。

appdmgシンプルなjson仕様からdmgファイルを作成する、シンプルで使いやすいオープンソースのコマンドラインプログラムです。公式Webサイトのreadmeをご覧ください。

https://github.com/LinusU/node-appdmg

簡単な例:

  1. appdmgをインストールする

    npm install -g appdmg
    
  2. jsonファイルを書き込む(spec.json

    {
      "title": "Test Title",
      "background": "background.png",
      "icon-size": 80,
      "contents": [
        { "x": 192, "y": 344, "type": "file", "path": "TestApp.app" },
        { "x": 448, "y": 344, "type": "link", "path": "/Applications" }
      ]
    }
    
  3. プログラムを実行する

    appdmg spec.json test.dmg
    

(免責事項。私はappdmgの作成者です)


3
シンプルで効果的。唯一の欠点は、npmをインストールする必要があることです
Jack James

@クリエイター:ドラッグアンドドロップすることなく、この1つのGUIのように進めていただけますか?s.sudre.free.fr/Software/Packages/about.html

.appファイルがjsonファイルと同じフォルダーにない場合、これは機能しません。「path」で相対パスを指定すると、「file not found」エラーが発生します
Joey

@Joey、問題が解決しない場合は、Githubリポジトリで問題を開くことができますか?
LinusUnnebäck2017

@Joey:同じフォルダにある必要はありません。背景があり、アプリはすべて別のパスにあり、相対パスを../../../ABCとして渡します
Anoop Vaidya

22

このトピックに関心のある方のために、DMGの作成方法について触れておきます。

hdiutil create XXX.dmg -volname "YYY" -fs HFS+ -srcfolder "ZZZ"

どこ

XXX == disk image file name (duh!)
YYY == window title displayed when DMG is opened
ZZZ == Path to a folder containing the files that will be copied into the DMG

1
それは問題ありませんが、実際のニーズ(背景画像、フォルダー内のアイテムの配置など)には対応していません
Tom Bogle

DMGを作成しましたが、CMDを使用してScript(.sh)を実行する必要があります
。DMGを

13

私のアプリDropDMGは、背景画像、アイコンレイアウト、カスタムボリュームアイコン、およびソフトウェアライセンス契約を含むディスクイメージを簡単に作成する方法です。「dropdmg」コマンドラインツールまたはAppleScriptを介してビルドシステムから制御できます。必要に応じて、画像とライセンスのRTFファイルをバージョン管理システムに保存できます。


3
私のチームは、これをJenkins CIビルドサーバーで美しく自動的に機能させており、バックグラウンドで完了し、アプリケーションエイリアスにドラッグします。ディスクイメージを作成するために、DropDMGまで実行してください。
ポールコリンズ

良いアプリです。試用期間が終了した後で購入します。
kilik52

見た目はいいですが、ウィンドウのサイズを変更するオプションがないようです。
avi 2015年

@avi DropDMGは、設定した背景画像(または必要に応じてその画像に挿入)に合わせてウィンドウのサイズを自動的に調整します。
Michael Tsai

まことにありがとうございます!背景画像なしでサイズを変更できますか?
avi 2015


5

見栄えの良いDMGを作成するには、よく書かれたオープンソースをいくつか使用するだけです。


彼らはそれを動かしたのかもしれません。create-dmgおよびnode-appdmgを使用できます。私はcreate-dmgを使用しています。それは良いです。
Anni S

@ PamelaCook-LightBeCorpまだ興味がある場合。dmgbuildへのリンクが修正されました。
SubOptimal 2017

4

カスタムボリュームアイコンを設定したい場合は、以下のコマンドを使用してください

/*Add a drive icon*/
cp "/Volumes/customIcon.icns" "/Volumes/dmgName/.VolumeIcon.icns"  


/*SetFile -c icnC will change the creator of the file to icnC*/
SetFile -c icnC /<your path>/.VolumeIcon.icns

次に、読み取り/書き込みdmgを作成します。

/*to set custom icon attribute*/
SetFile -a C /Volumes/dmgName

ここで「あなたの道」とはどういう意味ですか?ディスク上のアイコンファイルを使用できますが、SetFileはそれをコピーしますか、それとも.dmg内のファイルを使用する必要がありますか?Macは1つしかないので、他のマシンで動作するかどうかをテストするのは困難です。
ミラノバブスコフ

「あなたのパス」はDMG名です。(/ Volumes / dmgName)
Parag Bafna 14

icnsファイルをコピーする必要があります。cp "/Volumes/customIcon.icns" "/Volumes/dmgName/.VolumeIcon.icns"
Parag Bafna

4

私はようやくこれを自分のプロジェクト(たまたまXcodeにあります)で動作させました。これらの3つのスクリプトをビルドフェーズに追加すると、製品のディスクイメージが自動的に作成され、見栄えがよくなります。プロジェクトをビルドするだけで、DMGが製品フォルダーで待機します。

スクリプト1(一時ディスクイメージの作成):

#!/bin/bash
#Create a R/W DMG

dir="$TEMP_FILES_DIR/disk"
dmg="$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.temp.dmg"

rm -rf "$dir"
mkdir "$dir"
cp -R "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app" "$dir"
ln -s "/Applications" "$dir/Applications"
mkdir "$dir/.background"
cp "$PROJECT_DIR/$PROJECT_NAME/some_image.png" "$dir/.background"
rm -f "$dmg"
hdiutil create "$dmg" -srcfolder "$dir" -volname "$PRODUCT_NAME" -format UDRW

#Mount the disk image, and store the device name
hdiutil attach "$dmg" -noverify -noautoopen -readwrite

スクリプト2(ウィンドウプロパティスクリプトの設定):

#!/usr/bin/osascript
#get the dimensions of the main window using a bash script

set {width, height, scale} to words of (do shell script "system_profiler SPDisplaysDataType | awk '/Main Display: Yes/{found=1} /Resolution/{width=$2; height=$4} /Retina/{scale=($2 == \"Yes\" ? 2 : 1)} /^ {8}[^ ]+/{if(found) {exit}; scale=1} END{printf \"%d %d %d\\n\", width, height, scale}'")
set x to ((width / 2) / scale)
set y to ((height / 2) / scale)

#get the product name using a bash script
set {product_name} to words of (do shell script "printf \"%s\", $PRODUCT_NAME")
set background to alias ("Volumes:"&product_name&":.background:some_image.png")

tell application "Finder"
    tell disk product_name
        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 {x, y, (x + 479), (y + 383)}
        set theViewOptions to the icon view options of container window
        set arrangement of theViewOptions to not arranged
        set icon size of theViewOptions to 128
        set background picture of theViewOptions to background
        set position of item (product_name & ".app") of container window to {100, 225}
        set position of item "Applications" of container window to {375, 225}
        update without registering applications
        close
    end tell
end tell

上記のウィンドウの測定値は、特に私の背景の写真のサイズとアイコンの解像度のために、私のプロジェクトで機能します。独自のプロジェクトでこれらの値を変更する必要がある場合があります。

スクリプト3(最終ディスクイメージスクリプトの作成):

#!/bin/bash
dir="$TEMP_FILES_DIR/disk"
cp "$PROJECT_DIR/$PROJECT_NAME/some_other_image.png" "$dir/"

#unmount the temp image file, then convert it to final image file
sync
sync
hdiutil detach /Volumes/$PRODUCT_NAME
rm -f "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg"
hdiutil convert "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.temp.dmg" -format UDZO -imagekey zlib-level=9 -o "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg"
rm -f "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.temp.dmg"

#Change the icon of the image file
sips -i "$dir/some_other_image.png"
DeRez -only icns "$dir/some_other_image.png" > "$dir/tmpicns.rsrc"
Rez -append "$dir/tmpicns.rsrc" -o "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg"
SetFile -a C "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.dmg"

rm -rf "$dir"

使用している画像ファイルが$ PROJECT_DIR / $ PROJECT_NAME /ディレクトリにあることを確認してください!


私のプロジェクトで空のディスクイメージを作成しています。なにか提案を。
ManiaChamp

シェルスクリプト部分のみが機能しますが、ビルドフェーズでRunScriptのシェルスクリプトを使用してAppleスクリプトを追加するにはどうすればエラーが表示され、すべてのAppleスクリプトステートメントがシンボルが見つかりません。
ManiaChamp 2016年

2

.DS_Storeファイルは、Windowsの設定をMacに保存します。ウィンドウの設定には、アイコンレイアウト、ウィンドウの背景、ウィンドウのサイズなどが含まれます。.DS_Storeファイルは、ファイルの配置とウィンドウの背景を保持するためにマウントされたイメージのウィンドウを作成するときに必要です。

.DS_Storeファイルを作成したら、作成したインストーラー(DMG)にコピーするだけです。


ただし、最初に.background.pngのような名前を付けて背景画像をdmgに追加し、次にCmd-Jを使用してその(!)画像を背景に追加します。
Gijs

2

コマンドラインアプローチを使用して、パッケージ化とdmgの作成を「プログラムでスクリプトで」行う必要もあります。私がこれまでに見つけた最良の答えは、Adiumプロジェクトのリリース構築フレームワークからです(R1を参照)。OSX WindowsServer GUIの相互作用を回避できるようにするカスタムスクリプト(AdiumApplescriptRunner)があります。「osascript applescript.scpt」アプローチでは、ビルダーとしてログインし、コマンドラインvt100セッションからdmg作成を実行する必要があります。

OSXパッケージ管理システムは、このタスクを簡単かつ体系的に実行できる他のUnixenに比べてそれほど高度ではありません。

R1:http : //hg.adium.im/adium-1.4/file/00d944a3ef16/Release



1

これらの答えは非常に複雑で、時代は変わりました。以下は10.9で問題なく動作しますが、権限は正しく、見栄えがします。

ディレクトリから読み取り専用のDMGを作成する

#!/bin/sh
# create_dmg Frobulator Frobulator.dmg path/to/frobulator/dir [ 'Your Code Sign Identity' ]
set -e

VOLNAME="$1"
DMG="$2"
SRC_DIR="$3"
CODESIGN_IDENTITY="$4"

hdiutil create -srcfolder "$SRC_DIR" \
  -volname "$VOLNAME" \
  -fs HFS+ -fsargs "-c c=64,a=16,e=16" \
  -format UDZO -imagekey zlib-level=9 "$DMG"

if [ -n "$CODESIGN_IDENTITY" ]; then
  codesign -s "$CODESIGN_IDENTITY" -v "$DMG"
fi

アイコン付きの読み取り専用DMGを作成する(.icnsタイプ)

#!/bin/sh
# create_dmg_with_icon Frobulator Frobulator.dmg path/to/frobulator/dir path/to/someicon.icns [ 'Your Code Sign Identity' ]
set -e
VOLNAME="$1"
DMG="$2"
SRC_DIR="$3"
ICON_FILE="$4"
CODESIGN_IDENTITY="$5"

TMP_DMG="$(mktemp -u -t XXXXXXX)"
trap 'RESULT=$?; rm -f "$TMP_DMG"; exit $RESULT' INT QUIT TERM EXIT
hdiutil create -srcfolder "$SRC_DIR" -volname "$VOLNAME" -fs HFS+ \
               -fsargs "-c c=64,a=16,e=16" -format UDRW "$TMP_DMG"
TMP_DMG="${TMP_DMG}.dmg" # because OSX appends .dmg
DEVICE="$(hdiutil attach -readwrite -noautoopen "$TMP_DMG" | awk 'NR==1{print$1}')"
VOLUME="$(mount | grep "$DEVICE" | sed 's/^[^ ]* on //;s/ ([^)]*)$//')"
# start of DMG changes
cp "$ICON_FILE" "$VOLUME/.VolumeIcon.icns"
SetFile -c icnC "$VOLUME/.VolumeIcon.icns"
SetFile -a C "$VOLUME"
# end of DMG changes
hdiutil detach "$DEVICE"
hdiutil convert "$TMP_DMG" -format UDZO -imagekey zlib-level=9 -o "$DMG"
if [ -n "$CODESIGN_IDENTITY" ]; then
  codesign -s "$CODESIGN_IDENTITY" -v "$DMG"
fi

他に何かする必要がある場合、これらの最も簡単なことは、DMCを作成する前にSRC_DIRの一時的なコピーを作成し、それに変更を適用することです。


この答えは、以前に書かれたものに何も追加していませんし、元の質問にも答えていません(dmgにアイコンを配置することや、それに署名する方法ではありません。グラフィックスとアイコンをプログラムで配置することに関する質問です。 dmg)。
Ludvig A. Norin 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.