前一阵子在现场调试一套基于WinCC的上位机系统,画面里放了一个在线趋势控件,结果一运行就弹“许可证缺失”,按钮全灰没法操作。当时第一反应是授权没装好,可查了一圈西门子授权管理器,授权明明都在,后来才意识到问题出在WinCC ActiveX控件本身的许可证注册,而不是软件授权。顺着注册表和系统兼容性两条线查下去,才把问题彻底按死。
这篇东西不是教科书式的原理讲解,是我实际排查这个故障时走过的完整链路,包括注册表键值定位、权限修复、64位系统下的重定向问题,以及系统兼容性层面的坑。如果你也在WinCC画面里被ActiveX控件“许可证缺失”折磨,或者正在做上位机部署和运维,按我这套思路走一遍,大概率能省下两三天时间。
1. 故障现象盘点:许可证缺失报错在哪些场景最容易冒出来
1.1 控件类型与报错窗口的两种典型形态
先搞清楚对手是谁。WinCC里常见的ActiveX控件包括在线趋势控件WinCC OnlineTrendControl、报警控件WinCC AlarmControl、用户归档控件WinCC UserArchiveControl、函数趋势控件WinCC FunctionTrendControl,以及大量第三方或者自制的ActiveX控件。它们的共同点就是运行时需要从系统注册表读取许可证信息,读不到就罢工。
报错形态大概分两种:
- 设计态报错:在Graphics Designer里往画面拖控件时,直接弹出对话框,说控件的许可证缺失或者许可证无效,这个控件根本放不到画面上。
- 运行态报错:画面组态时一切正常,但项目激活运行后,控件区域出现红叉、灰块,或者弹一个“无法创建ActiveX控件”之类的错误。
这两种形态的排查方向不一样。设计态报错,大概率是控件的许可证键值没写入注册表,或者被清理工具干掉了。运行态报错则更复杂,有可能是权限不够、DLL注册状态异常、甚至兼容性设置把控件实例化给拦了。我这次遇到的问题就属于第二种,而且它是“时好时坏”的,开机第一次跑正常,运行一阵子再激活画面就报缺失。
1.2 哪些误操作会直接触发“许可证缺失”
结合我自己和身边同事踩过的坑,下面这些操作都很容易把ActiveX控件许可证弄丢:
- 使用各种“垃圾清理大师”清理注册表,ActiveX控件的License键经常被当成无效条目清掉。
- 把WinCC项目从一台机器拷贝到另一台机器,项目文件能拷过去,但控件DLL、OCX和对应注册表信息不会跟着走。
- 从32位系统往64位系统迁移,或者反过来,涉及注册表重定向问题,许可证键在另一个视图下面,程序读不到。
- 杀毒软件查杀或隔离控件文件,控件的DLL都没了,自然谈不上许可证。
- 长期用普通用户权限运行WinCC,许可证键值明明存在,但当前用户没有读取权限,程序就当成“缺失”。
- 某些远程桌面或终端服务会话中,ActiveX控件被会话隔离,也会出现类似提示。
你可能会问:产品授权(Net/License Key)都正常,为什么ActiveX控件还说缺许可证?这里的关键就是“许可证”这个词在不同层面的含义不一样。产品授权的License Key管的是软件能不能运行,而ActiveX控件要的许可是控件自身的许可信息,存在注册表里,跟软件授权没有一一对应关系。你就算把授权装得再全,注册表里的控件许可证没了,照样报错。
2. 许可证信息到底存在哪里:注册表相关机制拆解
2.1 ActiveX许可证机制与WinCC控件注册表键值分布
ActiveX控件本质是COM组件,当一个控件被设置为“Licensed”时,它必须在注册表里保存一条许可记录。操作系统或者应用程序创建控件实例时,会读取这条记录,验证是否有效。有效才允许创建,否则就返回“许可证缺失”。
这条许可记录通常放在注册表的Licenses键下面。打开注册表编辑器,一般能看到的路径类似:
HKEY_CLASSES_ROOT\Licenses
在这个键下面,每一个子键的键名就是控件的CLSID(Class ID,全局唯一类标识符),键值是一串编码后的许可证字符串。除了这里,许可证相关的信息有时也会出现在HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Licenses,以及HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Licenses等位置,不同操作系统、不同产品版本,分布差异很大。
WinCC在安装ActiveX控件时,安装程序会调用控件的自注册逻辑,把CLSID、TypeLib、License等条目写入注册表。正常情况下,这一系列动作是自动完成的。但如果安装过程被中断,或者安装时被安全软件拦截,控件注册到一半,CLSID有了,License键没有,后面使用时就报缺失。
明白了这个机制,你就能理解为什么有时候修复安装都没用:repair会把文件重新拷一遍,但如果它认为文件完整无损,就不一定会重新写入License键。这就是为什么遇到这种情况时,注册表层面的人工检查和修复往往是更直接的突破口。
2.2 注册表权限不足导致的“伪缺失”
还有一种更隐蔽的情况:键值明明在,但程序就是读不到。这种“伪缺失”多半是注册表权限问题。
Windows注册表的每个键都有自己的ACL(访问控制列表),不是所有用户都能读写所有键。有些ActiveX控件在安装时,许可证键只给了Administrator和SYSTEM完全控制权,普通Users组只有读取权,甚至没有读取权。如果你的WinCC是以服务方式运行,服务账户可能压根不在ACL里,那在运行时创建控件就会失败。
我之前就栽在权限上:注册表编辑器里打开Licenses键,清清楚楚能看到许可证字符串,但用普通域账户登录运行WinCC,就是报缺失。后来用Process Monitor一抓,发现控件进程对那个键的RegOpenKey操作被拒绝,Access Denied,问题一下就明朗了。
所以排查许可证问题,别只在“有没有键值”这个层面上纠结,还要看当前进程能不能访问到那个键。尤其那些在服务器上以服务方式跑WinCC的情况,服务账户一般比管理员账户权限更受限,更容易踩到权限坑。
2.3 排查前必须做的注册表备份和快照
在动手修改注册表之前,我强烈建议先做两件事:备份和监控。这不是走走形式,而是让你在改坏之后能原样滚回去。
先做注册表备份。如果只是打算动Licenses相关分支,可以在regedit里选中Licenses键,右键导出,保存为.reg文件。如果你拿不准要动哪些键,干脆在“文件”菜单里导出整个注册表,或者直接创建一个系统还原点。Windows系统还原点在修改系统配置之前创建,即使注册表改出问题,也能还原回去。
再做监控。Process Monitor这个工具是Sysinternals套件里的,能实时看进程对注册表、文件系统的每一项访问。排查ActiveX许可证问题时,建议添加两条过滤规则:进程名设为控件的主进程(比如WinCC激活后是S7-OCX相关的进程,或者BfsSvr、Scd_ocx等),路径包含“Licenses”。然后重新激活画面,让报错复现一次,Process Monitor会完整记录下进程到底访问了哪些键、哪一步被拒绝、哪一步返回了NotFound。有了这个日志,排查效率提升十倍。
3. 注册表修复实操:从备份、定位到导入分步走
3.1 手工备份注册表与导出键值:两种安全路径
真正的修复阶段,最稳妥的操作方式不是自己瞎写注册表,而是从另一台正常工作的机器上导出键值,再导入到故障机器。这样能保证键值内容的正确性。
这里有两个前提条件:
- 正常机器和故障机器必须装相同版本的WinCC和相同的Update Patch,最好操作系统位数也一致。
- 两台机器的Windows版本和语言最好也一致,避免系统级CLSID差异。
操作路径很简单:在正常机器上打开regedit,定位到HKEY_CLASSES_ROOT\Licenses,选中整个Licenses键,右键导出。导出范围选择“所选分支”,保存为.reg文件。因为这个分支里可能包含很多软件产品的许可证,不只是WinCC的,所以导出范围最小可控。
但注意,HKEY_CLASSES_ROOT整体内容可能比较大,导出时如果遇到权限不足的键,会被跳过。所以导出完成后,建议把文件大小和内容检查一下。如果只是想单独导出一个控件对应的键,也可以在OLE/COM Object Viewer里先查出控件的CLSID,再定位到对应的Licenses\CLSID键去导出。这个过程更精准,适合只处理单个控件的情况。
到了故障机器上,不要急着双击导入。先把导出的.reg文件内容用记事本打开看一眼,确认文件里的注册表路径和预期一致,里面没有明显异常内容。然后有两种导入方式:
- 图形界面:regedit -> 文件 -> 导入,选择这个.reg文件。
- 命令行:以管理员身份打开CMD或PowerShell,执行
reg import 路径\文件名.reg。
我习惯用命令行,因为能看到明确的返回信息。如果导入成功,命令行会提示“操作成功完成”。如果因为权限问题打不开某些键,这里也会报错,方便你进一步处理。
3.2 修复许可证的三种典型操作(修复、导入、赋权)
导入.reg文件只能解决“键值不存在”的问题。如果键值存在但权限不够,或者键值内容不完整,还要分情况处理。
第一,直接修复安装。如果你手里有WinCC安装介质,可以尝试在控制面板里选择WinCC对应的条目,点“更改/修复”,执行修复安装。修复安装会重新注册所有系统组件和ActiveX控件,也能把缺失的License键重新写进去。但这个操作前面说了,不一定百分之百有效,因为它主要检查文件完整性,而License键的写入依赖安装流程里的注册步骤,某些情况下会被跳过。
第二,手动导入键值。这个方法针对性强,适合从正常机器导出License键再导入的情况。导入之后最好重启一下机器,确保系统重新读取注册表。
第三,给键值赋权。如果当前用户对某个Licenses子键没有读取权限,可以在regedit里右键该键 -> 权限 -> 添加当前用户(或者对应的服务账户)并勾选读取权限。这里还有一个技巧:WinCC如果是以服务方式运行,服务账户通常是“LocalSystem”,而LocalSystem一般在键权限列表里已经存在,如果被单独拒绝,需要显式勾选允许读取。找到对应的账户,把“拒绝”勾去掉,或者重新配置权限。
赋权操作要谨慎,不要给Everyone完全控制权,只给读取权就够了。ActiveX许可证读取不需要写权限,运行期间一般也不写入,给完全控制反而引入了安全风险。
3.3 注册表重定向:64位系统下32位控件注册表的坑
很多WinCC控件是32位组件,即使WinCC软件本身看起来是64位安装,内部也有很多32位DLL。在64位Windows上,32位程序访问注册表时,系统会自动做重定向,把HKLM\SOFTWARE下的访问映射到HKLM\SOFTWARE\WOW6432Node这个视图里。这就导致一个很常见的坑:
你在64位注册表编辑器里看到的Licenses键,不等于32位程序看到的Licenses键。
排查时需要分两路看:
- 64位视图:
HKEY_CLASSES_ROOT\Licenses和HKEY_LOCAL_MACHINE\SOFTWARE\Licenses - 32位视图:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Licenses
你用regedit(64位版本)看的是64位视图,想看32位视图,可以运行C:\Windows\SysWOW64\regedit.exe,这个版本打开的注册表编辑器会见WOW6432Node下的内容。网上很多教程没说这一步,只教你打开注册表编辑器去看Licenses,结果很多用户找了半天找不到32位控件的许可证键。
所以当正常机器导出的.reg文件里路径是[HKEY_CLASSES_ROOT\Licenses\xxx],导入到64位系统时,regedit默认会写入64位视图。如果控件是32位的,它去读的是32位视图,那你导了等于白导。解决办法是先确认控件位数,使用SysWOW64版本的regedit导入,或者手动把.reg文件里的路径改成HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Licenses\xxx再导入。
3.4 修复后的验证方法
修复完别急着关窗口,验证是必须的。最简单的验证是打开WinCC的Graphics Designer,新建一个画面,把之前报错的控件拖进来,看是否正常创建。如果设计态正常,再激活运行跑一遍。
还有一个更底层一点的方法:用OLE/COM Object Viewer(oleview.exe)检查控件。这个工具在Windows SDK里能找到,打开后在“Object Classes”里找到“Grouped by CLSID”,搜索对应的CLSID,双击查看控件属性。如果界面上显示“Licensed”,说明许可证信息已经被系统识别了。如果显示“Not Licensed”,那说明许可证还是没到位,继续排查。
另外,用Process Monitor再抓一遍也是好办法。这次可以看到进程对Licenses键的访问结果不再是ACCESS DENIED或NAME NOT FOUND,而是SUCCESS,那就基本稳了。
4. 系统兼容性调优:问题往往不在注册表而在运行环境
4.1 兼容性设置的四步检查清单
注册表层面全部正常,许可证键也存在,权限也给了,控件还是报缺失,这时候十有八九是系统兼容性问题。WinCC的ActiveX控件本质上还是COM组件,Windows操作系统为了安全考虑,对COM组件的实例化有各种限制,尤其在高版本Windows上跑老版本的WinCC,更容易撞上。
可以按下面四步逐一检查:
第一步,右键WinCC图形设计器的运行程序(通常是GraphicsDesigner.exe,或者在WinCC项目的启动程序),进入“属性 -> 兼容性”,勾选“以兼容模式运行这个程序”,下拉框里选Windows 7。WinCC 7.x时代的主要开发系统还是Windows 7,在Windows 10或Server 2016/2019上运行老项目时,兼容模式能解决不少莫名奇妙的ActiveX问题。
第二步,勾选“以管理员身份运行此程序”。WinCC的很多操作需要管理员权限,ActiveX控件的许可证读取也需要访问注册表敏感区域。如果没有管理员权限,系统可能会用权限隔离的策略直接拦截。
第三步,关闭用户账户控制(UAC)。如果你为了让系统更安全,UAC一直拉到最高,COM组件的实例化也会被影响。这个不一定要全关,但可以尝试把UAC滑块拉到第二档(默认档),或者重启后再试。如果问题依旧,在“更改用户账户控制设置”里拉到最低,重启。
第四步,不要动数据执行保护(DEP)。有的老教程会教你把WinCC相关程序加入DEP例外列表,但在实际项目中,例外列表不一定生效,甚至会导致系统不稳定。我建议只要确认系统DEP是默认模式(仅对必要系统程序启用)就可以了,不需要额外排除。
4.2 运行库与系统组件缺失的补充安装
ActiveX控件在创建前,还会先加载一堆运行库。WinCC自带的控件依赖VC++运行库、MFC库、ATL库、.NET Framework。很多精简版Windows系统把这些组件精简掉了,或者安装顺序不对导致版本冲突。
维修现场最容易遇到的情况是:系统里只有一个新版的VC++ 2015-2022运行库,缺了老版本VC++ 2005/2008/2010。WinCC的老控件是在老编译器环境下构建的,运行时会去找它对应的运行库版本。找不到就报错,报错内容往往也是模糊的,有些甚至直接说“许可证缺失”,让人摸不着头脑。
解决办法很简单:把Visual C++运行库的合集装上,2005、2008、2010、2013、2015-2022都装一遍,x86和x64都装。反正这些运行库可以共存,没有冲突。同理,.NET Framework 3.5(包括2.0和3.0)也要确保启用,WinCC很多控件的托管代码依赖于.NET Framework 3.5。
如果系统是Windows Server版,还需要检查是否安装了“桌面体验”功能。Server Core模式下没有完整的图形界面组件,ActiveX控件大概率无法正常运行。这个在控制面板的服务器管理器中可以确认。
4.3 远程桌面/终端服务会话中的ActiveX控件特例
还有一种常见场景:调试人员不在现场,用远程桌面连到服务器上操作WinCC。这种环境下,ActiveX控件报许可证缺失的频率明显高于本地控制台。原因有两方面:
一是终端服务会话的注册表视图和本地会话不完全一致,某些COM组件在终端会话中被隔离,控件的许可证查询会失败。类似的情况在连接远程桌面服务时也会碰到,比如系统提示无法加载远程桌面的ActiveX控件,要求确保rdclientax.dll在路径中——那是远程桌面客户端自己的控件问题,但背后机制是一样的:ActiveX控件在非交互式会话中创建时,对注册表和系统状态的访问都会受限。
二是并发会话的中断,多个会话同时尝试创建同一个ActiveX控件时,许可证又没有做并发控制,可能相互踩踏,后创建的就拿不到许可证。
遇到这种情况,如果系统允许,建议在远程桌面会话里不做控件密集型操作,优先在本地控制台或者虚拟桌面里运行WinCC画面。如果必须远程,可以在组策略里设置“允许在终端服务会话中实例化ActiveX桌面控件”,或者给运行WinCC的用户开通“允许通过终端服务登录”的高级权限。但稳妥起见,还是本地运行优先。
5. 一次实战案例复盘与日常维护建议
5.1 案例:Win10 x64上WinCC控件“时好时坏”的完整排查链路
结合前面讲的,我复盘一个实际案例。
背景是一台Windows 10 Pro 64位工作站,安装WinCC V7.4 SP2,画面里用了WinCC OnlineTrendControl。现象是:系统刚重启后,第一次激活画面没问题,关掉画面再打开,趋势控件就变成红叉,日志里报“许可证缺失”。重启又正常,过一会儿又不行,非常随机。
排查链路:
第一步,看西门子授权管理器,所有授权都在,软件授权层面排除。
第二步,打开Process Monitor,在报错复现的瞬间抓取进程对注册表的访问。过滤条件:路径包含License。结果发现,控件进程第一次创建时访问的Licenses键是HKLM\SOFTWARE\WOW6432Node\Licenses\xxxx,返回SUCCESS。第二次再创建时,访问同一个键,返回KEY_NOT_FOUND。
这就奇怪了,键在,第二次却找不到。于是我在regedit里用SysWOW64版本打开32位视图,找到这个键,发现键值还在,但权限列表里有一项“该用户已被显式拒绝读取”。为什么会这样?后来查了系统日志,发现是这台机器装了安全软件,定时扫描时把某些注册表键的ACL给改了,加了拒绝条目。
第三步,手动编辑权限,把所有“拒绝”条目去掉,为当前用户和管理员组勾选完全控制(至少读取)。改完后再激活画面,恢复正常。
第四步,为了防再犯,我干脆把安全软件对WinCC安装目录和注册表Licenses键的扫描排除了。之后观察三周,没有再出现同样问题。
这个案例典型在于:它既不是真缺许可证,也不是注册表键值被清空,而是权限被安全软件篡改,造成“时好时坏”的假象。如果一开始就去重装系统或者重装WinCC,时间成本高,问题还不一定解决。Process Monitor + 注册表权限检查,半小时定位问题。
5.2 日常维护中防止许可证隐患的四个习惯
排查故障只是解决问题,真正省事的是让问题根本不发生。我自己在项目交付和运维中总结了几个习惯,效果不错。
第一,不用系统清理工具清理注册表。WinCC这类组态软件对注册表依赖非常重,市面上九成清理工具识别不了ActiveX许可证信息,很容易误删。宁可机器稍微乱一点,也不要去“优化”注册表。
第二,项目交付时,除了交付项目文件,还要附一份“运行环境清单”,写明WinCC版本、SP、补丁号、操作系统版本、必要的运行库列表。这样万一现场出问题,可以按清单核对环境,而不是到处摸索。
第三,定期备份注册表里的Licenses分支和CLSID分支。不用频繁,每次做完系统变更、打补丁、安装新控件之前,导出一次保存到本地备份目录。一旦出问题,直接导入旧键值就能回来。
第四,部署标准镜像。如果你们公司有多台相同配置的上位机,建议做一台基准机,把WinCC、控件、运行库全部装好,测试没有问题后做成系统镜像。后续机器全部刷镜像部署,能规避大量因为手动安装顺序不对导致的许可证问题。
5.3 如果所有修复都无效时的“终极大法”
讲了这么多常规手段,总有那么几次,所有检查都做了,键值存在,权限正常,运行库齐全,兼容性也设置了,控件还是报缺失。这时候我的终极大法就是干净卸载后重装WinCC。
但这里有个前提:干净卸载不是控制面板里点一下“卸载”就完事。WinCC涉及多个组件,包括WinCC本身、SQL Server、SIMATIC NET、消息运行时等,卸载顺序不对会留下一堆注册表残骸。理想顺序是:先把WinCC项目做完整备份,然后在控制面板中把WinCC相关的所有组件按依赖顺序逐一卸载,通常是从上层应用开始,到底层运行时和SQL Server结束。卸载完后重启,再用注册表清理工具(或者手搜)把和WinCC、Siemens相关的残留键删掉。这块工作量不小,所以前面才说“终极大法”。
如果时间实在紧张,还有一种办法是从正常机器上做一次完整系统克隆直接替换故障机的系统盘。这种方法在工业现场有时更高效,但要注意替换后Windows激活状态、主机名、IP地址都要重新设置,不能乱来。
最后说句实在话:ActiveX“许可证缺失”这个报错,百分之七八十都藏在注册表和系统环境里,真正需要重装的少之又少。遇到这种问题,不要急着去怀疑授权,先把Process Monitor打开,看看控件加载时到底读了哪些键,被谁拒绝了,往往比手动翻注册表更高效。这套排查思路不仅对WinCC有效,对其他工业组态软件里的ActiveX控件故障,一样通用。