.NET 4.x迁移至.NET 7后RTD公式无法正常工作
.NET 7 RTD Server 在Excel中显示N/A问题排查
我有一个在.NET Framework 4.x中运行正常的RTD Server实现,升级到.NET 7后出现问题。已用regsvr32.exe成功注册comhost.dll,但Excel中所有包含RTD公式的单元格均显示“N/A”,而COM客户端应用可正常运行。
代码文件
Server.cs
using System; using System.Runtime.InteropServices; using com.lightstreamer.client; using Microsoft.Office.Interop.Excel; namespace Examples.RtdDemo { [ComVisible(true)] [Guid("DB1797F5-7198-4411-8563-D05F4E904956")] [ProgId("lightstreamer.rtdnew12")] public class LsRtdServer : IServer { private int pi = 0; int IRtdServer.ServerStart(IRTDUpdateEvent CallbackObject) { return (int)pi; } object IRtdServer.ConnectData(int TopicID, ref Array Strings, ref bool GetNewValues) { pi += TopicID; return ""+pi; } Array IRtdServer.RefreshData(ref int TopicCount) { object[,] data = new object[1, 1]; data[0,0] = ""+pi; return data; } void IRtdServer.DisconnectData(int TopicID) { // . } int IRtdServer.Heartbeat() { return 0; } void IRtdServer.ServerTerminate() { // .. } } }
IServer.cs
using System; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; [ComVisible(true)] [Guid("BA9AC84B-C7FC-41CF-8B2F-1764EB773D4B")] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface IServer : IRtdServer { }
项目文件(.csproj)
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net7.0</TargetFramework> <TargetFramework Condition="'$(DefaultALC)' == 'True'">net8.0</TargetFramework> <!-- Indicate the assembly is providing a COM server --> <EnableComHosting>True</EnableComHosting> <!-- Generate a RegFree COM manifest --> <EnableRegFreeCom Condition="'$(RegFree)' == 'True'">True</EnableRegFreeCom> </PropertyGroup> <ItemGroup> <!-- Used in lieu of a Primary Interop Assembly (PIA) --> <Compile Include="../COMContract/*.cs" /> </ItemGroup> <ItemGroup> <PackageReference Include="Lightstreamer.DotNetStandard.Client" Version="6.0.0-beta.2" /> <PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1001" /> </ItemGroup> <ItemGroup> <RuntimeHostConfigurationOption Condition="'$(DefaultALC)' == 'True'" Include="System.Runtime.InteropServices.COM.LoadComponentInDefaultContext" Value="true" /> </ItemGroup> <Target Name="ServerUsage" Condition="'$(RegFree)' != 'True'" AfterTargets="Build"> <Message Importance="High" Text="%0a************************************%0a*** $(MSBuildProjectName) usage instructions ***%0a************************************" /> <Message Importance="High" Text="The server must be COM registered in order to activate.%0aThe following commands must be executed from an elevated command prompt." /> <Message Importance="High" Text="Register:%0a regsvr32.exe "$(ProjectDir)$(OutputPath)$(ComHostFileName)"" /> <Message Importance="High" Text="Unregister:%0a regsvr32.exe /u "$(ProjectDir)$(OutputPath)$(ComHostFileName)"" /> </Target> <Target Name="ServerUsage_RegFree" Condition="'$(RegFree)' == 'True'" AfterTargets="Build"> <Message Importance="High" Text="%0a************************************%0a*** $(MSBuildProjectName) usage instructions ***%0a************************************" /> <Message Importance="High" Text="A RegFree COM manifest has been created for the server.%0aThe manifest '@(RegFreeComManifest->%(Filename)%(Extension)')' must be included during server deployment.%0aThe COMServer project will copy all required outputs to the COMClient output directory." /> <ItemGroup> <ServerOutput Include="$(OutputPath)*.dll" /> <ServerOutput Include="$(OutputPath)*.runtimeconfig.json" /> <ServerOutput Include="$(OutputPath)*.deps.json" /> <ServerOutput Include="$(OutputPath)*.manifest" /> </ItemGroup> <!-- Deploy all required server outputs --> <Copy SourceFiles="@(ServerOutput)" DestinationFolder="../COMClient/$(OutputPath)" /> </Target> <Target Name="Clean_RegFree" AfterTargets="Clean"> <ItemGroup> <ServerOutputToDelete Include="../COMClient/$(OutputPath)COMServer.*" /> </ItemGroup> <!-- Cleanup deployed server outputs --> <Delete Files="@(ServerOutputToDelete)" /> </Target> </Project>
问题排查与修复建议
从实现和配置来看,以下几点是核心问题:
1. IRTDServer接口实现不符合Excel规范
- ServerStart返回值错误:Excel要求该方法返回
1表示初始化成功,返回0会被判定为启动失败,直接导致RTD连接中断。同时必须保存IRTDUpdateEvent回调对象,后续更新需要用它触发Excel刷新:private IRTDUpdateEvent _callback; int IRtdServer.ServerStart(IRTDUpdateEvent CallbackObject) { _callback = CallbackObject; return 1; // 返回1表示初始化成功 } - Heartbeat返回值错误:返回
0会让Excel认为服务器已停止,需返回1维持连接:int IRtdServer.Heartbeat() { return 1; } - RefreshData格式错误:Excel期望返回的是2维数组,第一维代表属性(主题ID、值),第二维代表主题数量。你的实现维度错误,且未正确设置
TopicCount:Array IRtdServer.RefreshData(ref int TopicCount) { TopicCount = 1; // 实际主题数量 object[,] data = new object[2, TopicCount]; data[0, 0] = 1; // 对应TopicID data[1, 0] = pi.ToString(); // 对应主题值 return data; }
2. 接口继承导致的COM类型歧义
自定义IServer接口继承IRTDServer可能导致COM类型库生成异常,建议直接让LsRtdServer实现IRTDServer,去掉中间接口:
[ComVisible(true)] [Guid("DB1797F5-7198-4411-8563-D05F4E904956")] [ProgId("lightstreamer.rtdnew12")] public class LsRtdServer : IRTDServer { // 直接实现IRTDServer所有方法 }
3. 位数不匹配
Excel分32位和64位版本,必须确保你的RTD Server编译位数与Excel一致:
- 在项目属性中明确设置目标平台为
x86或x64,而非AnyCPU - 注册对应位数的
comhost.dll
4. COM加载上下文配置
.NET 7默认会在独立的程序集加载上下文(ALC)中加载COM组件,可能导致与Excel交互异常。移除项目文件中的条件编译,强制启用默认上下文加载:
<ItemGroup> <RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.COM.LoadComponentInDefaultContext" Value="true" /> </ItemGroup>
验证步骤
- 修改代码后重新编译,确保目标平台与Excel位数一致
- 管理员命令行重新注册:
regsvr32.exe "你的输出路径\comhost.dll" - 打开Excel测试公式:
=RTD("lightstreamer.rtdnew12",, "测试参数") - 启用Excel RTD日志排查细节:Excel选项 -> 高级 -> 常规 -> 勾选“启用RTD服务器日志”
内容的提问来源于stack exchange,提问作者Giuseppe Corti
相关产品推荐
相关产品推荐

