macos 如何使用命令行工具为 Mac OS X 创建漂亮的 DMG?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/96882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I create a nice-looking DMG for Mac OS X using command-line tools?
提问by Ludvig A. Norin
I need to create a nice installer for a Mac application. I want it to be a disk image (DMG), with a predefined size, layout and background image.
我需要为 Mac 应用程序创建一个不错的安装程序。我希望它是一个磁盘映像 (DMG),具有预定义的大小、布局和背景图像。
I need to do this programmatically in a script, to be integrated in an existing build system (more of a pack system really, since it only create installers. The builds are done separately).
我需要在脚本中以编程方式执行此操作,以集成到现有构建系统中(实际上更像是一个包系统,因为它只创建安装程序。构建是单独完成的)。
I already have the DMG creation done using "hdiutil", what I haven't found out yet is how to make an icon layout and specify a background bitmap.
我已经使用“hdiutil”完成了 DMG 创建,我还没有发现如何制作图标布局和指定背景位图。
采纳答案by Ludvig A. Norin
After lots of research, I've come up with this answer, and I'm hereby putting it here as an answer for my own question, for reference:
经过大量的研究,我想出了这个答案,我把它放在这里作为我自己问题的答案,以供参考:
Make sure that "Enable access for assistive devices" is checked in System Preferences>>Universal Access. It is required for the AppleScript to work. You may have to reboot after this change (it doesn't work otherwise on Mac OS X Server 10.4).
Create a R/W DMG. It must be larger than the result will be. In this example, the bash variable "size" contains the size in Kb and the contents of the folder in the "source" bash variable will be copied into the 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
Mount the disk image, and store the device name (you might want to use sleep for a few seconds after this operation):
device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \ egrep '^/dev/' | sed 1q | awk '{print }')
Store the background picture (in PNG format) in a folder called ".background" in the DMG, and store its name in the "backgroundPictureName" variable.
Use AppleScript to set the visual styles (name of .app must be in bash variable "applicationName", use variables for the other properties as needed):
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
Finialize the DMG by setting permissions properly, compressing and releasing it:
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
确保在系统偏好设置>>通用访问中选中“启用辅助设备访问”。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 ${size}k pack.temp.dmg
挂载磁盘映像,并存储设备名称(您可能希望在此操作后使用 sleep 几秒钟):
device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \ egrep '^/dev/' | sed 1q | awk '{print }')
将背景图片(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
On Snow Leopard, the above applescript will not set the icon position correctly - it seems to be a Snow Leopard bug. One workaround is to simply call close/open after setting the icons, i.e.:
在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
回答by Andrey Tarantsov
There's a little Bash script called create-dmgthat builds fancy DMGs with custom backgrounds, custom icon positioning and volume name.
有一个名为create-dmg的小 Bash 脚本,它可以构建具有自定义背景、自定义图标定位和卷名称的精美 DMG。
I've built it many years ago for the company that I ran at the time; it survives on other people's contribution since then, and reportedly works well.
多年前,我为我当时经营的公司建立了它;从那时起,它依靠其他人的贡献而生存,并且据说运行良好。
There's also node-appdmgwhich looks like a more modern and active effort based on Node.js; check it out as well.
还有node-appdmg,它看起来像是基于 Node.js 的更现代和更积极的努力;也检查一下。
回答by Mecki
Don't go there. As a long term Mac developer, I can assure you, no solution is really working well. I tried so many solutions, but they are all not too good. I think the problem is that Apple does not really document the meta data format for the necessary data.
不要去那里。作为一名长期的 Mac 开发人员,我可以向您保证,没有任何解决方案是真正有效的。我尝试了很多解决方案,但都不太好。我认为问题在于 Apple 并没有真正记录必要数据的元数据格式。
Here's how I'm doing it for a long time, very successfully:
这是我做了很长时间的方法,非常成功:
Create a new DMG, writeable(!), big enough to hold the expected binary and extra files like readme (sparse might work).
Mount the DMG and give it a layout manually in Finder or with whatever tools suits you for doing that (see FileStorm link at the bottom for a good tool). The background image is usually an image we put into a hidden folder (".something") on the DMG. Put a copy of your app there (any version, even outdated one will do). Copy other files (aliases, readme, etc.) you want there, again, outdated versions will do just fine. Make sure icons have the right sizes and positions (IOW, layout the DMG the way you want it to be).
Unmount the DMG again, all settings should be stored by now.
Write a create DMG script, that works as follows:
- It copies the DMG, so the original one is never touched again.
- It mounts the copy.
- It replaces all files with the most up to date ones (e.g. latest app after build). You can simply use mvor dittofor that on command line. Note, when you replace a file like that, the icon will stay the same, the position will stay the same, everything but the file (or directory) content stays the same (at least with ditto, which we usually use for that task). You can of course also replace the background image with another one (just make sure it has the same dimensions).
- After replacing the files, make the script unmount the DMG copy again.
- Finally call hdiutil to convert the writable, to a compressed (and such not writable) DMG.
创建一个新的 DMG,可写(!),大到足以容纳预期的二进制文件和额外的文件,如自述文件(稀疏可能有效)。
安装 DMG 并在 Finder 中手动给它一个布局或使用任何适合您的工具(请参阅底部的 FileStorm 链接以获得一个好的工具)。背景图像通常是我们放入 DMG 上隐藏文件夹(“.something”)中的图像。将您的应用程序的副本放在那里(任何版本,甚至过时的版本都可以)。复制你想要的其他文件(别名、自述文件等),同样,过时的版本也可以。确保图标具有正确的大小和位置(IOW,按照您希望的方式布置 DMG)。
再次卸载 DMG,现在应该存储所有设置。
编写一个创建 DMG 脚本,其工作方式如下:
- 它复制了 DMG,因此再也不会触及原始的 DMG。
- 它安装副本。
- 它用最新的文件(例如构建后的最新应用程序)替换所有文件。您可以简单地在命令行上使用mv或同上。请注意,当您像这样替换文件时,图标将保持不变,位置将保持不变,除文件(或目录)内容外的所有内容都保持不变(至少对于我们通常用于该任务的同上) . 您当然也可以用另一个替换背景图像(只需确保它具有相同的尺寸)。
- 替换文件后,使脚本再次卸载 DMG 副本。
- 最后调用 hdiutil 将可写的转换为压缩的(不可写的)DMG。
This method may not sound optimal, but trust me, it works really well in practice. You can put the original DMG (DMG template) even under version control (e.g. SVN), so if you ever accidentally change/destroy it, you can just go back to a revision where it was still okay. You can add the DMG template to your Xcode project, together with all other files that belong onto the DMG (readme, URL file, background image), all under version control and then create a target (e.g. external target named "Create DMG") and there run the DMG script of above and add your old main target as dependent target. You can access files in the Xcode tree using ${SRCROOT} in the script (is always the source root of your product) and you can access build products by using ${BUILT_PRODUCTS_DIR} (is always the directory where Xcode creates the build results).
这种方法听起来可能不是最优的,但相信我,它在实践中非常有效。您甚至可以将原始 DMG(DMG 模板)置于版本控制(例如 SVN)之下,因此如果您不小心更改/破坏了它,您可以返回到它仍然没问题的修订版。您可以将 DMG 模板与属于 DMG 的所有其他文件(自述文件、URL 文件、背景图像)一起添加到您的 Xcode 项目中,所有这些都在版本控制之下,然后创建一个目标(例如名为“Create DMG”的外部目标)然后运行上面的 DMG 脚本并将旧的主要目标添加为依赖目标。您可以使用脚本中的 ${SRCROOT} 访问 Xcode 树中的文件(始终是您产品的源根目录),您可以使用 ${BUILT_PRODUCTS_DIR} 访问构建产品(始终是 Xcode 创建构建结果的目录) .
Result: Actually Xcode can produce the DMG at the end of the build. A DMG that is ready to release. Not only you can create a relase DMG pretty easy that way, you can actually do so in an automated process (on a headless server if you like), using xcodebuild from command line (automated nightly builds for example).
结果:实际上 Xcode 可以在构建结束时生成 DMG。准备发布的 DMG。您不仅可以通过这种方式非常轻松地创建 relase DMG,而且实际上可以在自动化过程中(如果您愿意,可以在无头服务器上)使用命令行中的 xcodebuild(例如,自动夜间构建)。
Regarding the initial layout of the template, FileStormis a good tool for doing it. It is commercial, but very powerful and easy to use. The normal version is less than $20, so it is really affordable. Maybe one can automate FileStorm to create a DMG (e.g. via AppleScript), never tried that, but once you have found the perfect template DMG, it's really easy to update it for every release.
关于模板的初始布局,FileStorm是一个很好的工具。它是商业的,但非常强大且易于使用。普通版不到20美元,所以真的很实惠。也许有人可以自动化 FileStorm 来创建 DMG(例如通过 AppleScript),从来没有尝试过,但是一旦你找到了完美的 DMG 模板,就很容易为每个版本更新它。
回答by Linus Unneb?ck
Bringing this question up to date by providing this answer.
通过提供这个答案来更新这个问题。
appdmg
is a simple, easy-to-use, open-source command line program that creates dmg-files from a simple json specification. Take a look at the readme at the official website:
appdmg
是一个简单、易于使用、开源的命令行程序,它根据简单的 json 规范创建 dmg 文件。看一下官网的readme:
https://github.com/LinusU/node-appdmg
https://github.com/LinusU/node-appdmg
Quick example:
快速示例:
Install appdmg
npm install -g appdmg
Write a json file (
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" } ] }
Run program
appdmg spec.json test.dmg
安装应用程序
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
(disclaimer. I'm the creator of appdmg)
(免责声明。我是appdmg的创建者)
回答by Ludvig A. Norin
For those of you that are interested in this topic, I should mention how I create the DMG:
对于那些对这个主题感兴趣的人,我应该提到我是如何创建 DMG 的:
hdiutil create XXX.dmg -volname "YYY" -fs HFS+ -srcfolder "ZZZ"
where
在哪里
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
回答by Michael Tsai
My app, DropDMG, is an easy way to create disk images with background pictures, icon layouts, custom volume icons, and software license agreements. It can be controlled from a build system via the "dropdmg" command-line tool or AppleScript. If desired, the picture and license RTF files can be stored under your version control system.
我的应用DropDMG是一种创建带有背景图片、图标布局、自定义卷图标和软件许可协议的磁盘映像的简单方法。它可以通过“dropdmg”命令行工具或 AppleScript 从构建系统进行控制。如果需要,图片和许可证 RTF 文件可以存储在您的版本控制系统下。
回答by Saurabh
I found this great mac app to automate the process - http://www.araelium.com/dmgcanvas/you must have a look if you are creating dmg installer for your mac app
我发现了这个很棒的 mac 应用程序来自动化这个过程 - http://www.araelium.com/dmgcanvas/如果你正在为你的 mac 应用程序创建 dmg 安装程序,你必须看看
回答by Parag Bafna
If you want to set custom volume icon then use below command
如果要设置自定义音量图标,请使用以下命令
/*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
Now create read/write dmg
现在创建读/写 dmg
/*to set custom icon attribute*/
SetFile -a C /Volumes/dmgName
回答by P.M.
I finally got this working in my own project (which happens to be in Xcode). Adding these 3 scripts to your build phase will automatically create a Disk Image for your product that is nice and neat. All you have to do is build your project and the DMG will be waiting in your products folder.
我终于在我自己的项目中得到了这个(恰好在 Xcode 中)。将这 3 个脚本添加到您的构建阶段将自动为您的产品创建一个漂亮整洁的磁盘映像。您所要做的就是构建您的项目,DMG 将在您的产品文件夹中等待。
Script 1 (Create Temp Disk Image):
脚本 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
Script 2 (Set Window Properties Script):
脚本 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=; height=} /Retina/{scale=( == \"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
The above measurement for the window work for my project specifically due to the size of my background pic and icon resolution; you may need to modify these values for your own project.
由于我的背景图片和图标分辨率的大小,上述窗口测量适用于我的项目;您可能需要为您自己的项目修改这些值。
Script 3 (Make Final Disk Image Script):
脚本 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"
Make sure the image files you are using are in the $PROJECT_DIR/$PROJECT_NAME/ directory!
确保您使用的图像文件位于 $PROJECT_DIR/$PROJECT_NAME/ 目录中!
回答by Anni S
For creating a nice looking DMG, you can now just use some well written open sources:
为了创建一个漂亮的 DMG,你现在可以使用一些写得很好的开源: