- 桌面应用
- 游戏开发
【免费下载链接】GlosSI
Tool for using Steam-Input controller rebinding at a system level alongside a global overlay
本文围绕 GlosSI 官方使用文档 Usage.md 展开,覆盖安装(安装包与 zip 包)、快速上手、通过 GlosSIConfig 管理 Steam 快捷方式的"舒适用法",以及两套配置体系(Pre-Launch 配置与 GlosSI overlay 运行时配置)的具体操作。读完并结合源码路径(common/Settings.h、GlosSIConfig/UIModel.cpp)后,你可以独立完成 GlosSI 的部署,理解每个配置项/命令行参数的实际作用,并掌握 AppID 技巧等进阶玩法与日志排查方法。
一、GlosSI 解决什么问题
GlosSI(Global systemwide Steam Input,前身为 GloSC)是一个工具,让你可以在系统级使用 Steam-Input 手柄重映射,并获得一个系统范围(无边框窗口模式)的 Steam Overlay。其典型使用场景是:在 Windows Store(UWP)应用、模拟器等与 Steam-Input 不兼容的程序中使用 SteamController/SteamDeck 手柄。
从 Readme.md 可以看到其工作机制:GlosSI 提供一个可添加为 Steam "非 Steam 游戏"的目标程序GlosSITarget.exe,它把配置好的手柄输入重定向到一个系统级虚拟 Xbox 360 手柄(基于 ViGEm 驱动,见 GlosSITarget/InputRedirector.h),同时用一个置顶透明窗口承载 Steam Overlay。因此:
- 游戏不需要通过 GlosSI 启动(Quick usage 模式);
- 也可以通过 GlosSIConfig 让 GlosSI 替你启动游戏并管理多个快捷方式(Comfy usage 模式)。
同时,Readme 明确指出 GlosSI不是Steam 手柄配置工具的替代品,也不是远程游玩/串流方案;ViGEm 已宣布停止维护(EOL),Readme 也说明该项目已由后继项目 SISR 接替。阅读本指南时请留意这一项目现状。
二、安装
2.1 使用安装包(Installer)
官方流程只有一句话:"Install, Reboot, Go!"——安装、重启、开玩。
对照安装包脚本 Installer/Installer.nsi,可以确认安装包实际做了以下事情,这也是"必须重启"的原因:
- 主程序安装到
$PROGRAMFILES64\GlosSI(InstallDir定义,第 45 行),并写入开始菜单快捷方式(GlosSI.lnk与GlosSI-Target.lnk,第 147-148 行); - 依次执行三个驱动/运行时安装节(第 118-134 行):
Section "Visual Studio Runtime":静默安装vc_redist.x64.exe;Section "ViGEmBus Driver":运行ViGEmBusSetup_x64.exe(虚拟手柄总线驱动);Section "HidHide Driver":运行HidHideSetup.exe(真实设备隐藏驱动)。
ViGEmBus 与 HidHide 都是内核驱动,加载后需要重启才能对已运行的系统进程生效,所以文档要求重启。
2.2 使用 .zip 文件
如果使用 zip 包发布,按照 Usage.md 的步骤操作:
- 将 .zip 文件解压到电脑上任意目录;
- 安装
vc_redist_x64.msi(Visual C++ 运行时); - 安装
ViGEmBusSetup_x64.exe(ViGEm 虚拟手柄驱动); - 安装
HidHideSetup.exe(设备隐藏驱动); - 重启(必须!)。
完成以上步骤即可使用 GlosSI。
三、前置条件(Prerequisites)
在开始任何使用前,必须满足两个前置条件:
- 在 Steam 中启用 "XBox configuration support"(Steam 设置 → 控制器,即允许用 Xbox 配置方案);
- 保持 Steam 正在运行。
这一点有源码级佐证:GlosSITarget启动时会检查该设置,若未启用,会在 overlay 中弹出提示窗口要求你先去 Steam 设置中开启——见 GlosSITarget/SteamTarget.cpp(util::steam::getXBCRebindingEnabled检查 + "XBox Controller configuration support Disabled" 提示框)。
此外,GlosSIConfig 还提供了自动开启该开关的入口:UIModel::enableSteamInputXboxSupport()会定位 Steam 用户数据目录下的localconfig.vdf,把SteamController_XBoxSupport的值从0改为1——见 GlosSIConfig/UIModel.cpp。
四、快速上手(Quick usage,适合故障排查)
这是最简使用路径,只依赖 3 步:
- 在 Steam 中将
GlosSITarget.exe添加为非 Steam 游戏(Add a Non-Steam Game); - 为这个新快捷方式在 Steam 中设置手柄配置(Controller Configuration);
- 从 Steam 启动这个GlosSITarget快捷方式。
完成之后,你就可以像平常一样直接启动任何游戏/应用(不经过 GlosSI 启动器),获得全局 SteamInput 以及系统范围的 Steam Overlay。
重要限制(原文档加粗强调):
Overlay 仅在**无边框窗口(borderless window)**模式下生效,不支持独占全屏(exclusive fullscreen)。 在此模式下,Overlay 默认对 UWP(Windows Store)应用也不生效——除非你在启动后通过 GlosSI overlay 手动启用。
从源码结构看,这两条限制的底层原因分别是:
- 独占全屏时 Steam 自身的 Overlay 注入机制不工作(这是 Steam 侧的限制);
- UWP 应用的 overlay 需要额外的启用流程,
GlosSITarget内有专门的 GlosSITarget/UWPOverlayEnabler.h 模块在运行时对目标 UWP 窗口做处理,且可通过-disableuwpoverlay参数关闭(见下文命令行参数)。
GlosSITarget 启动后发生了什么
了解内部流程有助于排查问题。入口在 GlosSITarget/main.cpp:
- 单实例检查:
FindWindowA(nullptr, "GlosSITarget")发现已有实例时,会向http://localhost:8756的/quit端点发 POST 请求关闭旧进程——即GlosSITarget内置了一个本地 HTTP 服务器(GlosSITarget/HttpServer.h),这也是 Steam 侧脚本与其通信的通道; - 解析命令行与配置文件:
Settings::Parse(argsv),加载逻辑详见 common/Settings.h; - Steam 注入检测:
SteamOverlayDetector::IsSteamInjected()通过检查进程中是否加载了GameOverlayRenderer64.dll来判断是否由 Steam 启动——见 GlosSITarget/SteamOverlayDetector.cpp。若未被 Steam 注入,则进入实验性 "global mode"(全局模式),这也是"不经过 Steam 也能用"的底层来源; - 主循环:
SteamTarget::run()(GlosSITarget/SteamTarget.cpp)中持续运行detector_.update()(利用 Steam hook 窗口消息的副作用检测 overlay 开关,见 SteamOverlayDetector.cpp 中的PeekMessage逻辑)、更新 overlay 窗口,以及处理AppLauncher的进程监控。
五、舒适用法(Comfy usage):用 GlosSIConfig 管理快捷方式
"从 Steam 启动 GlosSITarget,再单独去启动游戏"这一流程繁琐,且每个快捷方式只能对应一套手柄配置。GlosSIConfig 提供图形化的快捷方式管理与配置功能,基本流程如下(原文档步骤完整保留):
- 启动
GlosSIConfig.exe; - 点击➕ 按钮添加一个由 GlosSI 管理的新快捷方式;
- 选择你希望 GlosSI 替你启动的应用类型:
- 选择UWP App:Windows Store 应用;
- 选择Win32 Program:传统桌面程序与游戏;
- 选择Add Manually:不想让 GlosSI 启动任何东西、或想稍后再配置游戏启动时使用。
- 如果选择了Add Manually,请输入该快捷方式想要的名称;
- 点击💾 Save 按钮;
- 点击➕ to Steam 按钮;
- 可选若要添加多个快捷方式,重复步骤 2-5;
- 重启 Steam;
- 在 Steam 中为新添加的快捷方式设置手柄配置;
- 在 Steam 中搜索并启动新添加的快捷方式。
完成之后,GlosSI 会替你启动游戏,并在其上方绘制 Steam Overlay(仅 borderless window 与 UWP),同时提供手柄输入重定向。
源码视角:"Save" 与 "to Steam" 到底做了什么
- Save:
UIModel::writeTarget()会把该快捷方式的全部配置写成 JSON 文件,保存在用户配置目录%AppData%\GlosSI\Targets\<名称>.json(目录解析逻辑见 common/util.h 的getDataDirPath(),返回Roaming\GlosSI;目标配置目录在 GlosSIConfig/UIModel.cpp 中初始化为Targets子目录)。 - to Steam:
UIModel::addToSteam()(GlosSIConfig/UIModel.cpp)会向 Steam 的shortcuts.vdf写入一条记录:exe指向 GlosSI 安装目录下的GlosSITarget.exe;StartDir若配置了启动路径则为游戏所在目录,否则为 GlosSI 目录;LaunchOptions为该快捷方式对应的<名称>.json文件名——这正是GlosSITarget启动时用来定位具体配置的参数;- 图标字段自动取游戏 exe 或 Steam Grid 图片路径,并追加
Installed locally与GlosSI标签。
- 写 VDF 失败时的 UAC 重试:
writeShortcutsVDF()若普通权限写shortcuts.vdf失败,会以runas方式自我提权重试(GlosSIConfig/UIModel.cpp),对应界面上可能弹出的管理员授权窗口。 - 重启 Steam:
UIModel::restartSteam()执行taskkill.exe /im steam.exe /f后重新拉起steam.exe(GlosSIConfig/UIModel.cpp)。 - UWP 列表来源:界面中的 UWP 应用清单由
UWPApps()调用 GlosSIConfig/UWPFetch.h 枚举系统包获得;launch.isUWP标志则由 common/Settings.h 的checkIsUwp()根据启动路径形态(是否包含盘符前缀)自动判定。 - 启动器本身:
GlosSITarget内的AppLauncher(GlosSITarget/AppLauncher.cpp)按类型分派:- Win32 程序走
CreateProcessW,遇到ERROR_ELEVATION_REQUIRED时自动改用ShellExecuteExW+runas提权重试(第 323-399 行); - UWP 包走 COM 接口
IApplicationActivationManager::ActivateApplication启动(第 401-447 行),因为 UWP 进程不属于 GlosSITarget,AppLauncher会通过遍历ApplicationFrameWindow并匹配PKEY_AppUserModel_ID来找到其窗口句柄(getProcessHwnds(),第 266-296 行); - URL/商店链接走
ShellExecuteExW(如 Epic Games 启动器场景)。
- Win32 程序走
六、配置详解(Configuration)
6.1 启动前配置(Pre-Launch,GlosSIConfig)
GlosSIConfig 提供了相当多的配置项用于按喜好调整功能、以及辅助排查问题。大多数选项旁边都有一个?按钮,会给出该选项作用的简短说明。
不必过于纠结高级选项——官方默认值对绝大多数支持的用例都够用(sane defaults)。
6.2 运行时配置(On-the-fly,GlosSI overlay)
GlosSIConfig 中可用("几乎全部")的配置项,都可以在运行时通过GlosSI overlay修改:
- 打开/关闭 GlosSI overlay 的方式:快速连续两次打开并关闭 Steam Overlay;
- GlosSI overlay 支持手柄按键导航。
6.3 配置文件结构与默认值
GlosSITarget 的每个快捷方式对应一个 JSON 配置(%AppData%\GlosSI\Targets\<名称>.json),无参启动时则回退到default.json(解析逻辑见 common/Settings.h)。各字段的默认值定义在 common/Settings.h 的结构体中,与 GlosSIConfig 生成默认配置时的取值(GlosSIConfig/UIModel.cppgetDefaultConf())一致:
{ "version": 1, "launch": { "launch": false, // 是否由 GlosSITarget 代为启动应用 "launchPath": null, // 启动目标路径(exe / UWP 包名 / URL) "launchAppArgs": null, // 传递给应用的参数 "closeOnExit": true, // 被启动的应用退出后 GlosSITarget 是否随之退出 "waitForChildProcs": true, // 是否跟踪子进程树(游戏通过子进程启动时很关键) "ignoreLauncher": true, // 忽略启动器进程(如 Epic 启动器)自身 "killLauncher": false, // 是否结束启动器进程 "launcherProcesses": [] // 额外的启动器进程名列表 }, "devices": { "hideDevices": true, // 用 HidHide 对目标应用隐藏真实手柄 "realDeviceIds": false }, "window": { "windowMode": false, "maxFps": 0, // overlay 窗口帧率上限 "scale": 0.0, // overlay 缩放 "disableOverlay": false, // 完全禁用系统级 overlay 窗口 "hideAltTab": true, // 从 Alt+Tab 列表中隐藏 overlay 窗口 "disableGlosSIOverlay": false, "opaqueSteamOverlay": false }, "controller": { "maxControllers": -1, // 最多虚拟化的手柄数量(-1 为不限制) "allowDesktopConfig": false, "emulateDS4": false, // 是否模拟 DS4 而非 Xbox 手柄 "updateRate": 144 // 输入重定向轮询率(Hz) }, "steamPath": "<Steam 安装目录>", "steamUserId": "<Steam 用户 ID>", "globalModeGameId": "", // 全局模式使用的 GameID "globalModeUseGamepadUI": true, "minimizeSteamGamepadUI": true, "extendedLogging": false, "name": "<快捷方式名>", "icon": null }其中与 "设备隐藏" 相关的能力依赖 HidHide:真实手柄对被启动的游戏进程隐藏(devices.hideDevices,对应 common/HidHide.h),让游戏只看到 ViGEm 虚拟出的 Xbox 手柄,从而彻底走 Steam-Input 链路;ViGEm 虚拟手柄的创建、震动回调等实现在 GlosSITarget/InputRedirector.cpp。
6.4 GlosSITarget 命令行参数
Steam 快捷方式的 "Launch Options" 或手动启动时,GlosSITarget支持以下命令行开关(完整定义见 common/Settings.h):
| 参数 | 效果 | 对应配置项 |
|---|---|---|
-window | 使用窗口化 overlay 模式 | window.windowMode = true |
-disableuwpoverlay | 禁用 UWP overlay 自动处理 | common.no_uwp_overlay = true |
-disablewatchdog | 禁用 watchdog 机制 | common.disable_watchdog = true |
-ignorelauncher | 忽略启动器进程 | launch.ignoreLauncher = true |
-extendedLogging | 开启扩展日志 | common.extendedLogging = true |
-globalModeUseGamepadUI | 全局模式使用 Gamepad UI | common.globalModeUseGamepadUI = true |
-disallowGlobalMode | 禁止实验性全局模式(未从 Steam 启动时直接不可用) | common.allowGlobalMode = false |
注意解析优先级:先加载 JSON 配置文件,再依次应用命令行开关(common/Settings.h),即命令行参数可以覆盖配置文件。另外,若命令行中出现了不属于上述开关的参数,会被当作配置文件名(自动补.json后缀),在%AppData%\GlosSI\Targets\下查找;找不到时回退default.json。
七、实用技巧(Neat tips and tricks)
7.1 用 AppID 技巧解锁社区手柄配置
想让 GlosSI 托管的游戏用上** Steam 社区共享的手柄配置**(比如游戏在 Epic 或其他商店购买)?做法:
把 Steam 中的快捷方式重命名为该游戏的 Steam AppID。这样 Steam 会把它当作该 AppID 来匹配社区配置。社区配置可能仅在启动快捷方式之前可获取。AppID 可通过公开的 Steam AppID 查询站点(如 SteamDB、Steambase)获得。
实现层面,GlosSIConfig 会用 AppID 构造完整的 Steam GameID——UIModel::getGameId()的算法是((uint64)appid << 32) | ((uint32)2 << 24),其中2表示SteamLaunchableType::Shortcut,见 GlosSIConfig/UIModel.cpp;isInSteam()/getAppId()(第 165-199 行)则通过遍历shortcuts.vdf中exe包含glossitarget.exe的条目来反查 AppID。
7.2 日志排查
原文档将 Quick usage 标注为 "Handy for troubleshooting",其价值在于:出问题时可以把问题隔离到"Steam + GlosSITarget"这一最小链路。配合源码中的日志设施排查:
GlosSITarget的日志默认写入%AppData%\GlosSI\glossitarget.log(GlosSITarget/main.cpp),并同步到控制台与 overlay 内的日志窗口(OverlayLogSink);- 加
-extendedLogging参数可获得更细粒度的进程/消息跟踪(common/Settings.h); - 仓库还提供了两个辅助脚本 tail_config_logs.ps1 与 tail_target_logs.ps1,用于实时滚动查看 GlosSIConfig 与 GlosSITarget 的日志;
- 崩溃时
GlosSITarget会在同一数据目录生成glossitarget.dmp内存转储(GlosSITarget/main.cpp 的Win32FaultHandler),可供进一步分析。
八、小结
- 安装:安装包一键完成(VS 运行时 + ViGEmBus + HidHide 驱动),zip 方式需手动装齐三者后必须重启;
- 最小链路:把
GlosSITarget.exe加为非 Steam 游戏 → 配手柄方案 → 从 Steam 启动,即可获得全局 SteamInput + 系统级 Overlay(仅 borderless window); - 舒适链路:GlosSIConfig 添加快捷方式(UWP / Win32 / 手动)→ Save → to Steam → 重启 Steam → 配手柄方案;
- 配置:Pre-Launch(GlosSIConfig,JSON 存于
%AppData%\GlosSI\)与 On-the-fly(双开 Steam Overlay 呼出 GlosSI overlay)两套体系,关键参数默认值与命令行覆盖机制均有源码依据; - 技巧:快捷方式重命名为 Steam AppID 可获取社区手柄配置;日志与 dump 文件位于
%AppData%\GlosSI\下,配合-extendedLogging排查问题。
- 桌面应用
- 游戏开发
【免费下载链接】GlosSI
Tool for using Steam-Input controller rebinding at a system level alongside a global overlay
相关推荐
GlosSI 全局 Steam-Input 实现解析:虚拟手柄、系统级 Overlay 与 Steam 快捷方式管理
GlosSI 全局 Steam Input 实现解析:虚拟手柄、系统级 Overlay 与 Steam 快捷方式管理 GlosSI(前身 GloSC,Globa
桌面应用游戏开发Ultralytics 快速入门完全指南:安装方式、CLI/Python 双接口实战与全局配置详解
Ultralytics 快速入门完全指南:安装方式、CLI/Python 双接口实战与全局配置详解 Ultralytics YOLO(本仓库 ultralyti
人工智能深度学习计算机视觉预训练nestjs-i18n与视图引擎集成:EJS、Handlebars和Pug实战教程
nestjs i18n与视图引擎集成:EJS、Handlebars和Pug实战教程 nestjs i18n是NestJS框架的国际化模块,能够帮助开发者轻松实现
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考