我使用Microsoft的
CSExeCOMServer作为设置进程外COM服务器的基础,但它无法正常工作.服务器是64位,客户端是32位.
这是示例界面
[Guid(XXCryptService.InterfaceId), ComVisible(true)/*, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)*/]
public interface IXXCryptService
{
[DispId(1)] string Encrypt(string password, string key);
[DispId(2)] string Decrypt(string password, string key);
}
和班级
[ClassInterface(ClassInterfaceType.None)]
[Guid(XXCryptService.ClassId), ComVisible(true)]
public class XXCryptService : ReferenceCountedObject, IXXCryptService
{
internal const string ClassId =
"C5F6938B-5593-4872-B8C7-B47EE33EABCD";
internal const string InterfaceId =
"6990FF5F-22E2-4032-8B98-36115DBCEFFF";
[EditorBrowsable(EditorBrowsableState.Never)]
[ComRegisterFunction()]
public static void Register(Type t)
{
try
{
COMHelper.RegasmRegisterLocalServer(t);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw ex;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
[ComUnregisterFunction()]
public static void Unregister(Type t)
{
try
{
COMHelper.RegasmUnregisterLocalServer(t);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw ex;
}
}
public string Encrypt(string password, string key)
{
return "Encrypted";
}
public string Decrypt(string password, string key)
{
return "Decrypted";
}
}
该程序运行,但是当客户端连接它时,在服务器触发ObjectClassFactory上的CreateInstance后,它在客户端崩溃,并使用Marshal.GetComInterfaceForObject(new XXCryptService(),typeof(IXXCryptService))返回ppvObject上的对象并返回0.
在.NET上运行客户端会触发“无法将类型为’COMTest.XXCryptService’的COM对象’转换为接口类型’COMTest.IXXCryptService’.此操作失败,因为QueryInterface调用COM组件上的IID为{6990FF5F-的接口22E2-4032-8B98-36115DBCEFFF}由于以下错误而失败:找不到元素.(HRESULT异常:0x8002802B(TYPE_E_ELEMENTNOTFOUND)).“.
[Guid("6990FF5F-22E2-4032-8B98-36115DBCEFFF")]
//[InterfaceType(ComInterfaceType.InterfaceIsDual)]
interface IXXCryptService
{
[DispId(1)] string Encrypt(string password, string key);
[DispId(2)] string Decrypt(string password, string key);
}
[ComImport, Guid("C5F6938B-5593-4872-B8C7-B47EE33EABCD")]
class XXCryptService
{
}
class Program
{
static void Main(string[] args)
{
XXCryptService cs = new XXCryptService();
IXXCryptService ics = (IXXCryptService) cs;
Console.WriteLine(ics.Encrypt("Test","Test"));
Console.ReadKey();
}
}
在Delphi上运行客户端会在EIntfCastError中触发异常,并显示消息“Interface not supported”.使用“导入类型库”导入COM并像这样使用.
procedure TForm1.FormCreate(Sender: TObject);
begin
FCrypter := CoXXCryptService.Create;
end;
TLB界面看起来像这样
IXXCryptService = interface(IDispatch)
['{6990FF5F-22E2-4032-8B98-36115DBCEFFF}']
function Encrypt(const password: WideString; const key: WideString): WideString; safecall;
function Decrypt(const password: WideString; const key: WideString): WideString; safecall;
end;
// *********************************************************************//
// DispIntf: IXXCryptServiceDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {6990FF5F-22E2-4032-8B98-36115DBCEFFF}
// *********************************************************************//
IXXCryptServiceDisp = dispinterface
['{6990FF5F-22E2-4032-8B98-36115DBCEFFF}']
function Encrypt(const password: WideString; const key: WideString): WideString; dispid 1;
function Decrypt(const password: WideString; const key: WideString): WideString; dispid 2;
end;
我已通过注册表检查,一切似乎都已正确注册,所以我不明白为什么我应该得到这个问题.
这里有人对可能出现的问题有任何疑问吗?
编辑:在64位编译客户端,这是正常的.此外,它引用了错误的路径,在我调整它后,我在.NET x86客户端上遇到了不同的错误
此操作失败,因为由于以下错误,对IID为“{6990FF5F-22E2-4032-8B98-36115DBCEFFF}”的接口的COM组件的QueryInterface调用失败:加载类型库/ DLL时出错. (来自HRESULT的异常:0x80029C4A(TYPE_E_CANTLOADLIBRARY))
最佳答案 这是注册的问题,而且只有当程序集与regasm具有相同的目标时,才会执行regasm. regasm应该有一个“/ com_oop或something”参数,使其注册LocalServer32而不是InprocServer32,并在64位系统上为32位和64位注册.
为了解决这个问题,我不得不暂时将可执行文件(使用相同的路径)编译为32位,运行32位regasm(使用/ tlb:..),然后编译回64位,运行64位regasm(使用/ tlb:..再次),现在它适用于32位和64位对64位可执行文件.
CSExeComServer有一个注册和取消注册方法,它手动删除InprocServer32密钥并添加LocalServer32.为了确保这个工作正常,我将改变这个,检测它是否在64位系统上注册,然后让它在那里正确注册.当我完成后,我会将我做的更改发布到注册方法中.