ClickOnce 应用通过 Nginx 内网发布
# ClickOnce 应用通过 Nginx 内网发布
本文记录如何在 anim.nd.com.cn 上,用 Nginx 静态目录 + Visual Studio ClickOnce 发布多个 Windows 桌面工具(以 MY-C3S3-GUID-Tools 为例),供内网用户一键安装与自动更新。
http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application (opens new window)

# 目标与访问方式
| 项 | 示例 |
|---|---|
| 安装入口 | http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application |
| 服务器目录 | /home/nd/DownloadFile/Tools/publish-app/{应用名}/ |
| Nginx 配置 | svn-anim_-lib/nginx/conf/nginx_flask.conf |
# 目录结构(多应用)
publish-app 下每个应用独占一个子文件夹,避免 Application Files 等资源路径冲突:
/home/nd/DownloadFile/Tools/publish-app/
├── MY-C3S3-GUID-Tools/
│ ├── MY-C3S3-GUID-Tools.application # 部署清单(入口)
│ ├── MY-C3S3-GUID-Tools.application.manifest
│ ├── setup.exe # 可选,网页安装引导
│ ├── Publish.html
│ └── Application Files/
│ └── MY-C3S3-GUID-Tools_1_0_0_x/
│ ├── MY-C3S3-GUID-Tools.exe.deploy
│ └── ...
└── AnotherTool/ # 其它应用同理
└── AnotherTool.application
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# Visual Studio 发布设置
在 项目属性 → 发布 (Publish) 中:
| 设置项 | 正确示例 | 常见错误 |
|---|---|---|
| 发布位置 | 本机输出目录,再复制到服务器 publish-app/MY-C3S3-GUID-Tools/ | — |
| 安装文件夹 URL | http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/ | 写成 .../app/ 或带 .application 的完整文件路径 |
| 安装 URL | http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application | 与安装文件夹 URL 重复拼接文件名 |
发布完成后,在服务器上检查清单:
grep deploymentProvider \
/home/nd/DownloadFile/Tools/publish-app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application
1
2
2
codebase 应为(仅一个 .application):
<deploymentProvider codebase="http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application" />
1





# Nginx 配置说明
在 nginx_flask.conf 的 server 块中,location /(VuePress)之前增加:
# ClickOnce 多应用根目录
location ^~ /app/ {
alias /home/nd/DownloadFile/Tools/publish-app/;
# 兼容:/app/Foo.application → /app/Foo/Foo.application
rewrite ^/app/([^/]+)\.application$ /app/$1/$1.application last;
autoindex off;
types {
application/x-ms-application application;
application/x-ms-manifest manifest;
application/octet-stream deploy;
}
default_type application/octet-stream;
if ($uri ~* \.(application|manifest)$) {
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires -1;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 要点:
-
^~ /app/ :优先于根路径location /,避免被 VuePress 抢走。 -
alias 末尾必须有 / ,且指向publish-app/而非单个应用目录。 - MIME 类型:缺省会把
.application当成普通文件,ClickOnce 无法安装。 - 清单不缓存:便于客户端检测更新。
-
rewrite ... last:支持书签/旧文档中的扁平 URL。
修改后重载:
sudo nginx -t && sudo nginx -s reload
1
# URL 与磁盘路径对应关系
| 请求 URL | 磁盘文件 |
|---|---|
/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application | publish-app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application |
/app/MY-C3S3-GUID-Tools/Application%20Files/... | publish-app/MY-C3S3-GUID-Tools/Application Files/... |
# 验证
# 文件是否存在
ls /home/nd/DownloadFile/Tools/publish-app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application
# HTTP 与 Content-Type
curl -I "http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application"
# 期望:HTTP/1.1 200,Content-Type: application/x-ms-application
# 兼容扁平链接
curl -I "http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools.application"
# 期望:200(经 rewrite 后同样返回 application 类型)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Windows 客户端测试:
rundll32 dfshim.dll,ShOpenVerbApplication http://anim.nd.com.cn/app/MY-C3S3-GUID-Tools/MY-C3S3-GUID-Tools.application
1
或在浏览器直接打开上述 .application 链接。
# 新增第二个应用 checklist
- Visual Studio 发布到
publish-app/AnotherTool/。 - 安装文件夹 URL:
http://anim.nd.com.cn/app/AnotherTool/。 - 确认
deploymentProvider 指向
http://anim.nd.com.cn/app/AnotherTool/AnotherTool.application。 - 无需改 Nginx(已指向
publish-app/根目录)。 - 分发链接:
http://anim.nd.com.cn/app/AnotherTool/AnotherTool.application。
# 参考
