跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++大前端

基于 URI Scheme 实现从 Web 页面启动本地 C++ 应用程序

如何通过 URI Scheme 规范,在注册表中配置自定义协议,从而实现从 Web 网页直接启动本地 C++ 客户端程序。内容包括需求分析、注册表写入原理、C++ 源码实现、HTML 调用示例以及处理多实例、参数传递等细节问题。

蓝绿部署发布于 2026/4/6更新于 2026/5/1927 浏览
基于 URI Scheme 实现从 Web 页面启动本地 C++ 应用程序

需求描述

最近多个第三方开发厂商为了快速集成软件及系统,不想基于 SDK 做费时费力的二次开发,而是希望直接从 Web 网页上启动客户端软件。类似的需求可以归纳为以下几类:

  1. 仅仅是从 Web 网页上将 C++ 客户端软件启动起来,用户手动操作。
  2. 从 Web 网页上将 C++ 客户端软件启动起来,并传递服务器地址、用户名和密码,让软件自动发起登录。
  3. 从 Web 网页上将 C++ 客户端软件启动起来,传递信息执行指定操作,如加入指定会议。

上述需求可归结为:将 C++ 客户端软件启动起来,并给 C++ 客户端软件传递一些命令行参数,C++ 客户端软件解析出参数,执行指定的操作。

以浏览器打开腾讯会议的会议链接为例,点击链接后系统会弹出是否要打开本地安装的腾讯会议程序的提示框,确认后启动程序并自动加入会议。

选择 URI Scheme 实现

在 C++ 程序中启动另一个 C++ 软件比较简单,只需获取目标软件的安装路径即可直接启动。但在 B/S 架构下,Web 网页出于安全原因不能直接读写注册表,无法像 C++ 程序那样直接启动二进制文件。使用 URI Scheme 技术与规范就能实现这样的需求。

何为 URI Scheme?

URI(Uniform Resource Identifier)是统一资源标志符。URI Scheme 是一种技术规范,表示 Web 上每一种可用的资源。从 Web 网页中启动本地应用程序的 URI Scheme 规范中,需要将本地应用程序的信息通过写注册表的方式注册到系统中,然后在网页中使用'SchemeName://'就可以启动本地程序了。

具体的做法是,在注册表的 HKEY_CLASSES_ROOT 下创建一个自定义的 SchemeName 注册表节点,然后再在该节点下创建多个节点,并在给相关节点设置注册表键值。

以 QQGame 为例,添加注册表信息的步骤如下:

  1. 在 HKEY_CLASSES_ROOT 下创建 QQGameProtocol 节点。QQGameProtocol 就是对应的 Scheme 方案名称,也是 Web 页面上启动对应程序的 URL 的前缀名称。然后给该节点添加一个 URL Protocol 名称的键值,将其 Value 设置为本地应用程序的完整路径。
  2. 在 QQGameProtocol 根节点下创建 DefaultIcon 节点。给 DefaultIcon 节点设置默认的字符串键值,其 Value 的格式为'应用程序全路径,图标索引'的形式,用来指定该 URI 方案使用的图标。
  3. 在 QQGameProtocol 下创建 shell 节点,然后在 shell 节点下创建 open 节点,然后在 open 节点创建 command 节点。command 节点需要设置键值,其键值用来指定启动目标应用程序时是否给目标程序传递命令行参数。

一般只需要设置传递一个参数即可,比如当前 Scheme 下的 "C:\Users\Public\Documents\Tencent\QQGameMicro\QQGwp.exe" "%1"。如果要传递多个参数,可以自定义一个组合格式,命令行只用一个参数即可。

当在 Web 页面上点击'SchemeName://'链接时,就会到系统注册表的 HKEY_CLASSES_ROOT 节点下查找 SchemeName 节点项,找到后取出目标应用程序的全路径,并查找传递的命令行参数个数,这样就能把本地的目标应用程序启动起来了。

如果要给目标程序传递参数,则使用'SchemeName://参数'的形式。经测试发现,如果在 command 节点中设置了%1 传递参数的标识,则 Web 网页中设置的 URL 必须要带参数。如果使用不带参数的 URL,则无法启动目标程序。

那如何既要支持不传参数启动,也要支持传参数启动呢?其实不用这么麻烦,使用一个带参数的 SchemeName 节点就够了,对于直接启动目标程序不带启动参数的,也可以携带一个标识参数,在程序中约定不传参数的标识符,比如 noparam,当程序中解析出 noparam,则表示是不带参数启动的,直接启动程序即可。

将自定义的 URL Scheme 信息写入注册表的 C++ 源码实现

下面给出将自定义的 URL Scheme 信息写入注册表的 C++ 源码实现:

BOOL WriteURISchemaReg() {
    // exe 程序的完整路径
    CString strExePath = m_strInstallPath + _T("xyzlink.exe");
    // URI Scheme 名称
    CString strProtocolName = _T("XyzlinkProtocol");
    HKEY hRootKey = NULL;
    DWORD dwKeyValue = 0;
    DWORD dwDisposition = 0;
    UCHAR szBuf[MAX_PATH] = { 0 };
    
    // 1、在 HKEY_CLASSES_ROOT 下创建 URI Schema 相关注册表的根节点 RootNode
    long lRet = ::RegCreateKeyEx(HKEY_CLASSES_ROOT, strProtocolName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hRootKey, &dwDisposition);
    if (lRet != ERROR_SUCCESS) {
        return FALSE;
    }
    
    // 给根节点 RootNode 设置值 1
    lRet = ::RegSetValueEx(hRootKey, NULL, 0, REG_SZ, (LPBYTE)(LPCTSTR)strProtocolName, strProtocolName.GetLength() * sizeof(TCHAR));
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 给根节点 RootNode 设置值 2
    CString strKey = _T("URL Protocol");
    lRet = RegSetValueEx(hRootKey, strKey.GetBuffer(0), 0, REG_SZ, (LPBYTE)(LPCTSTR)strExePath, strExePath.GetLength() * sizeof(TCHAR));
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 2、在根节点 RootNode 下创建 DefaultIcon 节点
    strKey = _T("DefaultIcon");
    HKEY hDefaultIconKey = NULL;
    lRet = RegCreateKeyEx(hRootKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hDefaultIconKey, &dwDisposition);
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 给 RootNode\DefaultIcon 节点设置值
    CString strExePathPlus = strExePath + _T(",1");
    lRet = RegSetValueEx(hDefaultIconKey, NULL, 0, REG_SZ, (LPBYTE)(LPCTSTR)strExePathPlus, strExePathPlus.GetLength() * sizeof(TCHAR));
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hDefaultIconKey);
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 3、在 RootNode\DefaultIcon 节点下创建子节点 shell
    strKey = _T("shell");
    HKEY hShellKey = NULL;
    lRet = RegCreateKeyEx(hDefaultIconKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hShellKey, &dwDisposition);
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hDefaultIconKey);
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 4、在 RootNode\DefaultIcon\shell 节点下创建子节点 open
    strKey = _T("open");
    HKEY hOpenKey = NULL;
    lRet = RegCreateKeyEx(hShellKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hOpenKey, &dwDisposition);
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hDefaultIconKey);
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 5、在 RootNode\DefaultIcon\shell\open 节点下创建子节点 command
    strKey = _T("command");
    HKEY hCommandKey = NULL;
    lRet = RegCreateKeyEx(hOpenKey, strKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hCommandKey, &dwDisposition);
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hOpenKey);
        RegCloseKey(hDefaultIconKey);
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    // 给 command 节点设置值(命令行参数)
    CString strCmdParam;
    strCmdParam.Format(_T("\"%s\" \"%%1\""), strExePath);
    lRet = RegSetValueEx(hCommandKey, NULL, 0, REG_SZ, (LPBYTE)(LPCTSTR)strCmdParam, strCmdParam.GetLength() * sizeof(TCHAR));
    if (lRet != ERROR_SUCCESS) {
        RegCloseKey(hCommandKey);
        RegCloseKey(hOpenKey);
        RegCloseKey(hDefaultIconKey);
        RegCloseKey(hRootKey);
        return FALSE;
    }
    
    RegCloseKey(hCommandKey);
    RegCloseKey(hOpenKey);
    RegCloseKey(hDefaultIconKey);
    RegCloseKey(hRootKey);
    return TRUE;
}

如何实现最开始的 3 种需求

搞清楚了使用 URI Scheme 规范实现从 Web 页面中启动本地应用程序的方法,下面我们再回到最开始提出的 3 个需求,看看如何去实现。

第一种需求不需要传递参数,后面两种需求则需要传递参数,我们使用一个带参数传递的 Scheme 节点即可。我们可以定义一个启动 type 类型标识 launchtype,对于直接启动的,type 为 noparam。对于启动后发起自动登录的,type 为 autologin;对于启动后需要执行具体操作的,可以根据具体的业务,定义具体的 type 类型,这样更灵活。

对于目标应用程序,则可以根据不同的 type 类型,解析对应的参数数据,并对参数的合法性进行校验。

下面把 Web 网页的测试代码给出来,保存成.html 文件,用浏览器打开即可:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Start exe demo</title>
</head>
<body>
    <a href="SchemeName://">打开目标程序</a>
</body>
</html>

后续需要考虑的细节问题

上面大概说了一下问题的解决办法和思路,其实还有很多细节需要去考虑。比如下面的几种场景:

  1. 程序可能没有安装 如果目标应用程序没有安装,肯定是启动不起来的,是不是要检测启动失败的原因,然后自动跳转到安装程序的下载页面。

  2. 仅将目标程序启动起来,但目标程序已经运行 一般情况下,很多程序都是单实例运行的,即只允许运行一个实例。假定目标程序是单实例运行的,点击 Web 页面中的启动程序的链接时,已经有个进程在运行了,目标程序中要弹出程序已经运行的提示,并将已经启动的程序拉到前端显示。

  3. 启动程序后需要有后续操作,但目标程序已经运行 启动程序后需要有后续操作,比如自动发起登录,但此时目标应用程序已经运行。如果已启动的进程还没登录,是要自动发起登录?还是搁置不管?如果已启动的进程已经登录,则提示已经启动,并将已启动的主窗口拉到最前显示。如果目标程序已经启动且已经登录成功,则需要将命令行参数发给已启动的进程,让该进程执行要执行的操作,比如加入会议。

参考文档:Registering an Application to a URI Scheme

目录

  1. 需求描述
  2. 选择 URI Scheme 实现
  3. 何为 URI Scheme?
  4. 将自定义的 URL Scheme 信息写入注册表的 C++ 源码实现
  5. 如何实现最开始的 3 种需求
  6. 后续需要考虑的细节问题
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • UZH RPG 组 AC-MPC:微分 MPC 赋能强化学习实现高速无人机竞速
  • 基于 Qwen3-TTS 的博物馆 AR 导览多语种语音讲解系统开发
  • 大模型 + 数据分析产品打造指南:核心步骤与成功策略
  • AI 编程中的 Skills:概念解析与 Java 实战指南
  • 基于 AI 辅助的学生成绩综合统计分析系统设计与实现
  • 人工智能:自然语言处理在医疗领域的应用与实战
  • Django Web 框架实战:从零构建产品管理系统
  • 使用 Python 实现微信自动回复功能
  • PAT 乙级 1032:挖掘机技术哪家强 Python 高效解法
  • 命令行工具 MCPHost:利用模型上下文协议连接大模型与外部工具
  • Python 3.8+ 海象运算符详解
  • 命令行工具 MCPHost:让大模型通过协议调用外部工具
  • 攻防世界 Web 题解:Lottery 与 ics-05 漏洞分析
  • 小巧的 MCPHost:命令行大模型上下文协议交互实践
  • 小巧的 MCPHost:命令行下实现 LLM 与外部工具交互
  • Git 2.53.0 Windows 安装与 SSH 免密配置详解
  • 小巧的 MCPHost:命令行大模型与外部工具交互指南
  • 2024 第十五届蓝桥杯省赛 C/C++ 大学 B 组题解
  • 前缀和算法详解:一维、二维及经典题目
  • AI 绘画姿态迁移:利用 M2FP 提取人体轮廓

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online