별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출
재미있는 현상이군요. ^^; 지난 글의 마지막에,
Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약
; https://www.sysnet.pe.kr/2/0/12665
다음의 코드를 .NET Framework 환경에서 수행하면 결괏값이 RPC_E_TOO_LATE가 나온다고 했는데요,
using System;
using WslSdk.Interop;
class Program
{
[STAThread]
static void Main(string[] args)
{
var result = NativeMethods.CoInitializeSecurity(
IntPtr.Zero,
(-1),
IntPtr.Zero,
IntPtr.Zero,
NativeMethods.RpcAuthnLevel.None,
NativeMethods.RpcImpLevel.Impersonate,
IntPtr.Zero,
NativeMethods.EoAuthnCap.StaticCloaking,
IntPtr.Zero);
Console.WriteLine(result); // 출력 결과: 0
}
}
그런데, 실제로 저렇게 테스트해 보면 0이 나옵니다. 단지 영향이 없을 것 같은 코드를 저기에 싣지 않았던 것뿐인데요, 원래는 아래와 같았습니다.
using System;
using WslSdk.Interop;
// Install-Package Wslhub.Sdk
class Program
{
[STAThread]
static void Main(string[] args)
{
var result = NativeMethods.CoInitializeSecurity(
IntPtr.Zero,
(-1),
IntPtr.Zero,
IntPtr.Zero,
NativeMethods.RpcAuthnLevel.None,
NativeMethods.RpcImpLevel.Impersonate,
IntPtr.Zero,
NativeMethods.EoAuthnCap.StaticCloaking,
IntPtr.Zero);
Console.WriteLine(result); // 출력 결과: -2147417831
Wsl.GetDistroListFromRegistry();
}
}
그러니까, 저렇게 WslSdk의 메서드 호출만 추가한 것으로 CoInitializeSecurity가 실패하는 것입니다. 오~~~ 신기하지 않나요? ^^
위의 현상을 간단하게 재현하는 것이 가능합니다. 우선, .NET Framework 콘솔 프로젝트를 생성하고 NativeMethods.CoInitializeSecurity를 호출하는 상태로 만들어 둡니다. 그다음 아래의 소스 코드만 가진 .NET Framework 라이브러리를,
public class Class1
{
public static void Test() { }
}
콘솔 프로젝트에서 참조 추가해 Test 메서드를 호출하는 코드를 넣어 주면 상황을 재현할 수 있습니다.
using System;
class Program
{
[STAThread]
static void Main(string[] args)
{
var result = NativeMethods.CoInitializeSecurity(
IntPtr.Zero, (-1), IntPtr.Zero, IntPtr.Zero, NativeMethods.RpcAuthnLevel.None,
NativeMethods.RpcImpLevel.Impersonate, IntPtr.Zero, NativeMethods.EoAuthnCap.StaticCloaking, IntPtr.Zero);
Console.WriteLine(result); // 출력 결과: -2147417831
Class1.Test();
}
}
만약 저 코드를 JIT 컴파일러가 알지 못하도록 분리시켜 놓으면,
using System;
class Program
{
[STAThread]
static void Main(string[] args)
{
var result = NativeMethods.CoInitializeSecurity(
IntPtr.Zero, (-1), IntPtr.Zero, IntPtr.Zero, NativeMethods.RpcAuthnLevel.None,
NativeMethods.RpcImpLevel.Impersonate, IntPtr.Zero, NativeMethods.EoAuthnCap.StaticCloaking, IntPtr.Zero);
Console.WriteLine(result); // 출력 결과: 0
CallMethod();
}
static void CallMethod()
{
Class1.Test();
}
}
이번에는 다시 0이 반환됩니다. 도대체 ^^; 무슨 일이 있는 걸까요?
어쨌든 현상만을 정리해 보면, ^^ JIT 컴파일러는 외부 DLL이 사용되었다는 것만으로 STAThread Main 시작 전에 CoInitializeSecurity를 호출하고 있는 것입니다. 참고로, 해당 현상은 .NET Core 프로젝트에서는 발생하지 않습니다.
(
첨부 파일은 이 글의 예제 코드를 포함합니다.)
C# - CoCreateInstance 관련 Inteop 오류 정리
; https://www.sysnet.pe.kr/2/0/12678
Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약
; https://www.sysnet.pe.kr/2/0/12665
별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출
; https://www.sysnet.pe.kr/2/0/12666
COM+ 서버 응용 프로그램을 이용해 CoInitializeSecurity 제약 해결
; https://www.sysnet.pe.kr/2/0/12667
ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법
; https://www.sysnet.pe.kr/2/0/12676
역공학을 통한 lxssmanager.dll의 ILxssSession 사용법 분석
; https://www.sysnet.pe.kr/2/0/12677
C# - DLL Surrogate를 이용한 Out-of-process COM 개체 제작
; https://www.sysnet.pe.kr/2/0/12668
DLL Surrogate를 이용한 Out-of-process COM 개체에서의 CoInitializeSecurity 문제
; https://www.sysnet.pe.kr/2/0/12670
CoInitializeSecurity의 전역 설정을 재정의하는 CoSetProxyBlanket 함수 사용법
; https://www.sysnet.pe.kr/2/0/12679
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]