VC6.0在Win7/Win10添加文件失效与FileTool.dll修复
简介:面向仍在使用 Visual C++ 6.0 的开发者与维护旧项目的技术人员,这份 FileTool 插件资料针对 Windows 7/10 环境下 VC6 无法正常打开文件、添加工程文件的问题,提供可注册的 Developer Studio 附加项及完整源码。压缩包共 51 个文件,约 4.9MB,包含 4 个 cpp 源文件、6 个 h 头文件,以及 dll、lib、exp、tlb 等编译产物,另有 dsp/dsw 工程文件、rc/rc2 资源脚本、bmp 工具栏位图和 obj、pdb、sbr 等调试中间文件,Debug 与 Release 目录中均留有已生成版本,便于直接使用或二次编译。资源已有 447 人浏览学习,适合需要快速恢复 VC6 文件菜单功能、研究 Add-in 插件实现机制或补齐旧工程构建环境的读者。完整工程结构与编译输出一并保留,可对照头文件、命令实现和资源定义理解插件组成,也为排查注册失败、版本不匹配等问题提供参考。
1. 在 Win7/Win10 上打开 VC6.0,把 .cpp 从资源管理器拖进 FileView,光标变成一根竖线,松手——什么都没发生
右键点工程节点,也找不到Add Files to Project这一项。于是加十个文件,要么一个一个走Project > Add To Project > Files...,要么关掉 IDE 手工改.dsp里的SOURCE=行,改完还得祈祷格式没写歪。这个场景里,FileTool.dll 就是补那条断掉的路:把它注册成 VC6.0 的 Add-in,工程节点右键和工具栏上会多出Add File to Project与Add File to Project (Copy)两个入口,支持一次多选、自动换算相对路径,还能顺手把外部文件复制进工程目录。它不提升编译速度,也不改代码,纯粹解决"加文件"这一件小事——但恰恰是这件小事,在老工程迁移、跨平台系统整理源码时天天卡人。下面从拖放为什么失灵讲到注册表兜底、批量补SOURCE行的脚本,以及四条用坏过工程文件的血泪经验。
2. 拖放失灵不是灵异事件:VC6.0 在 Win7/Win10 上的文件添加链路
先把"为什么坏"讲清楚,后面装 FileTool 才知道每一步在补什么。很多人第一反应是 VC6.0 太老、Windows 不兼容,这个判断只对了一半:VC6.0 本身在 Win10 上跑得动,编译 32 位 MFC 工程也正常,真正断掉的是"从外部把文件塞进工程"这条交互链路,而它由三个互相独立的环节组成,任何一环出问题,表现都是"没反应"。
2.1 拖放这条链路上断在哪一环
VC6.0 的 FileView 是一个 OLE 拖放目标,启动时调用RegisterDragDrop把自己的窗口注册成IDropTarget,资源管理器作为拖放源,在鼠标松开时把文件列表投递过来。这套机制在 Windows 2000/XP 时代靠的是同一完整性级别下的进程间消息,而 Win7 引入 UIPI(用户界面特权隔离)之后,低完整性级别的进程不能向高完整性级别的窗口投递这类消息。反过来,很多人为了让 VC6.0 能往Program Files下写文件,把快捷方式设成"以管理员身份运行",VC6.0 的完整性级别被拉高,资源管理器还是普通权限,拖放直接被拦在窗口外面——于是出现两种互相矛盾的传言:有人说"管理员运行就修好了拖放",有人说"管理员运行反而拖不进去"。
实际情况取决于当前会话的提权状态、资源管理器是否以管理员身份重启过、以及 VC6.0 是否被设了兼容模式,组合起来就是一个玄学问题。我在三台机器上试过同一份 DLL、同一个工程,一台能拖、两台不能,最后放弃判断规律。结论很实用:不要试图修复拖放,绕开它。FileTool 走的是自己弹的文件选择对话框,压根不碰IDropTarget,所以它对完整性级别不敏感。
2.2 原生菜单能不能用,取决于对话框实现
有人会问:VC6.0 本来就有Project > Add To Project > Files...,为什么还要插件?能用,但不稳。这个菜单弹的是系统 shell 文件对话框,在高版本 Windows 上会去加载所有已注册的 shell 扩展——云盘同步、压缩软件预览、PDF 缩略图、右键菜单增强,任何一个写得不好的扩展都能让对话框卡住十几秒甚至直接无响应。老工程里文件多、目录深,卡一次就够烦的。
另一个现实问题是操作路径太长。Project > Add To Project > Files...每次只能从一个目录里选,加完一组头文件再加一组源文件,中间要重新定位目录;而 FileView 里对着工程右键直接加,是所有人从 VC6.0 时代就形成的肌肉记忆,插件恢复的正是这个习惯。所以 FileTool 的价值不在于"提供 VC6.0 没有的功能",而在于把一条又长又不稳的路径,换成一条短且不依赖 shell 的路径。
2.3 FileTool 补的到底是哪一段
FileTool.dll 是一个标准的 VC6.0 Add-in:一个 32 位 COM 组件,导出DllRegisterServer/DllUnregisterServer,注册时往 DevStudio 的AddIns分支写三个值——DisplayName、Description、Filename,其中Filename是 DLL 的绝对路径。VC6.0 启动时读这个分支,把列出来的 Add-in 加载进进程,插件再通过 IDE 暴露的接口往菜单和工具栏上挂命令。
它的核心动作非常朴素:弹一个文件选择框,拿到文件列表后,直接以文本方式读写工程文件(.dsp),在每个编译目标下插入# Begin Source File/SOURCE=/# End Source File三行,然后通知 IDE 刷新 FileView。没有二进制格式、没有数据库、没有隐藏状态——这意味着两件事:第一,它跟系统版本几乎无关,只要 DLL 能加载、注册表路径正确就能用;第二,它做的事你自己也能用脚本做,只是它把交互做顺了。理解这一点,后面遇到"加了文件但编译不过"就知道该去看.dsp,而不是怀疑插件。
提示:
.dsp是纯文本工程文件,.dsw只是工作区索引。任何"文件加进去了但 FileView 不显示"的问题,九成能在.dsp里找到答案。
2.4 动手前的三分钟环境体检
在注册之前先确认几个前置条件,能省掉后面一半的排错时间。下表是我每次换机器都会走一遍的检查项:
| 检查项 | 期望状态 | 查看方式 |
|---|---|---|
| 系统位数 | 64 位需用 SysWOW64 下的 regsvr32 | 系统属性,或命令行echo %PROCESSOR_ARCHITECTURE% |
| DLL 存放路径 | 纯 ASCII、无空格、非Program Files | 资源管理器地址栏 |
| DLL 位数 | 必须 32 位 | dumpbin /headers FileTool.dll看 machine 是否为 x86 |
| 当前用户权限 | 注册那一步需要管理员 | 命令行标题是否带"管理员" |
| 工程文件备份 | .dsp已有副本 | 复制一份.dsp.bak |
| 兼容模式 | 建议先取消,注册成功后再试 | 快捷方式属性 → 兼容性 |
路径这一项尤其关键。放在C:\Program Files (x86)\...下,注册表里写进去的路径带空格还能勉强工作,但一旦触发 UAC 虚拟化,regsvr32读到的路径和实际加载的路径就可能不是同一个,表现是"注册成功了但 VC6.0 里看不到菜单"。我一般统一放在D:\DevTools\VC6Addins\这类短路径下,全团队用同一个位置,后面写部署脚本时不用改参数。
3. 注册成 Add-in:把 FileTool.dll 挂到 VC6.0 的四个动作
这一章是全程最需要小心的部分,因为出错信息都很模糊——regsvr32只回一个错误码,VC6.0 加载失败则完全不提示,菜单就是不出现。所以每一步都要有明确的"做完了怎么确认"。
3.1 放置 DLL:路径选择的三个硬性约束
先把 DLL 从压缩包里解出来,放到一个固定的、全团队一致的目录,比如D:\DevTools\VC6Addins\FileTool.dll。三条约束值得单独强调:
第一,不要放在桌面或用户目录下。多用户机器上,A 用户注册的路径在 B 用户登录后可能不存在,或者指向另一个人的目录;更麻烦的是域环境下用户目录被重定向,路径会变。第二,不要放在网络盘或同步盘。VC6.0 启动时同步加载 Add-in,网络盘断连会让 IDE 启动卡住十几秒,同步盘在后台改文件会让 DLL 加载失败。第三,路径不要含中文。注册表里写的是宽字符,理论上没问题,但regsvr32在部分系统上对命令行参数编码处理不一致,带中文的路径有一定概率解析成乱码,然后报"找不到模块"。
放好之后,顺手确认一下文件的只读属性。从压缩包解出来的 DLL 经常带着只读标记,某些安全软件会因此在加载时静默拦截。
3.2 regsvr32 注册与错误码判读
打开管理员命令行,用 64 位系统上 SysWOW64 目录下的 32 位regsvr32执行注册。这一条最容易翻车:直接敲regsvr32,在 64 位系统上命中的是System32下的 64 位版本,它加载 32 位 DLL 会直接失败。
:: 64 位系统:必须显式使用 SysWOW64 下的 32 位 regsvr32 C:\Windows\SysWOW64\regsvr32.exe /s "D:\DevTools\VC6Addins\FileTool.dll" :: 检查返回码,0 表示 DllRegisterServer 返回成功 echo %ERRORLEVEL% :: 需要卸载时加 /u :: C:\Windows\SysWOW64\regsvr32.exe /u "D:\DevTools\VC6Addins\FileTool.dll"/s是静默模式,不弹成功提示框,适合写进脚本;第一次装建议不加/s,让弹窗把成功或失败明说一遍,确认没问题后再改成静默。返回码含义如下:0x80070005是拒绝访问,说明DllRegisterServer要写HKLM,当前命令行没有提权,换管理员终端重来;0x8007007E是找不到模块,通常是 DLL 位数不对或者依赖的 CRT 运行库缺失,用dumpbin /headers确认 machine 类型;0x80004005是未指定错误,多半是 DLL 路径里有特殊字符或被安全软件拦了写注册表;0x8007000B是"试图加载格式不正确的程序",同样是位数问题。
注册成功后,注册表里应该能看到对应的AddIns子键。用reg query快速核对,比打开注册表编辑器快:
:: 分别查 HKCU 和 HKLM 两个分支,不同版本写入位置可能不同 reg query "HKCU\Software\Microsoft\DevStudio\6.0\AddIns" /s reg query "HKLM\Software\Wow6432Node\Microsoft\DevStudio\6.0\AddIns" /s第二条命令里的Wow6432Node是 64 位系统给 32 位程序做的注册表重定向。VC6.0 是 32 位程序,它读HKLM\Software\...\DevStudio时会被系统自动转到Wow6432Node下,所以手工检查时必须带上这一层,否则会误判成"没写进去"。
3.3 在 Add-In Manager 里勾选并确认落点
注册只是让 VC6.0 "知道有这个插件",还需要在 IDE 里启用一次。启动 VC6.0,走Tools > Customize,切到Add-ins and Macro Files标签页。如果注册表写对了,列表里应该出现 FileTool 对应的条目,前面有个复选框。
这里有个细节:列表里可能显示的是Description字段的内容,而不是文件名,所以看到一行陌生描述不要以为是别的软件。如果列表里没有,点Browse手动选中 DLL,效果等同于写注册表。勾选后点Close,菜单栏或工具栏上应该立刻多出Add File to Project相关项;有些版本是挂在工程节点的右键菜单里,需要先在 FileView 里点一下工程名才能看到。
确认落点的方法:随便打开一个测试工程,右键工程根节点,看菜单里有没有新增项;没有的话,把 VC6.0 完全退出再启动一次——Add-in 是在 IDE 启动阶段加载的,Close之后的热加载不一定对所有版本生效。
注意:如果 VC6.0 是以兼容模式(比如 Windows XP SP3)运行的,注册表会被虚拟化重定向到
HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags相关的影子位置,Add-in 列表大概率是空的。这种情况先取消兼容模式,把注册跑通,再决定要不要加回来。
3.4 注册表兜底:手写 AddIns 键
regsvr32报错又查不出原因时,别在那儿反复试了,直接手写注册表。这是最快的一条后悔药,也能验证问题到底出在注册环节还是加载环节。
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\AddIns\FileTool.AddIn] "Description"="Add files to project" "DisplayName"="FileTool" "Filename"="D:\\DevTools\\VC6Addins\\FileTool.dll"保存成.reg文件后双击导入。三个值里只有Filename是关键,必须是绝对路径且用双反斜杠转义;DisplayName决定 Add-In Manager 里显示什么名字;Description只是说明文字,可以随便写。子键名FileTool.AddIn也可以换成别的,只要不跟已有项冲突。
写HKCU而不是HKLM的好处是不需要管理员权限,缺点是只对当前用户生效。团队分发时我一般两个都写:HKCU保证普通权限下能用,HKLM\Software\Wow6432Node\...保证新用户登录后开箱可用。手工导入后重启 VC6.0,如果菜单还是不出现,说明问题不在注册表——大概率是 DLL 本身加载失败,用dumpbin /dependents看依赖,或者干脆换个路径再试一次。
4. 往工程里加文件:两个菜单项、路径规则和批量脚本
插件挂上之后,真正的活才开始。这一章讲清楚两个菜单项的差别、.dsp被改成什么样,以及文件多到几十个时怎么用脚本收尾。
4.1 Add File to Project 与 Add File to Project (Copy) 的差别
两个入口只差一个词,行为完全不同,用错会打乱整个源码目录结构。
| 菜单项 | 对源文件的影响 | 写进.dsp的路径 | 适用场景 |
|---|---|---|---|
| Add File to Project | 原文件不动,只建立引用 | 相对.dsp所在目录,跨盘时退化为绝对路径 | 文件本来就在工程目录树内,日常开发 |
| Add File to Project (Copy) | 复制一份到工程目录,再引用副本 | 指向复制后的副本 | 从别处临时拿来的文件,需要纳入版本管理 |
第一种是绝大多数情况该用的。第二种的实际行为是"把外部文件搬进来",文件一旦复制过去,你的源码目录里就多了一份副本,两边同时修改就开始互相覆盖。我在一个跨平台系统项目里吃过这个亏:同事用 Copy 模式把十几个公共头文件复制进工程,结果工程里编译的是副本,公共库里改的东西完全没生效,查了半天以为编译缓存有问题。后来统一规定:只要文件在同一个仓库里,一律用第一个菜单项,Copy 模式只在"从工程外部一次性引入且不打算再维护同步"时使用。
还有一个隐含差别:Copy 模式复制到哪个目录,取决于弹框里的当前目录和你选中的目标,不同版本表现不完全一致。落盘之前先看清楚对话框上显示的路径,别闭着眼点确定。
4.2.dsp里 SOURCE 行是怎么被改的
理解这一步,出问题才知道去哪儿看。.dsp是纯文本,源文件列表长这样:
# Begin Source File SOURCE=.\src\main.cpp # End Source File三个要点。第一,路径基准是.dsp文件所在目录,不是当前工作目录,也不是 IDE 的什么隐藏设置。所以.\src\main.cpp表示.dsp同级src目录下的main.cpp。写错基准是"文件加进去了但一编译就报找不到"的头号原因。第二,VC6.0 里所有源文件和头文件写在同一个 SOURCE 列表里,FileView 显示时按扩展名自动分组,不需要你手工往"Header Files"组里放。第三,.dsp里每个编译目标(Win32 Debug、Win32 Release)各有一份独立的 SOURCE 列表,都夹在# Begin Target和# End Target之间。插件会往每个 Target 都插一遍,手工改的时候如果只改了一份,就会出现 Debug 能编、Release 报找不到文件的怪事。
这就是为什么我不推荐手工编辑.dsp:文件一多,漏改一个 Target 极难发现,而且.dsp被写坏之后没有后悔药,只能从版本库回滚。
4.3 用脚本批量补齐 SOURCE 行
插件一次能多选,但面对"把整个src目录下新增的几十个文件全部纳入工程"这种事,还是脚本更稳。下面这段脚本读.dsp、扫描源目录、找出还没被引用的文件,然后插到每个 Target 的末尾之前。
import os, re, shutil, datetime DSP = r"D:\Work\DemoApp\DemoApp.dsp" # 目标工程文件,必须是绝对路径 SRC_DIR = r"D:\Work\DemoApp\src" # 需要扫描的源码根目录 EXTS = (".cpp", ".c", ".h", ".rc", ".idl") # 按需增删 def norm(p): return os.path.normcase(os.path.abspath(p)) def main(): base = os.path.dirname(os.path.abspath(DSP)) # 用 mbcs 读写,保证 .dsp 里的 ANSI 中文注释不被破坏 raw = open(DSP, "r", encoding="mbcs", errors="strict").read() # 1. 收集已存在的 SOURCE 条目,统一转成绝对路径比较,避免 .\ 和 ..\ 混写漏判 have = set() for line in raw.splitlines(): m = re.match(r"\s*SOURCE\s*=\s*(.+?)\s*$", line, re.I) if m: have.add(norm(os.path.join(base, m.group(1)))) # 2. 扫描目录,找出未纳入的文件 missing = [] for root, _, files in os.walk(SRC_DIR): for name in files: if not name.lower().endswith(EXTS): continue full = os.path.abspath(os.path.join(root, name)) if norm(full) not in have: missing.append(full) if not missing: print("nothing to add") return # 3. 换算成相对 .dsp 的路径;跨盘时 relpath 会抛 ValueError,退回绝对路径 block = [] for full in missing: try: rel = ".\\" + os.path.relpath(full, base).replace("/", "\\") except ValueError: rel = full block += ["# Begin Source File", "", "SOURCE=" + rel, "# End Source File"] # 4. 备份,然后从后往前插入到每个 "# End Target" 之前 stamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S") shutil.copy2(DSP, DSP + ".bak." + stamp) lines = raw.splitlines() marks = [i for i, l in enumerate(lines) if l.strip().lower() == "# end target"] for i in reversed(marks): lines[i:i] = block open(DSP, "w", encoding="mbcs", newline="\r\n").write("\n".join(lines) + "\n") print("added %d files, backup=%s.bak.%s" % (len(missing), DSP, stamp)) if __name__ == "__main__": main()几处值得解释的参数和行为。EXTS决定扫描范围,如果工程里有自定义扩展名(比如某些编译器用的.cp),加进去即可,但别把.txt、.md这类也写进去,否则 FileView 里会冒出一堆非编译文件。encoding="mbcs"是关键,.dsp是 ANSI 编码,直接按 UTF-8 读会在遇到中文注释时报解码错误,按 UTF-8 写回则会把整个文件的中文注释变成乱码,工程注释全毁。
插入位置那一步更不能想当然。追加到文件末尾是错的——.dsp的最后几行是# End Target和# End Project,SOURCE 块必须夹在# End Target之前,否则 VC6.0 打开工程时可能提示工程损坏。脚本先收集所有# End Target的行号,再从后往前插,保证前面插入不会让后面的行号失效;同时因为遍历了所有 Target,Debug 和 Release 两份列表都会被补上。
备份那一步不要省。.dsp被写坏之后 VC6.0 打不开工程,报的错通常只有一句"工程文件格式无效",没有行号没有原因。留一份带时间戳的.bak,两秒钟就能回到原状。
4.4 加完之后的三个验证动作
跑完脚本或点完菜单,不要直接开始写代码,按顺序做三个检查。第一,关掉工程重新打开,看 FileView 里文件是否齐全、有没有重复条目。热加载有时候不刷新,肉眼看不准。第二,全编译一次,重点看链接阶段有没有"重复定义"和"找不到源文件"。重复定义通常意味着同一个文件被加了两次(一次带.\前缀,一次不带),脚本里统一转绝对路径比较就是为了防这个。第三,看.dsp的修改时间有没有被版本控制工具标出来,确认改动落在你预期的文件上——有些工程会把.dsp拆成多个,或者用.dsw引用了别处的.dsp,改错文件是常见乌龙。
注意:如果团队里有人用外部编辑器(比如另一款 IDE 或者纯文本编辑器)改同一个
.dsp,改之前先确认文件没被占用。VC6.0 打开工程期间会持有句柄,脚本写入会抛权限错误。
5. 避坑:四条翻车记录与现象到原因的对应表
这一章的四条都来自真实踩过的坑,按"现象、原因、解决"的顺序写,遇到对应症状可以直接跳过推导。注册类工具的麻烦之处在于错误信息太少,看着像同一件事,根因可能完全不同,所以定位方式比结论更重要。
5.1 现象:菜单出现了,点一下没反应或者弹一个空错误框
原因:两种可能。一是注册表里Filename指向的路径和你实际放 DLL 的路径不一致——常见于先注册后挪文件,或者从别人机器上拷了注册表项过来忘了改路径。二是 DLL 是 64 位的,regsvr32成功了,但 VC6.0 是 32 位进程,加载时直接失败,IDE 不会给任何提示,只是把菜单项画出来、点了什么都不发生。
解决:先用dumpbin /headers FileTool.dll看machine字段,出现x86才对,出现x64或ARM64就换一份。再看reg query输出的Filename,逐字符和dir出来的实际路径对一遍,特别注意盘符和反斜杠。两者都对还没反应,用Process Monitor过滤Path包含FileTool的事件,看 VC6.0 到底在找哪个路径的文件、返回的是NAME NOT FOUND还是ACCESS DENIED——这是排查加载类问题的黑匣子,比猜快得多。
5.2 现象:regsvr32报 0x80070005,或者提示"对指定的模块找不到"
原因:0x80070005是权限问题,说明这个 DLL 的DllRegisterServer要写HKLM,而你用的是普通权限命令行。后半句"找不到指定的模块"经常和权限错误一起出现,容易被误解成路径写错——实际上路径对、只是没有写权限时,某些系统上也会报这句。
解决:换成管理员命令行重跑。如果公司策略不允许提权,改用 3.4 节的手写注册表方案,只写HKCU,效果一样,只是对当前用户生效。还要注意别在普通权限下注册到一半、提权后又注册一次,两次写入位置不同会在注册表里留下两条重复项,Add-In Manager 里出现两个同名条目,勾哪个都不对——出现这种情况先把两个分支都清掉再重来。
5.3 现象:文件明明加进去了,一编译就报"Cannot open source file"
原因:.dsp里写的路径基准算错了。相对路径是相对.dsp所在目录,不是相对解决方案目录、也不是相对当前打开的源文件目录。有人习惯用..\..\common\foo.cpp这种深跳路径,工程换个位置放就全断。另一种情况是只在一个 Target 里插了 SOURCE 行,切到 Release 配置后列表是空的。
解决:打开.dsp直接搜文件名,看写进去的到底是相对路径还是绝对路径;对着.dsp所在目录手工拼一遍验证。批量脚本按 4.3 那样遍历所有# End Target就不会漏 Target。工程结构复杂时,宁可让脚本写绝对路径:可移植性差一点,但至少不会在编译阶段才暴露,等确定目录结构稳定了再改回相对路径。
5.4 现象:装上之后 VC6.0 启动变慢,或者启动到一半直接退出
原因:Add-in 是在 IDE 启动阶段同步加载的,DLL 放在网络盘、同步盘、或者被杀毒软件实时扫描的目录下,加载会被拖住。更糟的情况是 DLL 与某个已安装的其他 Add-in 冲突,或者兼容模式下注册表被虚拟化,VC6.0 读到一条指向不存在路径的记录,反复重试加载。
解决:先把 DLL 换到本地纯 ASCII 短路径,重新注册一次。还有问题就在启动前临时把AddIns下其他项备份后删除,逐个加回,看是哪两个冲突。兼容模式那一条单独强调:兼容模式和 Add-in 经常不能共存,如果之前为了修拖放勾了"以 Windows XP 兼容模式运行",先取消,用 FileTool 替代拖放,比两个一起上稳得多。这个顺序颠倒过来的人不少,折腾半天以为是插件坏了。
6. 进阶:把注册流程压成一条可复用的部署脚本
单人机器上手工点几下无所谓,团队里换一台机器就要重来一遍,早晚出事。我的做法是把整条链路固化成两个文件:一个部署脚本,一个校验脚本。部署脚本做四件事——检查系统位数选对regsvr32、把 DLL 复制到统一路径、注册、写注册表兜底。
@echo off setlocal :: 统一安装位置,全团队保持一致,后续脚本不用改参数 set ADDIN_DIR=D:\DevTools\VC6Addins set ADDIN_DLL=%ADDIN_DIR%\FileTool.dll set SRC_DLL=%~dp0FileTool.dll if not exist "%ADDIN_DIR%" mkdir "%ADDIN_DIR%" copy /y "%SRC_DLL%" "%ADDIN_DLL%" >nul || goto :fail :: 64 位系统走 SysWOW64,32 位系统直接用 System32 if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( set REGSVR=C:\Windows\SysWOW64\regsvr32.exe ) else ( set REGSVR=C:\Windows\System32\regsvr32.exe ) "%REGSVR%" /s "%ADDIN_DLL%" if errorlevel 1 echo register returned %errorlevel%, falling back to registry file :: 无论注册结果如何,都补一条 HKCU 记录,保证 Add-In Manager 能看到 reg add "HKCU\Software\Microsoft\DevStudio\6.0\AddIns\FileTool.AddIn" /f ^ /v DisplayName /t REG_SZ /d "FileTool" >nul reg add "HKCU\Software\Microsoft\DevStudio\6.0\AddIns\FileTool.AddIn" /f ^ /v Filename /t REG_SZ /d "%ADDIN_DLL%" >nul echo done. restart VC6 and check Tools > Customize > Add-ins. exit /b 0 :fail echo copy failed, check whether FileTool.dll sits next to this script. exit /b 1参数上只有三个地方需要按环境改:ADDIN_DIR换成你们团队的统一工具目录,SRC_DLL默认取脚本同目录下的 DLL(所以分发时把 bat 和 dll 打包在一起),PROCESSOR_ARCHITECTURE的判断覆盖了少数还在用 32 位系统的老机器。reg add那两行是刻意加的:regsvr32静默模式下返回码含义有限,补写一条HKCU记录成本极低,却能把"注册成功但 IDE 看不到"这类问题直接堵死。
校验脚本更简单,跑一次reg query拿到Filename,再判断文件是否存在,输出一行结论就够:
@echo off setlocal enabledelayedexpansion for /f "tokens=2,*" %%a in ('reg query "HKCU\Software\Microsoft\DevStudio\6.0\AddIns\FileTool.AddIn" /v Filename 2^>nul ^| findstr /i Filename') do set P=%%b if not defined P echo MISSING: no registry entry & exit /b 1 if not exist "!P!" echo BROKEN: registry points to !P! which does not exist & exit /b 1 echo OK: !P!这套东西我一般放在共享盘的一个tools\vc6\目录下,新机器装完 VC6.0 就跑一次,十秒钟搞定,比翻文档靠谱。最后的习惯是从一次事故之后养成的:那次一个老工程的.dsp被批量脚本写坏了,因为脚本把 SOURCE 块追加到了# End Project后面,VC6.0 打开直接报工程无效,而当时工程没进版本库,只能靠同事机器上的一份旧拷贝救回来。从那以后我每次批量改.dsp之前,都强制走一遍"复制.bak带时间戳、改完立刻用 VC6.0 打开验证、再提交"这三步,一步都不跳。希望帮到你。
本文还有配套的精品资源,点击获取