我正在尝试运行一个在启动时调用 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 调试器团队中某人的帮助,很难渗透。
您有几种可能的解决方法,按实用性排序:
工具 > 选项 > 调试 > 常规,勾选“使用托管兼容模式”复选框。这将用旧的调试引擎替换新的调试引擎,最后在 VS2010 中使用。您会错过一些最新的调试器功能(新的 PDB 格式、返回值检查、64 位编辑+继续),这些功能应该不会阻止您调试 WPF 应用。
如果不需要,您可以阻止函数抛出异常。将 [DllImport] 的 PreserveSig 属性更改为 true,将返回类型从 void 更改为 int。它仍然会失败,由负返回值指示,但您可以继续调试其余代码。也许您想使用返回值来设置一个全局变量,您将使用它来绕过棘手的 COM 代码。
如果不需要,您可以将调试引擎的初始化延迟到 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/