Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 4개 있습니다.)
(시리즈 글이 5개 있습니다.)
.NET Framework: 1066. Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약
; https://www.sysnet.pe.kr/2/0/12665

.NET Framework: 1067. 별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출
; https://www.sysnet.pe.kr/2/0/12666

.NET Framework: 1068. COM+ 서버 응용 프로그램을 이용해 CoInitializeSecurity 제약 해결
; https://www.sysnet.pe.kr/2/0/12667

.NET Framework: 1071. DLL Surrogate를 이용한 Out-of-process COM 개체에서의 CoInitializeSecurity 문제
; https://www.sysnet.pe.kr/2/0/12670

COM 개체 관련: 23. CoInitializeSecurity의 전역 설정을 재정의하는 CoSetProxyBlanket 함수 사용법
; https://www.sysnet.pe.kr/2/0/12679




별도 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




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 2/4/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 91  92  93  94  95  96  97  98  [99]  100  101  102  103  104  105  ...
NoWriterDateCnt.TitleFile(s)
11519정성태5/12/201824503개발 환경 구성: 376. ASP.NET Web Application 프로젝트의 FileSystem 배포(Publish) 시 Before/After Task 설정 방법 [1]
11518정성태5/10/201822445.NET Framework: 747. C# 7.0에서도 부분적으로 가능해진 "타입 추론을 통한 튜플의 변수명 자동 지정"
11517정성태5/10/201820141.NET Framework: 746. Azure runbook 예제 - 6시간 동안 수행 중인 VM을 중지 [1]파일 다운로드1
11516정성태5/9/201821504.NET Framework: 745. Azure runbook을 PowerShell 또는 C# 코드로 실행하는 방법파일 다운로드1
11515정성태5/9/201824115.NET Framework: 744. C# 6 - Expression bodied function [1]
11514정성태5/3/201821809오류 유형: 466. Bitvise - Error in component session/transport/kexHandler [2]
11513정성태5/3/201828853.NET Framework: 743. C# 언어의 공변성과 반공변성 [9]파일 다운로드2
11512정성태5/2/201821228개발 환경 구성: 375. Azure runbook 실행 시 "Errors", "All Logs"에 오류 메시지가 출력되는 경우
11511정성태5/2/201822172개발 환경 구성: 374. Azure - Runbook 기능 소개
11510정성태4/30/201823068.NET Framework: 742. windbg로 확인하는 Finalizer를 가진 객체의 GC 과정파일 다운로드1
11509정성태4/28/201821312.NET Framework: 741. windbg로 확인하는 객체의 GC 여부
11508정성태4/23/201823035개발 환경 구성: 373. MSBuild를 이용해 프로젝트 배포 후 결과물을 zip 파일로 압축하는 방법파일 다운로드1
11507정성태4/20/201824108개발 환경 구성: 372. MSBuild - 빌드 전/후, 배포 전/후 실행하고 싶은 Task 정의
11506정성태4/20/201828503.NET Framework: 740. C#에서 enum을 boxing 없이 int로 변환하기 - 두 번째 이야기 [7]파일 다운로드1
11505정성태4/19/201821447개발 환경 구성: 371. Azure Web App 확장 예제 - Simple WebSite Extension
11504정성태4/19/201823103오류 유형: 465. Azure Web App 확장 - Extplorer File manager 적용 시 오류
11503정성태4/19/201821189오류 유형: 464. PowerShell - Start-Service 명령 오류 (Service 'xxx' cannot be started)
11502정성태4/17/201823889개발 환경 구성: 370. Azure VM/App Services(Web Apps)에 Let's Encrypt 무료 인증서 적용 방법 [3]
11501정성태4/17/201821679개발 환경 구성: 369. New-AzureRmADServicePrincipal로 생성한 계정의 clientSecret, key 값을 구하는 방법파일 다운로드1
11500정성태4/17/201822694개발 환경 구성: 368. PowerShell로 접근하는 Azure의 Access control 보안과 Azure Active Directory의 계정 관리 서비스
11499정성태4/17/201821111개발 환경 구성: 367. Azure - New-AzureRmADServicePrincipal / New-AzureRmRoleAssignment 명령어
11498정성태4/17/201821128개발 환경 구성: 366. Azure Active Directory(Microsoft Enfra ID)의 사용자 유형 구분 - Guest/Member
11497정성태4/17/201818755개발 환경 구성: 365. Azure 리소스의 액세스 제어(Access control) 별로 사용자에게 권한을 할당하는 방법 [2]
11496정성태4/17/201819408개발 환경 구성: 364. Azure Portal에서 구독(Subscriptions) 메뉴가 보이지 않는 경우
11495정성태4/16/201820764개발 환경 구성: 363. Azure의 Access control 보안과 Azure Active Directory의 계정 관리 서비스
11494정성태4/16/201816921개발 환경 구성: 362. Azure Web Apps(App Services)에 사용자 DNS를 지정하는 방법
... 91  92  93  94  95  96  97  98  [99]  100  101  102  103  104  105  ...