更新:
我发现ITfDocumentMgr的IID在注册表中,但ITextStoreACP的IID却没有。当我从我的ITextStoreACP接口定义中删除[Guid(“28888 ....”)]时,Push()方法没有崩溃,我怀疑是因为我的类没有报告它有该接口。然后我把它放回去,使组件,类和接口NOT COM可见。同样,我的AdviseSink方法没有被调用。
对此的任何想法都将不胜感激。
NEAR ORIGINAL POST:
我正在尝试将Text Services Framework集成到我的C#应用程序中,我的C#应用程序作为TSF客户端(而不是TSF服务)。我可以使用TSF COM接口来创建文档管理器。我创建了一个实现ITextStoreACP的文本存储。
[ComVisible(true)]
public class TextStore : ITextStoreACP
{
public uint AdviseSink(
[MarshalAs(UnmanagedType.Struct)] ref IID Iid,
[MarshalAs(UnmanagedType.IUnknown)] Object pUnknown,
uint Mask
)
{
ITextStoreAcpSink Sink = pUnknown as ITextStoreAcpSink;
return 0;
}
....
}
在创建使用我的ITextStoreACP的上下文后,我使用DocumentMgr.Push()来使用引用我的文本存储的上下文。反过来,TSF框架应该使用其接收器调用我的ITextStoreACP.AdviseSink()方法,以便在文本存储内容发生更改时通知框架。
public partial class Form1 : Form
{
static ITextStoreACP pStore = new TextStore();
static Object pIunknown;
static ITfContext Context;
static ITfDocumentMgr DocMgr;
static IThreadMgr ThreadMgr;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
TfClientId Tid = new TfClientId();
TfEditCookie Cookie = new TfEditCookie();
uint hr;
// Get a new thread manager...
ThreadMgr = TsfInterfaces.CreateManager();
// Activate the thread manager and get our cookie back...
hr = ThreadMgr.Activate(out Tid);
// Create a document manager for our use...
hr = ThreadMgr.CreateDocumentMgr(out DocMgr);
// Get the IUnknown interface to pass to CreateContext()...
pIunknown = pStore as Object;
// Create a context to work in, designating our text store for our use...
hr = DocMgr.CreateContext(Tid, 0, pIunknown, out Context, out Cookie);
try
{
// Select our context to work in now. With a text store as part of
// the context, the Text services framework should call into our
// text store object with its sink interface.
//
// But it crashes instead.
//
hr = DocMgr.Push(Context);
}
catch
{
}
}
}
我在这里使用ITfDocumentMgr接口定义:
[Guid("aa80e7f4-2021-11d2-93e0-0060b067b86e")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITfDocumentMgr
{
uint CreateContext(
TfClientId Tid,
uint Flags,
[MarshalAs(UnmanagedType.IUnknown)] Object pUnkUnique,
[MarshalAs(UnmanagedType.Interface)] out ITfContext pContext,
out TfEditCookie pCookie
);
uint Push([MarshalAs(UnmanagedType.Interface)] ITfContext pContext);
uint Pop(uint Flags);
uint GetTop(out ITfContext Context);
uint GetBase(out ITfContext Context);
uint EnumContexts(out IEnumITfContexts EnumContexts);
}
然而,应用程序在调用Push()时崩溃并关闭,而不是接收对我的AdviseSink()方法的调用。如果我没有传递文本存储的接口(这是合法的),而是在调用CreateContext时为null,则Push()返回正常,因为没有要调用的ITextStoreACP.AdviseSink()。
我将项目属性“Make Assembly COM-Visible”设置为true。 我将项目属性“Register for COM interop”设置为true,但我不认为这是必要的。
我需要做些什么才能使我的C#类对象基于外部COM对象可以正确使用的方法访问的ITextStoreACP接口?
接下来显示我的TextStore对象的接口。所有方法都在文本存储中实现,至少具有默认的“Method not implemented”异常,以便我可以运行代码。
[Guid("28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITextStoreACP
{
uint AdviseSink(
[MarshalAs(UnmanagedType.Struct)] ref IID Iid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnknown,
uint Mask
);
uint UnadviseSink([MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
uint RequestLock(uint LockFlags, out uint hrSession);
uint GetStatus([MarshalAs(UnmanagedType.Struct)] out TS_STATUS TSS);
uint QueryInsert(long TestStart, long TestEnd, ulong Count, out long ResultStart, out long ResultEnd);
uint GetSelection(
ulong Index,
ulong Count,
[MarshalAs(UnmanagedType.Struct)] out TS_SELECTION_ACP Selection,
out ulong Fetched
);
uint SetSelection(
ulong Count,
[MarshalAs(UnmanagedType.Struct)] ref TS_SELECTION_ACP Selection
);
uint GetText(
long Start,
long End,
out string Plain,
ulong PlainReq,
out ulong PlainRet,
[MarshalAs(UnmanagedType.Struct)] out TS_RUNINFO RunInfo,
ulong RunInfoReq,
out ulong RunInfoRet,
out long Next
);
uint SetText(
uint Flags,
long Start,
long End,
string Text, // What kind of marshaling should I specify here for "in WCHAR *" types?
ulong Count,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint GetFormattedText(
long Start,
long End,
[MarshalAs(UnmanagedType.Interface)] out IDataObject DataObject
);
uint GetEmbedded(
long Pos,
[MarshalAs(UnmanagedType.Struct)] ref IID GUID_Service,
[MarshalAs(UnmanagedType.Struct)] ref IID IID_Service,
[MarshalAs(UnmanagedType.IUnknown)] out object pUnk
);
uint QueryInsertEmbedded(
[MarshalAs(UnmanagedType.Struct)] ref IID GUID_Service,
[MarshalAs(UnmanagedType.Struct)] ref FORMATETC FormatEtc,
[MarshalAs(UnmanagedType.Bool)] out bool IsInsertable
);
uint InsertEmbedded(
uint Flags,
long Start,
long End,
[MarshalAs(UnmanagedType.Interface)] IDataObject DataObject,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint InsertTextAtSelection(
uint Flags,
string Text,
ulong Count,
out long Start,
out long End,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint InsertEmbeddedAtSelection(
uint Flags,
[MarshalAs(UnmanagedType.Interface)] IDataObject DataObject,
out long Start,
out long End,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint RequestSupportedAttrs(
uint Flags,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId
);
uint RequestAttrsAtPosition(
long Pos,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId,
uint Flags
);
uint RequestAttrsTransitioningAtPosition(
long Pos,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId,
uint Flags
);
uint FindNextAttrTransition(
long Start,
long Halt,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId,
uint Flags,
out long Next,
out bool Found,
out long FoundOffset
);
uint RetrieveRequestedAttrs(
ulong Count,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRVAL Vals,
out ulong Fetched
);
uint GetEndACP(out long Acp);
uint GetActiveView(out TsViewCookie Cookie);
uint GetACPFromPoint(
TsViewCookie Cookie,
[MarshalAs(UnmanagedType.Struct)] ref POINT Point,
uint Flags,
out long Acp
);
uint GetTextExt(
TsViewCookie Cookie,
long Start,
long End,
[MarshalAs(UnmanagedType.Struct)] out RECT Rect,
out bool IsClipped
);
uint GetScreenExt(
TsViewCookie Cookie,
[MarshalAs(UnmanagedType.Struct)] out RECT Rect
);
uint GetWnd(
TsViewCookie Cookie,
[MarshalAs(UnmanagedType.I4)] IntPtr hWnd
);
}
答案 0 :(得分:0)
事实证明我需要以下签名:
[ComVisible(true)]
[Guid("28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITextStoreACP
{
uint AdviseSink(
ref Guid Iid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnknown,
uint Mask
);
.......
}
public class TextStore : ITextStoreACP
{
#region ITextStoreACP Members
public uint AdviseSink(ref Guid Iid, object pUnknown, uint Mask)
{
throw new NotImplementedException();
}
.....
}
但是现在我发现了一个读取访问冲突,看起来堆栈指针在回来的路上弹出0,这似乎表明调用本身仍然不太正确。
然后我发现我只需要将[PreserveSig]添加到AdviseSink方法声明中,一切都很好....
...或将uint(HRESULT)更改为void(无返回码)。请参阅此处的链接:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.preservesigattribute%28v=VS.90%29.aspx http://social.msdn.microsoft.com/Forums/en-US/clr/thread/a8c2d872-a42e-441a-907b-62d4a05f75ea
不需要雇佣任何人,只需要一点方向。谢谢大家!你太棒了!