c# - CoInitializeSecurity 在 Visual Studio 2017 中抛出 RPC_E_TOO_LATE

标签 c# .net visual-studio com visual-studio-2017

我正在尝试运行一个在启动时调用 CoInitializeSecurity 的应用程序。这适用于 Visual Studio 2013,但不适用于 Visual Studio 2017 - 我很好奇这是为什么。

在 Visual Studio 2017 中启动时调用 CoInitializeSecurity 时,我收到一个 COMException,错误代码为 RPC_E_TOO_LATE (0x80010119),这表明已经对 进行了调用CoInitialize,这在 Visual Studio 2013 中不会发生。

我之前在 Visual Studio 2013 中看到过这种行为,当时启用了 Visual Studio 托管进程,或者在调用 CoInitializeSecurity 之前加载了使用 COM 的程序集。

加载的程序集在 Visual Studio 2013 和 2017 之间有所不同(进入 App 构造函数时拍摄的快照),差异突出显示:

2013 年:

'WPFTestVS2017.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\WPFTestVS2017\bin\Debug\WPFTestVS2017.exe'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_64\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35\PresentationCore.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Xaml\v4.0_4.0.0.0__b77a5c561934e089\System.Xaml.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'.

2017 年:

'WPFTestVS2017.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\WPFTestVS2017\bin\Debug\WPFTestVS2017.exe'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_64\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35\PresentationCore.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Xaml\v4.0_4.0.0.0__b77a5c561934e089\System.Xaml.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Remote Debugger\x64\Runtime\Microsoft.VisualStudio.Debugger.Runtime.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'.

'WPFTestVS2017.exe' (CLR v4.0.30319: WPFTestVS2017.exe): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'.

远程调试器让我产生了怀疑,因为它让我想起了 Visual Studio 托管过程。另一行不同的是 System.Core.dll,它没有出现在 VS2013 的加载程序集中。

代码:

App.xaml

<Application x:Class="WPFTestVS2017.App"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            StartupUri="MainWindow.xaml">
</Application>

App.xaml.cs

using System;
using System.Runtime.InteropServices;
using System.Windows;

namespace WPFTestVS2017
{
    internal static class NativeMethods
    {
        private enum RpcAuthnLevel
        {
            Default = 0,
            None = 1,
            Connect = 2,
            Call = 3,
            Pkt = 4,
            PktIntegrity = 5,
            PktPrivacy = 6
        }

        private enum RpcImpLevel
        {
            Default = 0,
            Anonymous = 1,
            Identify = 2,
            Impersonate = 3,
            Delegate = 4
        }

        private enum EoAuthnCap
        {
            None = 0x0000,
            MutualAuth = 0x0001,
            StaticCloaking = 0x0020,
            DynamicCloaking = 0x0040,
            AnyAuthority = 0x0080,
            MakeFullSIC = 0x0100,
            Default = 0x0800,
            SecureRefs = 0x0002,
            AccessControl = 0x0004,
            AppID = 0x0008,
            Dynamic = 0x0010,
            RequireFullSIC = 0x0200,
            AutoImpersonate = 0x0400,
            NoCustomMarshal = 0x2000,
            DisableAAA = 0x1000
        }

        [DllImport("Ole32.dll",
            ExactSpelling = true,
            EntryPoint = "CoInitializeSecurity",
            CallingConvention = CallingConvention.StdCall,
            SetLastError = false,
            PreserveSig = false)]
        private static extern void CoInitializeSecurity(
            IntPtr pVoid,
            int cAuthSvc,
            IntPtr asAuthSvc,
            IntPtr pReserved1,
            uint dwAuthnLevel,
            uint dwImpLevel,
            IntPtr pAuthList,
            uint dwCapabilities,
            IntPtr pReserved3);

        public static void Initialize()
        {
            CoInitializeSecurity(IntPtr.Zero,
                -1,
                IntPtr.Zero,
                IntPtr.Zero,
                (uint)RpcAuthnLevel.PktPrivacy,
                (uint)RpcImpLevel.Impersonate,
                IntPtr.Zero,
                (uint)EoAuthnCap.DynamicCloaking,
                IntPtr.Zero);
        }
    }

    public partial class App : Application
    {
        public App()
        {
            NativeMethods.Initialize();
        }
    }
}

MainWindow.xaml

<Window x:Class="WPFTestVS2017.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>

MainWindow.xaml.cs

using System.Windows;

namespace WPFTestVS2017
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

编辑:

我对 App.xaml.cs 进行了以下修改:

public App()
{
    try
    {
        NativeMethods.Initialize();
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

在 Visual Studio 2017 中调试时会出现消息框,但在 Visual Studio 外部运行相同的可执行文件时不会出现。

最佳答案

您正在应对 VS2017 中托管调试引擎的变化。它与您猜测的内容没有任何关系,我认为删除 Visual Studio Hosting Process 选项很可能是相关的。盲目猜测,这是一个黑匣子,如果没有 Microsoft 调试器团队中某人的帮助,很难渗透。

您有几种可能的解决方法,按实用性排序:

  1. 工具 > 选项 > 调试 > 常规,勾选“使用托管兼容模式”复选框。这将用旧的调试引擎替换新的调试引擎,最后在 VS2010 中使用。您会错过一些最新的调试器功能(新的 PDB 格式、返回值检查、64 位编辑+继续),这些功能应该不会阻止您调试 WPF 应用。

  2. 如果不需要,您可以阻止函数抛出异常。将 [DllImport] 的 PreserveSig 属性更改为 true,将返回类型从 void 更改为 int。它仍然会失败,由负返回值指示,但您可以继续调试其余代码。也许您想使用返回值来设置一个全局变量,您将使用它来绕过棘手的 COM 代码。

  3. 如果不需要,您可以将调试引擎的初始化延迟到 CoInitializeSecurity 调用之后。附加 System.Diagnostics.Debugger.Launch();,用 #if DEBUG 包裹。现在您可以按 Ctrl+F5 开始调试,在出现提示时选择正在运行的 VS 实例作为所需的调试器。使用 Debug > Attach to Process 是一种类似的解决方法。

关于c# - CoInitializeSecurity 在 Visual Studio 2017 中抛出 RPC_E_TOO_LATE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54437684/

相关文章:

.net - 如果您可以使用任何 .NET DAL 技术,您会选择什么?

visual-studio - 如何通过 Visual Studio 2019、2017 和 2015 为 Windows 10 UWP 应用程序创建有效的可信和/或自签名证书

c++ - 如何在 visual studio 中自定义 cpu

c# - UAC 如何知道应用程序需要提升权限?

c# - 从我在 Xamarin.Android 中创建的文件夹中获取文件

.NET 绘制全屏游戏

c# - 配置FluentNHibernate、FluentMappings.AddFromAssembly;意义

asp.net - 将 MVC 5 降级到 mvc 4

c# - INotifyPropertyChanged 导致跨线程错误

c# - 修复 "A method was called at an unexpected time"错误的最佳方法是什么