如何使用命令行工具为 Mac OS X 创建漂亮的 DMG?
Posted
技术标签:
【中文标题】如何使用命令行工具为 Mac OS X 创建漂亮的 DMG?【英文标题】:How do I create a nice-looking DMG for Mac OS X using command-line tools? 【发布时间】:2010-09-10 22:41:46 【问题描述】:我需要为 Mac 应用程序创建一个不错的安装程序。我希望它是具有预定义大小、布局和背景图像的磁盘映像 (DMG)。
我需要在脚本中以编程方式执行此操作,以集成到现有的构建系统中(实际上更像是一个打包系统,因为它只创建安装程序。构建是单独完成的)。
我已经使用“hdiutil”创建了DMG,我还没有发现如何制作图标布局和指定背景位图。
【问题讨论】:
这不是问不同的东西吗? github.com/LinusU/node-appdmg 【参考方案1】:经过大量研究,我想出了这个答案,特此将其放在这里作为我自己问题的答案,以供参考:
确保在系统偏好设置>>通用访问中选中“启用辅助设备访问”。 AppleScript 需要它才能工作。进行此更改后,您可能需要重新启动(否则它在 Mac OS X Server 10.4 上不起作用)。
创建一个 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 $sizek pack.temp.dmg
挂载磁盘映像,并存储设备名称(您可能希望在此操作后使用 sleep 几秒钟):
device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \
egrep '^/dev/' | sed 1q | awk 'print $1')
将背景图片(PNG 格式)存储在 DMG 中名为“.background”的文件夹中,并将其名称存储在“backgroundPictureName”变量中。
使用 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
通过正确设置权限、压缩和释放来完成 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 的错误。一种解决方法是在设置图标后简单地调用关闭/打开,即:
..
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.你推荐sleep
在镜像后。多久?难道不能确定地等待过程完成吗? AppleScript 中的delay 5
相同。我总是对这种随意的等待时间保持警惕,因为我有过一些非常糟糕的经历。 2. 在您的第 6 步中,您两次致电 sync
- 为什么?
我还没有找到任何方法来确定地等待“更新而不注册应用程序”命令的完成。我不确定在“hdiutil attach”之后是否需要睡眠,您必须检查文档(man hdiutil)。 Sync 应该只需要被调用一次,自从 SunOS 好日子以来,我出于旧习惯做了两次。
它允许applescript模拟鼠标和键盘输入以及一堆其他的东西。
如果脚本挂起直到在“更新而不注册应用程序”行超时,则步骤 1 尚未完成(或已撤消)。我刚刚发现了这一点。
我想我发现了一个小故障 - AppleScript 中有一个弹出,这是在您尝试运行 chmod 之前完成的。 chmod 将失败,因为磁盘现在被弹出。【参考方案2】:
有一个名为create-dmg 的小 Bash 脚本可以构建具有自定义背景、自定义图标位置和卷名的精美 DMG。
我多年前为我当时经营的公司构建了它;从那时起,它依靠其他人的贡献得以生存,并且据报道运作良好。
还有node-appdmg,它看起来像是基于 Node.js 的更现代和更积极的努力;也来看看吧。
【讨论】:
您的 bash 脚本的链接已损坏。你能把它放在github.com上吗?谢谢 create-dmg NOT 很好地定位图标。如果您需要此功能,请不要使用它。 @laike9m 距离我上次接触它已经 5 年多了。我真的不再认为 DMG 是分发 Mac 软件的最佳方式。所以它依靠其他人的贡献得以生存——希望有人也能解决图标问题。 @Zmey 作为用户,到目前为止,我更喜欢 zip 文件。如果应用程序检测到它从~/Downloads
运行,则自动复制到/Applications
的奖励积分。另见this old article by John Gruber。
@Zmey 另见this article with a screenshot of the UI involved。【参考方案3】:
不要去那里。作为一名长期的 Mac 开发人员,我可以向您保证,没有任何解决方案能够真正奏效。我尝试了很多解决方案,但它们都不是很好。我认为问题在于 Apple 并没有真正记录必要数据的元数据格式。
这是我长期以来的做法,非常成功:
创建一个新的 DMG,可写(!),大到足以容纳预期的二进制文件和自述文件等额外文件(稀疏可能有效)。
安装 DMG 并在 Finder 中手动为其设置布局,或使用适合您的任何工具进行布局。背景图像通常是我们放入 DMG 上隐藏文件夹(“.something”)中的图像。将您的应用程序的副本放在那里(任何版本,甚至过时的版本都可以)。再次复制您想要的其他文件(别名、自述文件等),过时的版本就可以了。确保图标具有正确的大小和位置(IOW,按照您想要的方式布局 DMG)。
再次卸载 DMG,所有设置现在应该已存储。
编写一个创建 DMG 脚本,其工作原理如下:
这种方法听起来可能不是最理想的,但相信我,它在实践中非常有效。您甚至可以将原始 DMG(DMG 模板)置于版本控制之下(例如 SVN),因此如果您不小心更改/破坏了它,您可以返回到它仍然可以的版本。您可以将 DMG 模板与属于 DMG 的所有其他文件(自述文件、URL 文件、背景图像)一起添加到您的 Xcode 项目中,都在版本控制下,然后创建一个目标(例如名为“Create DMG”的外部目标)并在那里运行上面的 DMG 脚本并将您的旧主目标添加为依赖目标。您可以在脚本中使用 $SRCROOT 访问 Xcode 树中的文件(始终是产品的源根目录),并且可以使用 $BUILT_PRODUCTS_DIR 访问构建产品(始终是 Xcode 创建构建结果的目录) .
结果:实际上 Xcode 可以在构建结束时生成 DMG。准备发布的 DMG。您不仅可以通过这种方式非常轻松地创建发布 DMG,而且您实际上可以在自动化过程中(如果您愿意,可以在无头服务器上)使用命令行中的 xcodebuild(例如自动夜间构建)来执行此操作。
【讨论】:
我已经放弃了这样做的想法,原因有几个。以下是其中两个:安装程序的内容会因产品而异,我们只想依赖安装在打包机器上的软件和脚本——添加新产品的单一、最小的手动例程。 这与我们的情况相同。我们有十几种产品;每个都有完全不同的DMG。为每个产品创建一个模板 DMG 是一次性任务,需要几分钟时间。 “安装程序”是什么意思? PKG/MPKG 安装包? 这不是同一个场景。我们经常在短时间内添加产品。最小的手动例程意味着运行一个脚本,为产品命名和一些其他属性。除此之外,还有其他原因使我们决定不使用这种解决方案。 我们将打包过程与构建过程分开,因为它是由不同的人在不同的时间完成的。打包过程还为 Windows、Windows CE、Symbian、AIX、Linux 和 Solaris 创建安装程序。 您可能指的是 hdiutil,而不是 hdutil。【参考方案4】:通过提供此答案更新此问题。
appdmg
是一个简单易用的开源命令行程序,可从简单的 json 规范创建 dmg 文件。看看官网的readme:
https://github.com/LinusU/node-appdmg
快速示例:
安装 appdmg
npm install -g appdmg
写一个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"
]
运行程序
appdmg spec.json test.dmg
(免责声明。我是 appdmg 的创建者)
【讨论】:
简单有效。唯一的缺点是需要安装 npm @Creator:你能不能让它像这个提供GUI一样前进,而不必拖放? s.sudre.free.fr/Software/Packages/about.html 如果 .app 文件与 json 文件不在同一个文件夹中,这不起作用,当您在“路径”中指定相对路径时,会出现“找不到文件”错误 @Joey,如果它不适合你,你能在 Github 存储库上打开一个问题吗? @Joey:不需要在同一个文件夹中,我有后台,应用程序都在不同的路径中,只需将相对路径传递为../../../ABC【参考方案5】:对于那些对此主题感兴趣的人,我应该提到我是如何创建 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
【讨论】:
没关系,但并不能满足实际需要(背景图片、文件夹中项目的定位等) 创建了 DMG,但我必须再次使用 CMD 运行我的脚本(.sh),我需要它在创建 DMG 后自动运行 sh【参考方案6】:我的应用程序DropDMG 是一种创建具有背景图片、图标布局、自定义卷图标和软件许可协议的磁盘图像的简单方法。它可以通过“dropdmg”命令行工具或 AppleScript 从构建系统进行控制。如果需要,图片和许可证 RTF 文件可以存储在您的版本控制系统下。
【讨论】:
我的团队在 Jenkins CI 构建服务器上完美自动地工作,完成背景,拖到应用程序别名。跑到 DropDMG 制作磁盘映像。 好应用,试用期结束后我打算购买。 看起来不错,但似乎没有调整窗口大小的选项。 @avi DropDMG 会根据您设置的背景图片自动调整窗口大小(如果需要,也可以将inset 调整为该图片)。 太好了,谢谢!是否可以在没有背景图像的情况下调整大小?【参考方案7】:为了创建漂亮的 DMG,您现在可以使用一些编写良好的开源代码:
create-dmg node-appdmg dmgbuild【讨论】:
可能是他们移动了它。您可以使用 create-dmg 和 node-appdmg。我正在使用 create-dmg。很好。 @PamelaCook-LightBeCorp 如果您仍然感兴趣。 dmgbuild 的链接已修复。【参考方案8】:我发现这个很棒的 mac 应用程序可以自动化这个过程 - http://www.araelium.com/dmgcanvas/ 如果你正在为你的 mac 应用程序创建 dmg 安装程序,你必须看看
【讨论】:
请注意,这不是一个免费程序,所以它不适合很多环境。【参考方案9】:如果您想设置自定义音量图标,请使用以下命令
/*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,所以很难测试这些东西是否可以在其他机器上运行。 “你的路径”是 DMG 名称。 (/Volumes/dmgName) 你应该复制icns文件。 cp "/Volumes/customIcon.icns" "/Volumes/dmgName/.VolumeIcon.icns"【参考方案10】:我终于在我自己的项目(恰好在 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 ENDprintf \"%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/ 目录中!
【讨论】:
它正在我的项目上创建空白磁盘映像。任何建议。 Shell 脚本部分只能工作,但是如何在 Build Phase 下的 RunScript 中添加带有 Shell Script 的 Apple 脚本显示错误,每个 Apple 脚本语句都找不到符号。【参考方案11】:.DS_Store 文件将 Windows 设置存储在 Mac 中。窗口设置包括图标布局、窗口背景、窗口大小等。为挂载图像创建窗口时需要.DS_Store文件,以保留文件排列和窗口背景。
创建 .DS_Store 文件后,您可以将其复制到您创建的安装程序 (DMG)。
【讨论】:
但是首先将背景图像添加到 dmg 中,将其命名为 .background.png,然后使用 Cmd-J 将该 (!) 图像添加到背景中。【参考方案12】:我还需要使用命令行方法“在脚本中以编程方式”进行打包和 dmg 创建。到目前为止,我找到的最佳答案来自 Adium 项目的发布构建框架(参见 R1)。有一个自定义脚本 (AdiumApplescriptRunner) 可以让您避免 OSX WindowsServer GUI 交互。 “osascript applescript.scpt”方法要求您以 builder 身份登录并从命令行 vt100 会话运行 dmg 创建。
OSX 包管理系统与其他可以轻松系统地完成这项任务的 Unixen 相比,并没有那么先进。
R1:http://hg.adium.im/adium-1.4/file/00d944a3ef16/Release
【讨论】:
【参考方案13】:我刚刚编写了一个新的(友好的)命令行实用程序来执行此操作。它不依赖于 Finder/AppleScript 或任何(已弃用)Alias Manager API,并且易于配置和使用。
不管怎样,有兴趣的可以find it on PyPi;文档是available on Read The Docs。
【讨论】:
【参考方案14】:这些答案太复杂了,时代变了。以下在 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
创建带有图标(.icns 类型)的只读 DMG
#!/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==1print$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
如果需要进行其他操作,最简单的方法是制作 SRC_DIR 的临时副本并在创建 DMG 之前对其应用更改。
【讨论】:
这个答案并没有在之前写的内容中添加任何内容,也没有回答原始问题(这不仅仅是在 dmg 中放置一个图标,或者如何对其进行签名;问题是关于以编程方式将图形和定位图标添加到 dmg)。【参考方案15】:我用dmgbuild。
安装:pip3 install dmgbuild
安装音量
创建设置文件:
"title": "NAME",
"background": "YOUR_BACKGROUND.png",
"format": "UDZO",
"compression-level": 9,
"window": "position": "x": 100, "y": 100 ,
"size": "width": 640, "height": 300 ,
"contents": [
"x": 140, "y": 165, "type": "file", "path": "/Volumes/YOUR_VOLUME_NAME/YOUR_APP.app" ,
"x": 480, "y": 165, "type": "link", "path": "/Applications"
]
宽度值是背景的宽度。
高度值应该是窗口栏的背景高度+20。
在终端中:dmgbuild -s settings.json "YOUR_VOLUME_NAME" output.dmg
【讨论】:
以上是关于如何使用命令行工具为 Mac OS X 创建漂亮的 DMG?的主要内容,如果未能解决你的问题,请参考以下文章
Mac OS X 命令行登录 Parallels Desktop 虚拟机下的Linux
安装了 Xcode 命令行工具的 Mac OS X 中的 clang-format 和 clang-format.py 在哪里?