【问题标题】:Asynchronous Pluggable Protocols异步可插拔协议
【发布时间】:2011-01-02 01:16:03
【问题描述】:

使用this 作为参考,我正在尝试创建一个异步可插入协议,该协议仅对我的应用程序临时可用(并且未在系统范围内注册)。我正在使用CoInternetGetSession,然后调用RegisterNameSpace 来执行此操作。但是,当我调用 RegisterNameSpace 时,我得到一个 AccessViolation 异常:Attempting to read or write protected memory

知道发生了什么吗?

我的代码如下所示:

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00000001-0000-0000-C000-000000000046")]
[ComVisible(true)]
public interface IClassFactory
{
    void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);
    void LockServer(bool fLock);
}

/* Custom class to act as a class factory that create's an instance of the protocol */
[Guid("0b9c4422-2b6e-4c2d-91b0-9016053ab1b1")]
[ComVisible(true),ClassInterface(ClassInterfaceType.AutoDispatch)]
public class PluggableProtocolFactory : IClassFactory
{
    public Type AppType;
    public PluggableProtocolFactory(Type t)
    {
        this.AppType = t;
    }
    public void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
    {
        riid = ProtocolSupport.GetGuid(this.AppType);
        IInternetProtocol p = Activator.CreateInstance(this.AppType) as IInternetProtocol;
        ppvObject = Marshal.GetComInterfaceForObject(p, typeof(IInternetProtocol));
    }

    public void LockServer(bool fLock)
    {
        var b = fLock;
    }

}

[ComVisible(true)]
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("79eac9e7-baf9-11ce-8c82-00aa004ba90b")]
public interface IInternetSession
{
    void CreateBinding(); // Not Implemented
    void GetCache(); // Not Implemented
    void GetSessionOption(); // Not Implemented
    void RegisterMimeFilter([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
    void RegisterNameSpace([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol,
                           UInt32 cPatterns, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPWStr)] string[] ppwzPatterns, UInt32 dwReserved);
    void SetCache(); // Not Implemented
    void SetSessionOption(); // Not Implemented
    void UnregisterMimeFilter(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
    void UnregisterNameSpace(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol);
}

[ComVisible(false)] public interface IComRegister
{
    void Register(Type t);
    void Unregister(Type t);
}

[ComVisible(false), AttributeUsage(AttributeTargets.Class, AllowMultiple=true) ] 
public class AsyncProtocolAttribute : Attribute, IComRegister
{
    public string Name;
    public string Description;

    [DllImport("urlmon.dll",PreserveSig=false)]
    public static extern int CoInternetGetSession(UInt32 dwSessionMode /* = 0 */, ref IInternetSession ppIInternetSession, UInt32 dwReserved /* = 0 */);

    public void Register(Type t)
    {
        IInternetSession session = null;
        CoInternetGetSession(0, ref session, 0);
        Guid g = new Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B");
        session.RegisterNameSpace(new PluggableProtocolFactory(t), ref g, this.Name, 0, null, 0);

    }

PluggableProtocolFactory 中的CreateInstance 方法永远不会被调用。 (那里的断点永远不会被击中)所以在 RegisterNameSpace 方法中发生了其他事情。

我尝试以管理员和普通用户的身份运行。两种情况都出现同样的错误。

【问题讨论】:

  • 是否可以使用您的AsyncProtocolAttribute 属性粘贴包含您示例的更新?我自己一直在尝试实现相同的“临时协议处理程序”范例,但我看到了你的工作,我对你的属性方法很感兴趣。
  • 我的代码基于此:codeproject.com/kb/aspnet/AspxProtocol.aspx 有一个完整的工作示例。
  • @HS 感谢您的回复,我使用相同的资源为我的大型项目构建了一个示例基础项目。不过我遇到了一个错误,既然你已经开始工作了,我想知道你是否可以对此有所了解:stackoverflow.com/questions/3062642/…

标签: c# com interop


【解决方案1】:

您在 RegisterNameSpace 方法中调用 PluggableProtocolFactory 的构造函数,而不是 CreateInstance 方法。我认为这就是您的问题所在,从来没有创建 IInternetProtocol 的实例来传递给您的方法。

【讨论】:

  • RegisterNameSpace 方法将 IClassFactory 作为其第一个参数。我假设 RegisterNameSpace 方法准备好时会调用 CreateInstance 本身吗?这不就是 ClassFactory 接口的目的吗?
  • 不,它不会自己调用它,你必须在 PluggableProtocolFactory 的构造函数中调用它,或者在你的 Register 方法中调用它。您应该查看接口的用途和作用。
  • 拥有接口的全部意义在于让消费方法能够使用它。如果消费方法不打算使用它,为什么还需要在接口中声明它呢?对不起,这没有任何意义。这是一个思想实验:假设我确实手动调用了 CreateInstance。我会传递什么参数给它?我将如何处理它返回的值? RegisterNameSpace 将如何使用它?如果 RegisterNameSpace 不使用它,那么我是否真的调用它又有什么关系呢?
【解决方案2】:

好的,想通了:IInternetSession接口的声明错误:

这是我从monoblog挑选的一个更好的:

[ComVisible(true), Guid("79eac9e7-baf9-11ce-8c82-00aa004ba90b"),InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetSession
{
    [PreserveSig]
    int RegisterNameSpace(
        [In] IClassFactory classFactory,
        [In] ref Guid rclsid,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol,
        [In]
            int cPatterns,
        [In, MarshalAs(UnmanagedType.LPWStr)]
            string ppwzPatterns,
        [In] int dwReserved);

    [PreserveSig]
    int UnregisterNameSpace(
        [In] IClassFactory classFactory,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pszProtocol);

    int Bogus1();

    int Bogus2();

    int Bogus3();

    int Bogus4();

    int Bogus5();
}

【讨论】:

    猜你喜欢
    • 2010-11-04
    • 2013-05-02
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2010-09-23
    相关资源
    最近更新 更多