------------基于自定义协议的桌面端版本控制方案
在基础篇中,我们已经实现了:
- 通过 Windows 自定义协议(XXXX://open)
- 从浏览器直接唤起本地桌面程序
本篇作为 进阶版,核心目标不再只是「能唤起」,而是:
在多版本桌面程序共存的情况下,实现"可控、可扩展、可演进"的版本选择机制
为什么需要"桌面端版本控制"?
在工程软件企业内部工具中,常见问题包括:
- 多个版本并行安装1.0、2.0、3.0、...
- 不同项目、不同数据依赖特定版本
- 浏览器 / Web 系统需要精确控制启动的版本
如果只是简单写死一个 exe 路径,会带来:
- ❌ 无法指定版本
- ❌ Web 侧与桌面侧强耦合
- ❌ 后期升级成本高
因此我们需要一个 "启动代理层(Launcher)", 接下来我们以NX为案例去实现一个对于不同版本控制的唤起。
整体架构设计思路
text
浏览器
|
| nx://open?version=12
v
Windows 协议注册(nx)
|
v
NxLauncher(bat / ps1)
|
| 解析参数 + 版本选择
v
具体 NX 版本 exe
核心思想:
❗ 浏览器永远只关心"意图",
❗ 桌面端 Launcher 决定"如何执行"。
NxLauncher:启动代理的职责划分
NxLauncher 需要做什么?
- 接收并解析 URL
nx://opennx://open?version=11nx://open?version=12
- 清洗参数
- 去掉协议前缀
- 去掉不可见字符 / 空格
- 保证解析稳定性
- 版本 → 可执行文件映射
- version = 11 → NX 11 路径
- version = 12 → NX 12 路径
- 兜底策略
- 未指定 version → 启动最新版本
- 指定版本不存在 → fallback
- 真正启动程序
落地方案
1. 注册表实现
新建文本,复制如下文字
scss
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\nx]
@="URL:NX Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\nx\shell\open\command]
;ps1 使用的代码
;@="powershell -NoProfile -ExecutionPolicy Bypass -File \"D:\\Desktop\\NxLauncher.ps1\" \"%1\""
;bat 使用代码
@="\"D:\\Desktop\\NxLauncher.bat\" \"%1\""
将文件后缀改为reg, 命名为nx.reg
然后根据使用的脚本做修改, 双击注册
⚠️ 注意;请根据你本机NxLauncher的实际位置修改 @= 后的路径。

注册表原则:
❌ 不判断版本,只做转发,不做逻辑
❌ 不写死 exe
✅ 只负责把 URL 原样交给 Launcher
2. NxLauncher实现
2.1 BAT 方案(轻量、零依赖)
适合:
- 环境受限
- 不方便修改 PowerShell 策略
- 希望注册表直接调用
特点:
- 使用 PowerShell 作为辅助解析
- 控制力略弱,但稳定可靠
c#
@echo off
setlocal EnableDelayedExpansion
:: ==================================================
:: NxLauncher.bat
:: 功能:
:: 1. 解析 nx://open?version=xx
:: 2. 去掉空格和不可见字符
:: 3. 输出调试信息
:: 4. 根据 version 打开对应 NX
:: ==================================================
:: 获取浏览器传来的 URL,去掉两端引号
set RAW_URL=%~1
:: ---------------------------
:: 去掉协议前缀 nx://open 或 nx://open/
:: ---------------------------
set PARAMS=%RAW_URL:nx://open/=%
set PARAMS=%PARAMS:nx://open?=%
:: 去掉开头的 ?(如果有)
if defined PARAMS if "%PARAMS:~0,1%"=="?" set PARAMS=%PARAMS:~1%
:: ---------------------------
:: 提取 version
:: ---------------------------
set VERSION=[]
:: 调用 PowerShell 去解析并 trim
for /f %%V in ('powershell -NoProfile -Command ^
"$p='%PARAMS%'; if ($p -match 'version=(.+)') { ($matches[1]).Trim() }"') do set VERSION=%%V
:: ---------------------------
:: 输出调试信息
:: ---------------------------
:: echo RAW_URL=%RAW_URL%
:: echo PARAMS=%PARAMS%
:: echo VERSION=[%VERSION%]
:: pause
:: ---------------------------
:: NX 安装路径
:: ---------------------------
set NX12=D:\Program Files\Siemens\NX 12.0\NXBIN\ugraf.exe
set NX11=D:\NX\NX 11.0\NXBIN\ugraf.exe
:: ---------------------------
:: 根据 version 选择 NX
:: ---------------------------
set NX_EXE=
if /i "%VERSION%"=="12" if exist "%NX12%" set NX_EXE="%NX12%"
if /i "%VERSION%"=="11" if exist "%NX11%" set NX_EXE="%NX11%"
:: 默认最新
if not defined NX_EXE (
if exist "%NX12%" set NX_EXE="%NX12%"
if not defined NX_EXE if exist "%NX11%" set NX_EXE="%NX11%"
)
:: ---------------------------
:: 找不到 NX
:: ---------------------------
if not defined NX_EXE (
echo NX not found!
pause
exit /b 1
)
:: ---------------------------
:: 启动 NX
:: ---------------------------
start "" %NX_EXE%
exit /b 0
将文件后缀改为bat, 命名为NxLauncher.bat
然后根据使用的脚本做修改
⚠️ 注意;请根据你本机Nx的实际位置修改路径。

设计重点:
- 不在 bat 中硬解析 URL(太脆弱)
- 利用 PowerShell 做字符串清洗
- bat 只负责"调度"
2.2 PowerShell 方案(推荐 / 可扩展)
新建文本,粘贴以下文本
c#
# NxLauncher.ps1
# ==================================================
# 功能:
# 1. 解析 nx://open?version=xx
# 2. 有 version → 打开指定 NX 版本
# 3. 无 version → 默认打开最新版本
# 4. 调试输出并暂停,方便查看解析过程
# ==================================================
param (
[string]$RawUrl
)
# ---------------------------
# 1. 清理 URL
# ---------------------------
$RawUrl = $RawUrl.Trim('"') # 去掉可能的引号
Write-Host "RawUrl: $RawUrl"
# 去掉协议前缀 nx://open 或 nx://open/
$paramString = $RawUrl -replace '^nx://open/?', ''
Write-Host "Param string: $paramString"
# ---------------------------
# 2. 解析 version
# ---------------------------
Add-Type -AssemblyName System.Web
$query = [System.Web.HttpUtility]::ParseQueryString($paramString)
$version = $query['version']
Write-Host "Parsed version: [$version]"
# ---------------------------
# 3. NX 安装路径配置
# ---------------------------
$nx12 = 'D:\Program Files\Siemens\NX 12.0\NXBIN\ugraf.exe'
$nx11 = 'D:\NX\NX 11.0\NXBIN\ugraf.exe'
$nxExe = $null
# ---------------------------
# 4. 根据 version 选择 NX
# ---------------------------
switch ($version) {
'12' { if (Test-Path $nx12) { $nxExe = $nx12 } }
'11' { if (Test-Path $nx11) { $nxExe = $nx11 } }
}
# 默认最新
if (-not $nxExe) {
if (Test-Path $nx12) { $nxExe = $nx12 }
elseif (Test-Path $nx11) { $nxExe = $nx11 }
}
# ---------------------------
# 5. 检查 NX 是否存在
# ---------------------------
if (-not $nxExe) {
Write-Host "NX not found!"
Read-Host "Press Enter to exit..."
exit 1
}
Write-Host "Using NX: $nxExe"
# ---------------------------
# 6. 启动 NX
# ---------------------------
Start-Process -FilePath $nxExe
# ---------------------------
# 7. 暂停查看输出
# ---------------------------
# Read-Host "Press Enter to exit..."
将文件后缀改为ps1, 命名为NxLauncher.ps1
然后根据使用的脚本做修改
⚠️ 注意;请根据你本机Nx的实际位置修改路径。

适合:
- 长期维护
- 复杂参数
- 后续扩展(license / workspace / project)
优势:
- 原生 QueryString 解析
- 逻辑清晰
- 可维护性极高
3. 浏览器实现
html
<button id="openNX11">唤起NX11</button>
<button id="openNX12">唤起NX12</button>
<button id="openNXAuto">自动选择最新版本</button>
<script>
document.getElementById('openNX11').addEventListener('click', () => {
openNX('11');
})
document.getElementById('openNX12').addEventListener('click', () => {
openNX('12');
})
document.getElementById('openNXAuto').addEventListener('click', () => {
openNX();
})
function openNX(version = '') {
let url = 'nx://open';
const params = [];
if (version) params.push(`version=${version}`);
if (params.length > 0) {
url += '?' + params.join('&');
}
window.location.href = url;
}
</script>
好处:
-
前端逻辑极简
-
参数可自由扩展:
nx://open?version=12&project=Anx://open?workspace=xxx
成果展示

可继续演进的方向
📦 JSON 配置驱动版本映射
🧠 自动检测已安装版本
🧩 NxLauncher → 通用 Desktop Launcher
🌐 Web 平台统一调度本地能力
✅ 总结
基础篇解决"能不能唤起"
进阶篇解决"唤起谁、如何唤起、以后怎么扩展"
这套思路本质上是:
用 Web 参数驱动桌面能力,用 Launcher 隔离不确定性。