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

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

在启用Visual Studio托管进程或在调用CoInitializeSecurity之前加载使用COM的程序集的情况下,我在Visual Studio 2013中已经看到了此行为。

加载的程序集在Visual Studio 2013和2017之间有所不同(输入App构造函数时将捕获快照),突出显示了不同之处:

2013年:


  'WPFTestVS2017.exe'(CLR v4.0.30319:DefaultDomain):已加载'C:\ windows \ Microsoft.Net \ assembly \ GAC_64 \ mscorlib \ v4.0_4.0.0.0__b77a5c561934e089 \ mscorlib.dll'。
  
  'WPFTestVS2017.exe'(CLR v4.0.30319:DefaultDomain):已加载'C:\ WPFTestVS2017 \ bin \ Debug \ WPFTestVS2017.exe'。
  
  'WPFTestVS2017.exe'(CLR v4.0.30319:WPFTestVS2017.exe):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'C:\ windows \ Microsoft.Net \ assembly \ GAC_64 \ mscorlib \ v4.0_4.0.0.0__b77a5c561934e089 \ mscorlib.dll'。
  
  'WPFTestVS2017.exe'(CLR v4.0.30319:DefaultDomain):已加载'C:\ WPFTestVS2017 \ bin \ Debug \ WPFTestVS2017.exe'。
  
  'WPFTestVS2017.exe'(CLR v4.0.30319:WPFTestVS2017.exe):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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):已加载'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的已加载程序集中。

码:

应用程式

<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调试器团队中的任何人的帮助,很难穿透。

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


在工具>选项>调试>常规中,选中“使用托管的兼容模式”复选框。这将新的调试引擎替换为上一次在VS2010中使用的旧调试引擎。您会错过一些最新的调试器功能(新的PDB格式,返回值检查,64位Edit + Continue),这些几乎不会阻止您调试WPF应用程序。
如果不需要,可以阻止该函数引发异常。将[DllImport]的PreserveSig属性更改为true,将返回类型从void更改为int。它仍然会失败,由负的返回值指示,但是您可以继续调试其余代码。也许您想使用返回值来设置一个全局变量,以用于绕过棘手的COM代码。
如果不需要,可以将初始化调试引擎的时间推迟到CoInitializeSecurity调用之后。附加System.Diagnostics.Debugger.Launch();,并用#if DEBUG包裹。现在,您可以按Ctrl + F5开始调试,在出现提示时,将VS的运行实例选择为所需的调试器。使用调试>附加到进程是一个类似的解决方法。

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

10-10 17:56