免注册 COM 互操作:在终结器中停用激活上下文会引发 SEHException

2023-12-03

我目前正在开发混合托管/本机工作链,需要为免注册 COM 支持创建激活上下文(请参阅将免注册 COM 清单嵌入到具有本机/托管环境的 C# dll 中)。以下代码片段是 C# DLL 内一个较大类的一部分,该类保存对 COM 包装器的引用并建立所需的激活上下文:

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace FirstClient
{
    public class FirstClientDLL : IDisposable
    {
        ~FirstClientDLL()
        {
            Dispose(false);
        }

        void IDisposable.Dispose()
        {
            Dispose(true);
        }

        private void Dispose(bool disposing)
        {
            DestroyActivationContext();
        }

        private bool DestroyActivationContext()
        {
            if (m_cookie != IntPtr.Zero)
            {
                try
                {
                    //When being invoked from the destructor or the dispose method, the following line always fails...
                    if (!DeactivateActCtx(0, m_cookie))
                        return false;

                    m_cookie = IntPtr.Zero;
                }

                catch (SEHException ex)
                {
                    // Always gets hit. Why??

                    Debug.Print(ex.Message + " " + "0x" + ex.ErrorCode.ToString("X"));

                    return false;
                }

                if (!ReleaseActCtx(m_hActCtx))
                    return false;

                m_hActCtx = IntPtr.Zero;
            }

            return true;
        }

        public bool EstablishActivationContext()
        {
            ACTCTX info = new ACTCTX();

            info.cbSize = Marshal.SizeOf(typeof(ACTCTX));
            info.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
            info.lpSource = System.Reflection.Assembly.GetExecutingAssembly().Location;
            info.lpResourceName = ISOLATIONAWARE_MANIFEST_RESOURCE_ID;

            m_hActCtx = CreateActCtx(ref info);

            if (m_hActCtx == new IntPtr(-1))
                return false;

            m_cookie = IntPtr.Zero;

            if (!ActivateActCtx(m_hActCtx, out m_cookie))
                return false;

            m_iCOMInstance = new atlw.TestClass();

            // --> If I destroy the activation context here, no exception is thrown. Obviously, the COM wrapper will get invalidated and can no longer accept any calls.

            //DestroyActivationContext();

            return true;
        }

        public string CallCOMMethod()
        {
            return m_iCOMInstance.SayHello();
        }


        private const uint ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x008;

        private const UInt16 ISOLATIONAWARE_MANIFEST_RESOURCE_ID = 2;

        private const UInt16 DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION = 1;

        [DllImport("Kernel32.dll")]
        private extern static IntPtr CreateActCtx(ref ACTCTX actctx);
        [DllImport("Kernel32.dll")]
        private extern static bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie);
        [DllImport("Kernel32.dll")]
        private extern static bool DeactivateActCtx(uint dwFlags, IntPtr lpCookie);
        [DllImport("Kernel32.dll")]
        private extern static bool ReleaseActCtx(IntPtr hActCtx);

        private struct ACTCTX
        {
            public int cbSize;
            public uint dwFlags;
            public string lpSource;
            public ushort wProcessorArchitecture;
            public ushort wLangId;
            public string lpAssemblyDirectory;
            public UInt16 lpResourceName;
            public string lpApplicationName;
            public IntPtr hModule;
        }

        private atlw.ITestClass m_iCOMInstance;

        private IntPtr m_cookie;

        private IntPtr m_hActCtx;
    }
}

问题出在pinvoked上DeactivateActCtx()里面的函数DestroyActivationContext()方法。一旦被调用,就会出现一个SEHExceptionis throws:外部组件抛出异常。 0x80004005。

没有可用的错误代码Marshal.GetLastWin32Error()函数,这将为我提供一些合理的信息。

到目前为止我尝试过的事情:

  • 移动DestroyActivationContext()从析构函数到函数Dispose方法,反之亦然。
  • 删除IDisposable界面一并。
  • 将底层 COM 对象的线程模型从 Apartment 更改为 Free。
  • 提供DeactivateActCtx()功能与DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION作为输入参数。
  • 改变类型IntPtr实例到UIntPtr.

不幸的是,这些选择都没有帮助。是否有任何可能的方法可以在不遇到上述情况的情况下解除激活上下文SEHException?

UPDATE

看来垃圾收集器的线程是问题的原因。 GC 始终在其自己的独特线程中运行,显然不可能另行指定。当尝试停用激活上下文时,似乎在幕后发生了某种访问冲突(DeactivateActCtx)来自这个特定的线程。所以我想除了在每个包装调用中激活和停用激活上下文之外,没有直接的方法来处理这种麻烦。任何可以证明并非如此的建议仍然受到欢迎。


为了使其工作,每个包装的调用都需要包含一个激活和随后的停用请求。谢谢大卫赫夫南,谁提供了处理这个问题的合理方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

免注册 COM 互操作:在终结器中停用激活上下文会引发 SEHException 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐

  • 文件上传控制和 GWT 外观

    我正在编写我的第一个 GWT 项目 我有一个带有标签 文件上传控件和上传按钮的表单 但它们在各种网络浏览器中看起来很糟糕并且差异很大 另外 文件上传控件中的按钮与 GWT 按钮控件的样式不同 另一个问题是 在 Chrome 中 文件选择按钮
  • Android Widget 在更新期间显示奇怪的图像

    我这里有一个奇怪的 我有一台配备 Nextel 的 Motorola i1 运行 Android 1 5 我有一个安卓小部件 当我开始运行更新此小部件的服务时 我看到来自另一个小部件的图像 启动 DC Contact 它在我的小部件的位置显
  • 使用 Newton-Raphson 方法在 C 中求平方根

    在下面的代码中 我想将终止条件替换为 如果猜测平方与x的比率接近1 则while循环应该终止 我尝试了各种表达式 但没有一个能够正确运行代码 有什么建议吗 include
  • R:带有 geom_map 的 ggplot2 返回“x 和单位必须具有长度 > 0”错误,尽管值已转换为因子

    我正在开发一个原始的闪亮应用程序 它将映射来自苏格兰开放数据项目 我制定了 SPARQL 查询 用于生成类似于下面提供的摘录的数据框 dz label overall quantiles S010001 8 S010002 9 我有强化的形
  • 从 XCode 调用本地 HTML 文件时出现问题

    这是我的 WebView 代码 webView loadRequest NSURLRequest requestWithURL NSURL fileURLWithPath NSBundle mainBundle pathForResourc
  • Android SpeechRecognizer 只能在应用程序的主线程中使用

    我正在尝试将一些 Android 语音 API 集成到我的基于 AndEngine 的游戏中 我将代码放在 BaseGame 活动中 但是在运行时出现此错误 05 06 23 51 28 955 错误 AndroidRuntime 553
  • 4D 到 3D 透视投影

    我正在尝试计算 3D 世界中 4D 点的位置 我从 2D 开始 尝试将其扩展到 3D 然后再扩展到 4D 首先 我发现计算直线上二维点的投影位置很容易 Whoops there should be in the first equation
  • 如何在 Dart 中替换 unicode 转义字符

    我需要清理具有转义字符的字符串 但无法这样做 这是我的测试代码 test Replace unicode escape character String originalText Jeremiah 52 1 u201334 String r
  • 为初学者保护 PHP 表单?资源?

    我成功构建了第一个 html PHP 表单 该表单使用 POST 全局变量在多个页面之间传递变量 然后使用 mail 函数将结果通过电子邮件发送给我 我确信这种形式非常不安全 因为它现在很容易受到各种攻击 我想知道如何修补这些漏洞 但我几乎
  • Java错误路径中没有lwjgl64?

    我正在尝试制作一个游戏 它在 eclipse 中运行良好 但是当我将其导出并作为 jar 文件运行时 出现此错误 Exception in thread main java lang UnsatisfiedLinkError no lwjg
  • 这里建议API返回PARSING_ERROR

    从昨天开始 我们用于获取地点建议的 Here API 系统地返回 PARSING ERROR 状态页面在这里https status here com status说一切都很好 那可能是什么问题呢 我们的代码几周以来一直在运行 if fro
  • 无法使用字符串在 PowerShell 中设置别名

    我尝试通过运行在 PowerShell 中设置别名Set Alias Name artisan Value php aritsan 虽然命令运行成功 但是当我调用别名时 出现以下错误 artisan The term php aritsan
  • 使用 iPhone 和 iPad 的 Safari 中的传单地图问题

    我在 iPhone 和 iPad 中使用 Safari 浏览传单地图时遇到一些奇怪的问题 我正在使用 AJAX GET 请求来获取地图上的标记并在获取时绑定弹出内容 在弹出窗口中 我有一个按钮 当用户单击它以查看详细信息时 该按钮会打开引导
  • 如何使用 VoiceOver 逐段阅读 UITextView?

    我正在为盲人编写一个应用程序 并想在其主页上放置一些说明 该指令是多段静态文本 我把它放在 UITextView 中 我希望盲人用户能够使用 VoiceOver 逐段阅读说明 但是 当用户将 VoiceOver 焦点移到 UITextVie
  • 运行梁管道时,“PBegin”对象没有属性“windowing”

    我在运行数据流作业时发现 PBegin 对象没有属性 windowing 我在 pardo 函数中调用 connectclass 类 我正在尝试从 Beam python SDK 连接 NOSQL 数据库并运行 sql 从表中提取数据 然后
  • 帮助!如何在月份更改后在 UI 日期选择器中启用日期?

    在我的情况下 我得到了想要从 ajax 调用启用的日子 当我更改月份时 我读取了 ajax 调用的 xml 文件并获取了该月的天数 如何计算出来 非常感谢 保存日期的数组变量 var daysWithRecords new Array 加载
  • 在 OS X 10.11 上构建 GCC

    在 OS X 10 11 1 上使用命令行构建 GCC 最新版本 gccx configure with gmp opt local with mpfr opt local with mpc opt local with libiconv
  • 以编程方式将数据网格列置于视图中(水平滚动)

    我想以编程方式显示一个专栏 我有很多列 当它们不在屏幕上时 我想选择一个单元格并将该单元格带入视图中 我可以选择一个在屏幕外的单元格 当我水平滚动以使单元格可见时 该单元格被选中 我知道你可以用行来做到这一点 即 ScrollIntoVie
  • 使用 DirectLine 和网络聊天 (Node.js) 在 bot-framework v4 中发送打字指示符

    Microsoft bot framework 的官方文档SDK v4不演示如何发送打字指示符 而v3 有这些说明 我正在使用 DirectLine 和 botframework webchat 我该怎么做呢 谢谢 您可以通过发送带有以下内
  • 免注册 COM 互操作:在终结器中停用激活上下文会引发 SEHException

    我目前正在开发混合托管 本机工作链 需要为免注册 COM 支持创建激活上下文 请参阅将免注册 COM 清单嵌入到具有本机 托管环境的 C dll 中 以下代码片段是 C DLL 内一个较大类的一部分 该类保存对 COM 包装器的引用并建立所