我需要让一段 C# 代码通过 COM 与各种实现进行交互。
为了使该集成的用户更容易,我在 IDL 中包含了交互接口(作为相关现有 DLL 的一部分,但没有 coclass 或实现),然后通过运行 Tlbimp 将其放入我的 C# 代码中以创建类型定义。
我实现了我的 C#,基于 Windows 注册表信息创建 COM 对象并将对象转换为我需要的接口。
然后我在一个单独的项目中创建了接口的 C# 实现并注册了它。主程序正确创建了测试 COM 对象,但未能将其转换为接口(使用 C#'as' 时获取空对象,获取显式转换的 InvalidCastException)。
有人可以建议为什么接口没有被测试对象识别为实现吗?
这是 IDL 中的接口定义(在 VS 2005 中用 C++ 编译):
[
object,
uuid(B60C546F-EE91-48a2-A352-CFC36E613CB7),
dual,
nonextensible,
helpstring("IScriptGenerator Interface"),
pointer_default(unique)
]
interface IScriptGenerator : IDispatch{
[helpstring("Init the Script generator")]
HRESULT Init();
[helpstring("General purpose error reporting")]
HRESULT GetLastError([out] BSTR *Error);
};
这是 Tlbimp 为 C# 创建的存根:
[TypeLibType(4288)]
[Guid("B60C546F-EE91-48A2-A352-CFC36E613CB7")]
public interface IScriptGenerator
{
[DispId(1610743813)]
void GetLastError(out string Error);
[DispId(1610743808)]
void Init();
}
这是主要 C# 代码的一部分,通过其 ProgID 创建一个 COM 对象并将其转换为 IScriptGenerator 接口:
public ScriptGenerator(string GUID)
{
Type comType = Type.GetTypeFromProgID(GUID);
object comObj = null;
if (comType != null)
{
try
{
comObj = Activator.CreateInstance(comType);
}
catch (Exception ex)
{
Debug.Fail("Cannot create the script generator COM object due to the following exception: " + ex, ex.Message + "\n" + ex.StackTrace);
throw ex;
}
}
else
throw new ArgumentException("The GUID does not match a registetred COM object", "GUID");
m_internalGenerator = comObj as IScriptGenerator;
if (m_internalGenerator == null)
{
Debug.Fail("The script generator doesn't support the required interface - IScriptGenerator");
throw new InvalidCastException("The script generator with the GUID " + GUID + " doesn't support the required interface - IScriptGenerator");
}
}
这是实现 C# 代码,以测试它是否正常工作(但它不是):
[Guid("EB46E31F-0961-4179-8A56-3895DDF2884E"),
ProgId("ScriptGeneratorExample.ScriptGenerator"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(SOAAPIOLELib.IScriptGeneratorCallback))]
public class ScriptGenerator : IScriptGenerator
{
public void GetLastError(out string Error)
{
throw new NotImplementedException();
}
public void Init()
{
// nothing to do
}
}