¿Cómo puedo crear un DMG atractivo para Mac OS X usando herramientas de línea de comandos?


Necesito crear un buen instalador para una aplicación Mac. Quiero que sea una imagen de disco (DMG), con un tamaño predefinido, diseño e imagen de fondo.

Necesito hacer esto programáticamente en un script, para ser integrado en un sistema de compilación existente (más bien un sistema de paquetes en realidad, ya que solo crea instaladores. Las construcciones se hacen por separado).

Ya tengo la creación de DMG hecha usando "hdiutil", lo que aún no he descubierto es cómo hacer un diseño de icono y especificar un mapa de bits de fondo.

Author: Ludvig A Norin, 2008-09-19

14 answers

Después de mucha investigación, se me ocurrió esta respuesta, y por la presente la pongo aquí como una respuesta para mi propia pregunta, como referencia:

  1. Asegúrese de que la opción" Habilitar acceso para dispositivos de asistencia " esté marcada en Preferencias del sistema>>Acceso universal. Es necesario para que el AppleScript funcione. Es posible que tenga que reiniciar después de este cambio (de lo contrario no funciona en Mac OS X Server 10.4).

  2. Cree un DMG R / W. Debe ser más grande de lo que será el resultado. En este por ejemplo, la variable bash "size" contiene el tamaño en Kb y el contenido de la carpeta en la variable bash "source" se copiará en el 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. Monte la imagen de disco y almacene el nombre del dispositivo (es posible que desee usar sleep durante unos segundos después de esta operación):

    device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \
             egrep '^/dev/' | sed 1q | awk '{print $1}')
    
  4. Almacene la imagen de fondo (en formato PNG) en una carpeta llamada ".background "en el DMG, y almacena su nombre en la variable" backgroundPictureName".

  5. Utilice AppleScript para establecer los estilos visuales (nombre de.app debe estar en la variable bash "ApplicationName", use variables para las otras propiedades según sea necesario):

    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. Termine el DMG configurando los permisos correctamente, comprimiéndolo y liberándolo:

    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 
    

En Snow Leopard, el applescript anterior no establecerá la posición del icono correctamente - parece ser un error de Snow Leopard. Una solución es simplemente llamar a cerrar / abrir después de configurar el iconos, es decir:

..
set position of item "'${applicationName}'" of container window to {100, 100}
set position of item "Applications" of container window to {375, 100}
close
open
 188
Author: Ludvig A Norin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-14 10:56:37

Hay un pequeño script Bash llamado create-dmg que construye DMG de lujo con fondos personalizados, posicionamiento de iconos personalizados y nombre de volumen.

Lo construí hace muchos años para la compañía que dirigía en ese momento; sobrevive gracias a la contribución de otras personas desde entonces, y según los informes, funciona bien.

También hay node-appdmg que parece un esfuerzo más moderno y activo basado en el nodo.js; échale un vistazo también.

 53
Author: Andrey Tarantsov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-10 11:51:39

No vayas allí. Como desarrollador de Mac a largo plazo, puedo asegurarle que ninguna solución funciona realmente bien. He intentado tantas soluciones, pero no todas son demasiado buenas. Creo que el problema es que Apple realmente no documenta el formato de metadatos para los datos necesarios.

Así es como lo estoy haciendo durante mucho tiempo, con mucho éxito:

  1. Crear un nuevo DMG, escribible (!), lo suficientemente grande como para contener los archivos binarios y adicionales esperados como readme (sparse might trabajo).

  2. Montar el DMG y darle un diseño manualmente en Finder o con las herramientas que más le convenga para hacer eso (ver FileStorm enlace en la parte inferior para una buena herramienta). La imagen de fondo suele ser una imagen que ponemos en una carpeta oculta (".algo") en el DMG. Coloque una copia de su aplicación allí(cualquier versión, incluso una obsoleta servirá). Copie otros archivos(alias, readme, etc.) usted quiere allí, una vez más, versiones obsoletas va a hacer muy bien. Asegúrese de que los iconos tienen los tamaños adecuados y posiciones (IOW, diseño de la DMG de la manera que desea que sea).

  3. Desmontar el DMG de nuevo, todos los ajustes deben ser almacenados por ahora.

  4. Escribe un script para crear DMG, que funciona de la siguiente manera:

    • Copia el DMG, por lo que el original nunca se vuelve a tocar.
    • monta la copia.
    • Reemplaza todos los archivos con los más actualizados (por ejemplo, la última aplicación después de la compilación). Simplemente puede usar mv o ídem para eso en la línea de comandos. Tenga en cuenta que cuando reemplace un archivo como ese, el icono se mantendrá igual, la posición se mantendrá igual, todo excepto el contenido del archivo (o directorio) se mantendrá igual (al menos con ditto, que generalmente usamos para esa tarea). Por supuesto, también puede reemplazar la imagen de fondo con otra (solo asegúrese de que tenga las mismas dimensiones).
    • Después de reemplazar los archivos, haga que el script desmonte la copia DMG de nuevo.
    • Finalmente llamar hdiutil para convertir el escribible, a un comprimido (y tal no escribible) DMG.

Este método puede no sonar óptimo, pero confía en mí, funciona muy bien en la práctica. Puede poner el DMG original (plantilla DMG) incluso bajo control de versión (por ejemplo, SVN), por lo que si alguna vez lo cambia/destruye accidentalmente, puede volver a una revisión donde todavía estaba bien. Puede agregar la plantilla DMG a su proyecto Xcode, junto con todos los demás archivos que pertenecen al DMG (readme, archivo URL, imagen de fondo), todo bajo control de versión y luego cree un objetivo (por ejemplo, un objetivo externo llamado "Create DMG") y ejecute el script DMG de arriba y agregue su antiguo objetivo principal como objetivo dependiente. Puede acceder a los archivos en el árbol de Xcode usando ${SRCROOT} en el script (siempre es la raíz de origen de su producto) y puede acceder a los productos de compilación usando ${BUILT_PRODUCTS_DIR} (siempre es el directorio donde Xcode crea los resultados de compilación).

Resultado: En realidad Xcode puede producir el DMG al final de la compilación. Un DMG que está listo lanzar. No solo puede crear un DMG relase de esa manera bastante fácil, sino que en realidad puede hacerlo en un proceso automatizado (en un servidor sin cabeza si lo desea), utilizando xcodebuild desde la línea de comandos (compilaciones nocturnas automatizadas, por ejemplo).

En cuanto al diseño inicial de la plantilla, FileStorm es una buena herramienta para hacerlo. Es comercial, pero muy potente y fácil de usar. La versión normal es menos de $20, por lo que es realmente asequible. Tal vez uno puede automatizar FileStorm para crear un DMG (por ejemplo, a través de AppleScript), nunca lo intentó, pero una vez que haya encontrado la plantilla perfecta DMG, es realmente fácil actualizarla para cada versión.

 37
Author: Mecki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-18 13:30:45

Actualizando esta pregunta proporcionando esta respuesta.

appdmg es un programa de línea de comandos simple, fácil de usar y de código abierto que crea archivos dmg a partir de una simple especificación json. Echa un vistazo al readme en el sitio web oficial:

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

Ejemplo rápido:

  1. Instalar appdmg

    npm install -g appdmg
    
  2. Escribir un archivo 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. Ejecutar programa

    appdmg spec.json test.dmg
    

(descargo de responsabilidad. Soy el creador de appdmg)

 24
Author: Linus Unnebäck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-23 15:12:07

Para aquellos de ustedes que están interesados en este tema, debo mencionar cómo creo el DMG:

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

Donde

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
 22
Author: Ludvig A. Norin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 21:13:35

Mi aplicación, DropDMG, es una manera fácil de crear imágenes de disco con imágenes de fondo, diseños de iconos, iconos de volumen personalizados y acuerdos de licencia de software. Se puede controlar desde un sistema de compilación a través de la herramienta de línea de comandos" dropdmg " o AppleScript. Si lo desea, los archivos RTF de imagen y licencia se pueden almacenar bajo su sistema de control de versiones.

 14
Author: Michael Tsai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-30 15:38:26

Encontré esta gran aplicación para mac para automatizar el proceso - http://www.araelium.com/dmgcanvas / debe echar un vistazo si está creando dmg installer para su aplicación mac

 5
Author: Saurabh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-22 14:05:40

Si desea configurar el icono de volumen personalizado, use el comando siguiente

/*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

Ahora crea dmg de lectura/escritura

/*to set custom icon attribute*/
SetFile -a C /Volumes/dmgName
 4
Author: Parag Bafna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-15 04:43:09

.Archivos DS_Store almacena la configuración de Windows en Mac. La configuración de Windows incluye el diseño de los iconos, el fondo de la ventana, el tamaño de la ventana, etc. El .El archivo DS_Store es necesario para crear la ventana de imágenes montadas para preservar la disposición de los archivos y el fondo de windows.

Una vez que lo haya hecho .Archivo DS_Store creado, solo puede copiarlo a su instalador creado (DMG).

 2
Author: hor10zs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-14 08:09:40

También necesito usar el enfoque de línea de comandos para hacer el empaquetado y la creación de dmg "programáticamente en un script". La mejor respuesta que he encontrado hasta ahora es de Adium project' Release building framework (Ver R1). Hay un script personalizado (AdiumApplescriptRunner) que le permite evitar la interacción con la GUI de OSX WindowsServer. "osascript applescript.el enfoque "scpt" requiere que inicie sesión como constructor y ejecute la creación de dmg desde una sesión vt100 de línea de comandos.

El sistema de gestión de paquetes OSX no es así avanzado en comparación con otros Unixen que pueden hacer esta tarea fácil y sistemáticamente.

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

 2
Author: T.J. Yang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-09 12:55:20

Finalmente conseguí esto trabajando en mi propio proyecto (que pasa a estar en Xcode). Agregar estos 3 scripts a su fase de compilación creará automáticamente una imagen de disco para su producto que sea agradable y ordenada. Todo lo que tiene que hacer es construir su proyecto y el DMG estará esperando en su carpeta de productos.

Script 1 (Crear Imagen de Disco Temporal):

#!/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):

#!/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

La medición anterior para el trabajo de ventana para mi proyecto específicamente debido al tamaño de mi foto de fondo y la resolución del icono; es posible que tenga que modificar estos valores para su propio proyecto.

Script 3 (Hacer Script de Imagen de Disco Final):

#!/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"

Asegúrese de que los archivos de imagen que está utilizando están en el directorio PROJ PROJECT_DIR /NAME PROJECT_NAME/!

 2
Author: P.M.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-24 21:13:55

Para crear un DMG atractivo, ahora puede usar algunas fuentes abiertas bien escritas:

 2
Author: Anni S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-27 11:31:18

Estas respuestas son demasiado complicadas y los tiempos han cambiado. Lo siguiente funciona en 10.9 muy bien, los permisos son correctos y se ve bien.

Crear un DMG de solo lectura desde un directorio

#!/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

Crear DMG de solo lectura con un icono (.tipo 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

Si algo más tiene que suceder, lo más fácil es hacer una copia temporal del SRC_DIR y aplicar cambios a eso antes de crear un DMG.

 1
Author: Barry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-02 10:54:28

Acabo de escribir una nueva utilidad de línea de comandos (amigable) para hacer esto. No se basa en Finder / AppleScript ni en ninguna de las API (obsoletas) de Alias Manager, y es fácil de configurar y usar.

De todos modos, cualquiera que esté interesado puede encontrarlo en PyPI; la documentación está disponible en Read The Docs.

 1
Author: alastair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-17 10:35:14