MacOS app打包Dmg线下分发测试及公证shell脚本

macOS app除了上架苹果商店还可以通过发布到自己网站对外下载使用,本文主要介绍使用shell 脚本提交给苹果公证以及公证后打包dmg文件。如果使用Testflight 分发测试或者直接发布到商店就不需要这样麻烦,里面一站式做了处理。

1、公证脚本。之所以要提交公证是应为不做此操作,用户下载后会提示不安全应用,如下图:

具体公证脚本如下(当然还可以通过Xcode自带的等其他方式进行公证):

bash 复制代码
#!/bin/bash
# notarize_app_only.sh

# 只公证 .app 文件,而不是安装包
APP_PATH="/Users/WorkSpace/MacOS/KcStudentProject.app"
ZIP_PATH="/Users/WorkSpace/MacOS/西度科学会PC版/KcStudentProject.zip"

# 1. 签名应用(使用 Developer ID Application)
codesign --force \
    --options runtime \
    --sign "Developer ID Application" \
    --timestamp \
    "${APP_PATH}"

# 2. 创建 ZIP
ditto -c -k --keepParent "${APP_PATH}" "${ZIP_PATH}"

# 3. 提交公证(使用 notarytool)
xcrun notarytool submit "${ZIP_PATH}" \
    --apple-id "开发者账号" \
    --password "开发者账号对应密码" \
    --team-id "项目证书所在团队" \
    --wait

# 4. 装订票据
xcrun stapler staple "${APP_PATH}"

apple-id:开发者账号

password:对应开发者账号密码

team-id:项目证书所在的团队

文件后缀:.sh

在脚本目录(指定 脚本里面的APP_PATH和ZIP_PATH路径)输入命令,如下(出现类似的提示 "The staple and validate action worked!"说明公证成功,会在指定的ZIP_PAH 生成压缩包,解压后的app文件就是包含公证信息的新包):

bash 复制代码
#notarize_app_only.sh 脚本名称,以实际名称为准
bash notarize_app_only.sh

2、打包成dmg安装文件(通过上步解压后的app,执行脚本即可生成dmg),具体如下:

bash 复制代码
#!/bin/bas

# create_dmg.sh
# 创建 DMG 安装包

APP_NAME="com.macos.demo.app"
VERSION="1.0(1)"
APP_PATH="/Users/yanyan/Desktop/com.macos.demo 2026-02-13 09-46-48/com.macos.demo.app"
DMG_NAME="demo Release_${VERSION}.dmg"
VOLUME_NAME="${APP_NAME}"
DMG_TMP_PATH="/Users/yanyan/Desktop/tmp/${DMG_NAME}"
DMG_FINAL_PATH="/Users/yanyan/Desktop/com.macos.demo 2026-02-13 09-46-48/${DMG_NAME}"

# 检查应用是否存在
if [ ! -d "${APP_PATH}" ]; then
echo "错误: 应用不存在 ${APP_PATH}"
exit 1
fi

# 计算应用大小(增加一些空间)
APP_SIZE=$(du -sm "${APP_PATH}" | cut -f1)
DMG_SIZE=$((APP_SIZE + 10))M

echo "创建 DMG 安装包..."
echo "应用: ${APP_NAME}"
echo "版本: ${VERSION}"
echo "大小: ${DMG_SIZE}"

# 创建临时目录
mkdir -p /tmp/dmg_build

# 复制应用到临时目录
cp -R "${APP_PATH}" /tmp/dmg_build/

# 创建 Applications 文件夹的快捷方式
ln -s /Applications /tmp/dmg_build/Applications

# 创建 DMG
hdiutil create \
-srcfolder /tmp/dmg_build \
-volname "${VOLUME_NAME}" \
-fs HFS+ \
-fsargs "-c c=64,a=16,e=16" \
-format UDRW \
-size ${DMG_SIZE} \
"${DMG_TMP_PATH}"

# 挂载 DMG
DEVICE=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TMP_PATH}" | \
awk 'NR==1{print $1}')
MOUNT_PATH=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TMP_PATH}" | \
awk 'NR==2{print $3}')

# 添加背景图片
BACKGROUND_IMG="西度科学会PC版.png"
if [ -f "${BACKGROUND_IMG}" ]; then
    # 在 DMG 中创建 .background 文件夹
    mkdir -p "${MOUNT_PATH}/.background"
    cp "${BACKGROUND_IMG}" "${MOUNT_PATH}/.background/background.png"
fi

# 设置 DMG 窗口样式
echo '
        tell application "Finder"
        tell disk "'${VOLUME_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 {400, 100, 920, 420}
            set viewOptions to the icon view options of container window
            set arrangement of viewOptions to not arranged
            set icon size of viewOptions to 72
            set background picture of viewOptions to file ".background:background.png"
            set position of item "'${APP_NAME}.app'" of container window to {120, 180}
            set position of item "Applications" of container window to {380, 180}
            update without registering applications
            delay 5
            close
        end tell
    end tell
' | osascript

# 设置权限
chmod -Rf go-w "${MOUNT_PATH}"
sync

# 卸载 DMG
hdiutil detach "${DEVICE}"

# 压缩 DMG
hdiutil convert "${DMG_TMP_PATH}" \
-format UDZO \
-imagekey zlib-level=9 \
-o "${DMG_FINAL_PATH}"

# 清理
rm -rf /tmp/dmg_build
rm -f "${DMG_TMP_PATH}"

echo "DMG 创建完成: ${DMG_FINAL_PATH}"

APP_NAME:需要打包的app名称(此处注意,是原始的工程名称,而不是通过BundleName或DisplayName本地化指定后的名称)

APP_PATH:公证后解压的app文件路径

DMG_TMP_PATH:指向tmp目录,此目录是临时新建的文件夹,不可删除,名称根据设置保持一致即可

其他路径对应设置即可,执行脚本如下(执行成功会在DMG_FINAL_PATH目录生成dmg文件了):

bash 复制代码
#create_dmg.sh 脚本名称,以实际名称为准
bash create_dmg.sh

以上内容就是这些,有问题欢迎交流沟通

相关推荐
a4493153627 小时前
iPhone Face ID 故障的分层诊断——原深感系统与主板加密配对机制
macos·ios·电脑·cocoa·iphone
白玉cfc8 小时前
【iOS】内存五大分区
macos·ios·cocoa
a44931536217 小时前
iPhone 基带故障诊断——无服务/搜索不到网络的芯片级维修实录
网络·macos·ios·电脑·iphone
半条_虫18 小时前
豆包-网页逆向接口, 免token调用AI
python·ai·shell
a44931536218 小时前
MacBook USB-C不充电故障诊断:从PD握手到主板供电链路
c语言·开发语言·macos·电脑
寒水馨19 小时前
macOS下载、安装scrcpy-v4.1(附安装包scrcpy-macos-aarch64-v4.1.tar.gz)
macos·adb·手机控制·scrcpy·投屏软件·android投屏·屏幕镜像
a44931536219 小时前
iPhone 充电故障的全链路诊断——从 Lightning/USB-C 接口到 Tristar 充电 IC
c语言·macos·ios·电脑·硬件架构·iphone
xiaowang1234shs2 天前
怪兽轻断食技术深度测评:从断食计时引擎到AI识别算法的工程实践解析
数据库·人工智能·算法·macos·机器学习·p2p·visual studio
爱码少年2 天前
Docker遍历镜像生成导出镜像命令六法
docker·shell
yAdrian2 天前
macOS launchd CPU 占用过高问题排查记录
macos