不能。source generator 在编译期仅能访问当前项目 c# 语法树和符号,无法读取类型库(.tlb)、注册表 com 信息,也不能调用 tlbimp.exe 或 comhost.dll,因此不能自动生成传统 interop 程序集。

Source Generator 能不能直接生成 COM 互操作代码?
不能。C# 的 Source Generator 在编译期运行,只能读取当前项目中的 C# 语法树和符号,它**看不到类型库(.tlb)、注册表中的 COM 类信息,也无法调用 tlbimp.exe 或 comhost.dll 的逻辑**。所以你无法用 Source Generator “自动生成”像 Interop.MyLib.dll 那样的传统 COM 互操作程序集。
那怎么让 Source Generator 和 COM 协同工作?
可行路径是:把 COM 类型信息提前转成结构化输入(比如 JSON/YAML 描述接口、CLSID、IID),再让 Source Generator 读取该文件并生成 C# 声明 —— 本质是“手写 IDL 的轻量替代”,不是全自动绑定。
- 先用
oleview.exe或dumpbin /headers提取 COM 接口定义,或导出 .idl 文件 - 用脚本(Python/PowerShell)把
IUnknown继承链、方法签名、[in]/[out]标记转成 JSON,例如:{"interface": "IMyService", "iid": "00000000-0000-0000-0000-000000000000", "methods": [{"name": "DoWork", "params": [{"name": "input", "type": "int"}]}]} - 在 Source Generator 中用
AdditionalFiles读取该 JSON,用SyntaxGenerator拼出[ComImport]、[Guid]、[InterfaceType]等属性的接口声明 - 生成的代码仍需手动调用
Marshal.GetActiveObject或Activator.CreateInstance(传入 CLSID)来获取实例
为什么不用 TlbImp 或 Windows SDK 的默认方式?
因为 tlbimp.exe 生成的互操作程序集依赖运行时注册(regsvr32)、容易版本漂移,且不支持 .NET 6+ 的单文件发布;而 Source Generator 生成的是纯源码,可 git 跟踪、可 diff、可定制 marshaling 行为(比如把 BSTR 自动转 string,跳过某些字段)。
- 典型痛点:COM 接口返回
VARIANT*,默认生成器会映射成object,但你想强制转double?—— 这种逻辑只能靠 Source Generator 在生成时注入判断 - 另一个场景:多个 COM 组件共用同一组回调接口,但
tlbimp会为每个组件生成重复接口 —— Source Generator 可统一提取、去重、加命名空间前缀 - 注意:生成的代码里仍要保留
[UnmanagedFunctionPointer]委托、Marshal.AllocHGlobal手动内存管理等细节,Generator 不会帮你补全运行时逻辑
实际项目中更推荐的组合方案
不要指望 Source Generator 替代 COM 互操作基础设施,而是把它当作“类型声明工厂”:用 Microsoft.Windows.CsWin32 处理 Win32 API,用 COMImport 手写关键接口,再用 Source Generator 填补中间层(比如把配置文件里的 CLSID 列表批量生成 GetComInstance<t>(string clsid)</t> 工厂方法)。
- 必须引用
System.Runtime.InteropServices,且项目 SDK 要设为Microsoft.NET.Sdk(非Microsoft.NET.Sdk.Web等变体,否则Generator可能被跳过) - 在
.csproj中显式启用:<PropertyGroup><EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles><CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath></PropertyGroup>
- 调试 Generator 时,用
dotnet build -v:d > log.txt查看是否加载成功;常见失败原因是AdditionalFiles路径没匹配到,或 JSON 格式有 BOM
真正麻烦的从来不是生成代码,而是 COM 对象生命周期、线程模型(STA/MTA)、错误码转换(HRESULT → 异常)、以及跨 apartment 的接口指针传递 —— 这些 Source Generator 一概不碰,得你自己用 Marshal.ThrowExceptionForHR 和 CoInitializeEx 补齐。










