업데이트 :C# 인터페이스를 사용하기 위해 외부 COM 개체에 전달하는 방법은 무엇입니까?
ITfDocumentMgr의 IID가 레지스트리에 있지만 ITextStoreACP의 IID가 아닌 것으로 나타났습니다. 내 ITextStoreACP 인터페이스 정의에서 [Guid ("28888 ....")]을 제거했을 때 Push() 메소드가 충돌하지 않았지만 클래스가 인터페이스를보고하지 않았기 때문에 의심 스럽습니다. 그런 다음 다시 배치하고 어셈블리, 클래스 및 인터페이스를 COM으로 표시하지 않았습니다. 다시 말하지만, 내 AdviseSink 메서드는 호출되지 않습니다.
이 문제에 대한 의견을 보내 주시면 감사하겠습니다.
NEAR ORIGINAL POST : 나는 (A TSF 서비스와 반대) TSF 클라이언트로 내 C# 응용 프로그램과 함께, 내 C# 응용 프로그램에 텍스트 서비스 프레임 워크를 통합하기 위해 노력하고
. 필자는 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() 메서드를 호출하여 텍스트 저장소 내용이 변경 될 때 프레임 워크에 알릴 수 있습니다.) (단
[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);
}
을 대신 내 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 인터페이스 정의를 사용하고 있습니다 . 텍스트 저장소 (합법적) 인터페이스를 전달하지 않고 CreateContext를 호출 할 때 null을 반환하면 호출 할 ITextStoreACP.AdviseSink()가 없으므로 Push()가 반환됩니다.
프로젝트 속성을 "Make COM-Visible"으로 설정했습니다. 필자는 이것이 필요 없다고 생각하지만 "COM interop에 등록"프로젝트 속성을 true로 설정했습니다.
올바르게 사용할 수있는 외부 COM 개체의 메서드에 액세스 할 수있는 ITextStoreACP 인터페이스를 기반으로 C# 클래스 개체를 만들기 위해 필요한 다른 작업이 있습니까?
내 TextStore 객체 기반 인터페이스가 다음에 표시됩니다. 모든 메소드는 최소한 "메소드 구현되지 않음"예외로 텍스트 저장소에 구현되므로 코드를 실행할 수 있습니다.
[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
);
}
아니요, 인터페이스 만 있으면 필요한 작업입니다. –
구현해야하는 인터페이스를 정의하는 com dll (또는 tlb) 용 interop 파일을 만들었습니까? C# 프로젝트에서이 interop을 참조하고 객체를 상속 받았습니까? – Marco