Come posso creare un DMG di bell'aspetto per Mac OS X usando gli strumenti da riga di comando?


212

Devo creare un bel programma di installazione per un'applicazione Mac. Voglio che sia un'immagine del disco (DMG), con dimensioni, layout e immagine di sfondo predefiniti.

Devo farlo a livello di codice in uno script, per essere integrato in un sistema di build esistente (in realtà più di un sistema pack, poiché crea solo programmi di installazione. Le build vengono eseguite separatamente).

Ho già fatto la creazione DMG usando "hdiutil", quello che non ho ancora scoperto è come creare un layout di icona e specificare una bitmap di sfondo.


1
Questo non è qualcosa per Ask Different?
Lenar Hoyt,

Risposte:


199

Dopo molte ricerche, ho trovato questa risposta e la inserisco qui come risposta per la mia domanda, come riferimento:

  1. Assicurati che "Abilita accesso per dispositivi di assistenza" sia selezionato in Preferenze di Sistema >> Accesso universale. È necessario per il funzionamento di AppleScript. Potrebbe essere necessario riavviare dopo questa modifica (altrimenti non funzionerà su Mac OS X Server 10.4).

  2. Crea un DMG R / W. Deve essere maggiore del risultato. In questo esempio, la variabile "dimensione" bash contiene la dimensione in Kb e il contenuto della cartella nella variabile bash "sorgente" verrà copiato nel 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. Montare l'immagine del disco e memorizzare il nome del dispositivo (è possibile che si desideri utilizzare la sospensione per alcuni secondi dopo questa operazione):

    device=$(hdiutil attach -readwrite -noverify -noautoopen "pack.temp.dmg" | \
             egrep '^/dev/' | sed 1q | awk '{print $1}')
    
  4. Memorizza l'immagine di sfondo (in formato PNG) in una cartella denominata ".background" nel DMG e memorizza il suo nome nella variabile "backgroundPictureName".

  5. Usa AppleScript per impostare gli stili di visualizzazione (il nome di .app deve essere nella variabile bash "applicationName", usa le variabili per le altre proprietà secondo necessità):

    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. Finializza il DMG impostando correttamente le autorizzazioni, comprimendolo e rilasciandolo:

    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 
    

Su Snow Leopard, il suddetto script di apple non imposterà correttamente la posizione dell'icona - sembra essere un bug di Snow Leopard. Una soluzione alternativa consiste nel chiamare close / open dopo aver impostato le icone, ovvero:

..
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
Eccellente. Due domande a riguardo: 1. Si consiglia sleepdopo aver montato l'immagine. Per quanto? Non è possibile attendere in modo deterministico il completamento del processo? Lo stesso per delay 5AppleScript. Sono sempre diffidente nei confronti di tali tempi di attesa arbitrari, avendo avuto una brutta esperienza con loro. 2. Nel passaggio 6 chiami syncdue volte: perché?
Konrad Rudolph,

Non ho trovato alcun modo per attendere deterministicamente il completamento del comando "aggiorna senza registrare le applicazioni". Non sono sicuro che dopo "hdiutil attach" sia necessario dormire, dovrai controllare la documentazione (man hdiutil). La sincronizzazione dovrebbe essere necessaria solo per essere chiamata una volta, lo faccio due volte per vecchia abitudine dai bei vecchi tempi di SunOS.
Ludvig A. Norin,

1
Permette a applecript di simulare l'input da mouse e tastiera e molte altre cose.
Ludvig A. Norin,

1
Se lo script si blocca fino al timeout nella riga "aggiorna senza registrare le applicazioni", il passaggio 1 non è stato eseguito (o non è stato annullato). L'ho appena scoperto nel modo più duro.
Jay Maynard K5ZC

Penso di aver trovato un piccolo difetto: c'è un espulsione in AppleScript, che viene fatto prima di provare a eseguire chmod. chmod fallirà perché il disco è ora espulso.
Trejkaz,

56

C'è un piccolo script di Bash chiamato create-dmg che crea fantastici DMG con sfondi personalizzati, posizionamento personalizzato delle icone e nome del volume.

L'ho costruito molti anni fa per l'azienda che gestivo in quel momento; da allora sopravvive con il contributo di altre persone e, a quanto si dice, funziona bene.

C'è anche node-appdmg che sembra uno sforzo più moderno e attivo basato su Node.js; controlla pure.


7
Il link al tuo script bash è interrotto. Puoi metterlo in pratica su github.com? Grazie
dquimper il

create-dmg NON posiziona bene l'icona. Se hai bisogno di questa funzione, non usarla.
laike9m,

1
@ laike9m Sono passati più di 5 anni dall'ultima volta che l'ho toccato. Non considero più i DMG il modo migliore per distribuire software Mac. Quindi sopravvive grazie al contributo di altri - speriamo che qualcuno capisca anche il problema delle icone.
Andrey Tarantsov,

3
@Zmey Beh, come utente, preferisco di gran lunga i file zip. Punti bonus per la copia automatica /Applicationsse l'app rileva che sta funzionando ~/Downloads. Vedi anche questo vecchio articolo di John Gruber .
Andrey Tarantsov,


37

Non ci andare. Come sviluppatore Mac a lungo termine, posso assicurarti che nessuna soluzione funziona davvero bene. Ho provato così tante soluzioni, ma non sono tutte troppo buone. Penso che il problema sia che Apple non documenta realmente il formato dei metadati per i dati necessari.

Ecco come lo sto facendo da molto tempo, con molto successo:

  1. Crea un nuovo DMG, scrivibile (!), Abbastanza grande da contenere il file binario atteso e file extra come readme (lo sparse potrebbe funzionare).

  2. Montare il DMG e dargli un layout manualmente nel Finder o con qualsiasi strumento adatto a farlo (consultare il link FileStorm in basso per un buon strumento). L'immagine di sfondo è in genere un'immagine che inseriamo in una cartella nascosta (".something") sul DMG. Metti una copia della tua app lì (qualsiasi versione, anche obsoleta, lo farà). Copia altri file (alias, readme, ecc.) Che vuoi lì, ancora una volta, le versioni obsolete andranno bene. Assicurati che le icone abbiano le giuste dimensioni e posizioni (IOW, impagina il DMG nel modo desiderato).

  3. Smonta di nuovo il DMG, ormai tutte le impostazioni dovrebbero essere memorizzate.

  4. Scrivi uno script DMG creato, che funzioni come segue:

    • Copia il DMG, quindi l'originale non viene mai più toccato.
    • Monta la copia.
    • Sostituisce tutti i file con i più aggiornati (ad es. L'ultima app dopo la compilazione). Puoi semplicemente usare mv o idem per quello dalla riga di comando. Nota, quando sostituisci un file del genere, l'icona rimarrà la stessa, la posizione rimarrà la stessa, tutto tranne il contenuto del file (o della directory) rimarrà lo stesso (almeno con idem, che di solito usiamo per quell'attività) . Ovviamente puoi anche sostituire l'immagine di sfondo con un'altra (assicurati solo che abbia le stesse dimensioni).
    • Dopo aver sostituito i file, rendere lo script smontare di nuovo la copia DMG.
    • Chiama infine hdiutil per convertire il DMG comprimibile, in un DMG compresso (e non scrivibile).

Questo metodo potrebbe non sembrare ottimale, ma credetemi, funziona davvero bene nella pratica. Puoi mettere il DMG originale (modello DMG) anche sotto il controllo della versione (ad es. SVN), quindi se lo cambi o lo distruci accidentalmente, puoi semplicemente tornare a una revisione in cui era ancora a posto. Puoi aggiungere il modello DMG al tuo progetto Xcode, insieme a tutti gli altri file che appartengono al DMG (file Leggimi, file URL, immagine di sfondo), tutti sotto controllo della versione e quindi creare un target (es. Target esterno chiamato "Crea DMG") e lì esegui lo script DMG sopra e aggiungi il tuo vecchio target principale come target dipendente. Puoi accedere ai file nell'albero Xcode usando $ {SRCROOT} nello script (è sempre la radice di origine del tuo prodotto) e puoi accedere ai prodotti di compilazione usando $ {BUILT_PRODUCTS_DIR} (è sempre la directory in cui Xcode crea i risultati di compilazione) .

Risultato: in realtà Xcode può produrre il DMG alla fine della build. Un DMG pronto per il rilascio. Non solo puoi creare un DMG relase abbastanza facilmente in questo modo, ma puoi farlo in un processo automatizzato (su un server senza testa, se lo desideri), usando xcodebuild dalla riga di comando (ad esempio build notturne automatizzate).

Per quanto riguarda il layout iniziale del modello, FileStorm è un ottimo strumento per farlo. È commerciale, ma molto potente e facile da usare. La versione normale è inferiore a $ 20, quindi è davvero conveniente. Forse uno può automatizzare FileStorm per creare un DMG (ad es. Tramite AppleScript), mai provato, ma una volta trovato il modello DMG perfetto, è davvero facile aggiornarlo per ogni versione.


3
Ho già scartato l'idea di farlo in questo modo, per diversi motivi. Eccone due: il contenuto degli installatori varierà a seconda del prodotto e vogliamo fare affidamento solo sul software installato sulle macchine pack e sugli script: un'unica routine minima per l'aggiunta di nuovi prodotti.
Ludvig A. Norin,

Questo è lo stesso scenario che abbiamo. Abbiamo più di una dozzina di prodotti; ognuno ha un DMG completamente diverso. La creazione di un modello DMG per prodotto è un'attività unica e richiede un paio di minuti. E cosa intendi per "installer"? Pacchetti di installazione PKG / MPKG?
Mecki

Non è lo stesso scenario. Aggiungiamo prodotti spesso, con breve preavviso. La routine manuale minima significa eseguire uno script che dia al prodotto un nome e alcuni altri attributi. Ci sono anche ragioni al di là di ciò che ci hanno fatto prendere la decisione di non utilizzare quel tipo di soluzione.
Ludvig A. Norin,

Abbiamo separato il processo di impacchettamento dal processo di compilazione, perché viene eseguito da persone diverse in momenti diversi. Il processo del pacchetto crea anche programmi di installazione per Windows, Windows CE, Symbian, AIX, Linux e Solaris.
Ludvig A. Norin,

Probabilmente ti riferisci a hdiutil, non a hdutil.
Ivan Vučica,

25

Aggiorna questa domanda fornendo questa risposta.

appdmgè un programma da riga di comando open source semplice, facile da usare che crea file dmg da una semplice specifica json. Dai un'occhiata al readme sul sito ufficiale:

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

Esempio rapido:

  1. Installa appdmg

    npm install -g appdmg
    
  2. Scrivi un file 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. Eseguire il programma

    appdmg spec.json test.dmg
    

(disclaimer. Sono il creatore di appdmg)


3
semplice ed efficace. L'unico aspetto negativo è che richiede l'installazione di npm
Jack James,

@Creator: puoi farlo avanzare come questa GUI dell'offerta senza trascinarla? s.sudre.free.fr/Software/Packages/about.html

Se il file .app non si trova nella stessa cartella del file json, questo non funziona, genera un errore "file non trovato" quando si specifica un percorso relativo in "percorso"
Joey

@Joey, potresti aprire un problema sul repository Github se non funziona per te?
Linus Unnebäck,

@Joey: non è necessario trovarsi nella stessa cartella, ho uno sfondo, un'app tutta in un percorso diverso, basta passare percorsi relativi come ../../../ABC
Anoop Vaidya,

22

Per quelli di voi che sono interessati a questo argomento, dovrei menzionare come creo il DMG:

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

dove

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
Va bene, ma non risponde all'esigenza effettiva (immagine di sfondo, posizionamento degli elementi nella cartella, ecc.)
Tom Bogle,

creato DMG ma di nuovo devo eseguire il mio script (.sh) usando CMD, ho bisogno che esegua automaticamente sh dopo aver creato DMG
SANTOSH

13

La mia app, DropDMG , è un modo semplice per creare immagini del disco con immagini di sfondo, layout di icone, icone di volume personalizzate e contratti di licenza software. Può essere controllato da un sistema di compilazione tramite lo strumento da riga di comando "dropdmg" o AppleScript. Se lo si desidera, i file immagine e licenza RTF possono essere archiviati nel sistema di controllo della versione.


3
Il mio team funziona perfettamente e automaticamente su un server di build CI Jenkins, completo di background, trascina sull'alias Applicazioni. Corri, non camminare, verso DropDMG per creare immagini del disco.
Paul Collins,

Buona app, la comprerò dopo la scadenza del periodo di prova.
kilik52,

Sembra carino, ma non sembra avere la possibilità di ridimensionare la finestra.
avi

@avi DropDMG ridimensiona automaticamente la finestra sull'immagine di sfondo che hai impostato (o inseriscilo nell'immagine se lo desideri).
Michael Tsai,

Grazie mille! È possibile ridimensionare senza l'immagine di sfondo?
avi


5

Per creare un DMG di bell'aspetto, ora puoi semplicemente usare alcuni open source ben scritti:


Potrebbe essere stato spostato. Puoi usare create-dmg e node-appdmg. Sto usando create-dmg. Va bene.
Anni S,

@ PamelaCook-LightBeCorp Nel caso tu sia ancora interessato. Il collegamento a dmgbuild è stato corretto.
Subottimale

4

Se si desidera impostare l'icona del volume personalizzato, utilizzare il comando seguente

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

Ora crea lettura / scrittura dmg

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

Puoi spiegarci cosa significa "il tuo percorso" qui? Posso usare qualsiasi file di icone sul disco e SetFile lo copierebbe o dovrei usare un file che si trova all'interno di .dmg? Ho solo un Mac, quindi è difficile verificare se le cose funzioneranno su altre macchine.
Milan Babuškov,

"il tuo percorso" è il nome DMG. (/ Volumes / dmgName)
Parag Bafna,

Dovresti copiare il file icns. cp "/Volumes/customIcon.icns" "/Volumes/dmgName/.VolumeIcon.icns"
Parag Bafna,

4

Ho finalmente ottenuto questo lavoro nel mio progetto (che sembra essere in Xcode). L'aggiunta di questi 3 script alla fase di creazione creerà automaticamente un'immagine del disco per il tuo prodotto che è bello e pulito. Tutto quello che devi fare è costruire il tuo progetto e il DMG attenderà nella cartella dei tuoi prodotti.

Script 1 (Crea immagine disco temporaneo):

#!/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 (Imposta script proprietà finestra):

#!/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 misura di cui sopra per la finestra funziona per il mio progetto in particolare a causa delle dimensioni della mia immagine di sfondo e della risoluzione dell'icona; potresti dover modificare questi valori per il tuo progetto.

Script 3 (Crea script immagine disco finale):

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

Assicurati che i file di immagine che stai utilizzando siano nella directory $ PROJECT_DIR / $ PROJECT_NAME /!


Sta creando un'immagine del disco vuota sul mio progetto. Qualche suggerimento.
ManiaChamp

La parte dello script Shell funziona solo, ma come posso aggiungere lo script Apple con Shell Script in RunScript in Build Phase che mostra errori, ogni istruzione di script Apple non è stata trovata.
ManiaChamp,

2

I file .DS_Store memorizzano le impostazioni di Windows su Mac. Le impostazioni di Windows includono il layout delle icone, lo sfondo della finestra, le dimensioni della finestra, ecc. Il file .DS_Store è necessario per creare la finestra per le immagini montate per preservare la disposizione dei file e lo sfondo di Windows.

Dopo aver creato il file .DS_Store, puoi semplicemente copiarlo nel programma di installazione creato (DMG).


Ma prima aggiungi un'immagine di sfondo al dmg nominandolo in qualche modo come .background.png e poi usando Cmd-J per aggiungere quella (!) Immagine allo sfondo.
Gijs,

2

Ho anche bisogno di usare l'approccio da riga di comando per fare il packaging e la creazione di dmg "programmaticamente in uno script". La migliore risposta che ho trovato finora è dal progetto di costruzione del framework Adium (vedi R1). Esiste uno script personalizzato (AdiumApplescriptRunner) che consente di evitare l'interazione della GUI di Windows Server OSX. L'approccio "osascript applescript.scpt" richiede di accedere come builder ed eseguire la creazione di dmg da una sessione della riga di comando vt100.

Il sistema di gestione dei pacchetti OSX non è così avanzato rispetto ad altri Unixen che possono svolgere questo compito in modo semplice e sistematico.

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


2

Ho appena scritto una nuova (amichevole) utility da riga di comando per farlo. Non si basa su Finder / AppleScript o su nessuna delle API (obsolete) di Alias ​​Manager ed è facile da configurare e utilizzare.

Comunque, chiunque sia interessato può trovarlo su PyPi ; la documentazione è disponibile su Leggi i documenti .


1

Queste risposte sono troppo complicate e i tempi sono cambiati. Il seguente funziona su 10.9 bene, i permessi sono corretti e sembra bello.

Crea un DMG di sola lettura da una directory

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

Crea DMG di sola lettura con un'icona (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

Se dovesse succedere qualcos'altro, la cosa più semplice è fare una copia temporanea di SRC_DIR e applicare le modifiche prima di creare un DMG.


Questa risposta non aggiunge nulla a ciò che è stato scritto in precedenza e non risponde alla domanda originale (non si tratta solo di inserire un'icona nel dmg o di come firmarla; la domanda riguarda l'aggiunta di grafica e icone posizionate a livello di codice a un dmg).
Ludvig A. Norin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.