2011-02-02 4 views
2

업데이트 :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 
     ); 
} 
+0

아니요, 인터페이스 만 있으면 필요한 작업입니다. –

+0

구현해야하는 인터페이스를 정의하는 com dll (또는 tlb) 용 interop 파일을 만들었습니까? C# 프로젝트에서이 interop을 참조하고 객체를 상속 받았습니까? – Marco

답변

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 터지는 것 같습니다 호출 자체가 여전히 올바르지 않음을 나타냅니다.

그리고 나는 단순히 AdviseSink 방법 선언 [PreserveSig] 추가 할 필요가 모든 좋은 것을 발견 ....

... 또는 무효로 할 수 UINT (HRESULT)을 변경 (더 리턴 코드 없습니다).여기 링크를 참조하십시오 :

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 누군가를 고용하는 데는 단지 약간의 방향이 필요했습니다. 고마워요 !!! 너는 최고야!

관련 문제