Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)

AllowPartiallyTrustedCallers 특성이 적용된 GAC 어셈블리에서 DynamicMethod의 calli 명령어 사용

calli 명령어 사용법에 대해 지난 글에서 대략 설명드렸는데요.

calli IL 호출이 DllImport 호출보다 빠를까요?
; https://www.sysnet.pe.kr/2/0/10808

OpenCover 코드 커버리지 도구의 동작방식을 통해 살펴보는 Calli IL 코드 사용법
; https://www.sysnet.pe.kr/2/0/2882

calli IL 코드를 사용하는 메서드를 만들기 위해 직접 DynamicMethod를 사용했습니다.

// x86 기준 calli IL 코드를 사용하는 동적 메서드 생성

long result = 0;

if (IntPtr.Size == 4)
{
    result = GetThisThreadId32();
}

var type = typeof(Class1);
DynamicMethod dynamicMethod = new DynamicMethod("", typeof(int), Type.EmptyTypes, type, true);

var iLGenerator = dynamicMethod.GetILGenerator();

if (IntPtr.Size == 4)
{
    iLGenerator.Emit(OpCodes.Ldc_I4, (int)result);
}

iLGenerator.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, typeof(int), Type.EmptyTypes);
iLGenerator.Emit(OpCodes.Ret);

GetThisThreadIdDelegate tempDelegate = dynamicMethod.CreateDelegate(typeof(GetThisThreadIdDelegate)) as GetThisThreadIdDelegate;
_GetThisThreadIdMethod = tempDelegate;

재미있는 것은 이 코드를 .NET 4.0 보안의 APTCA가 적용된 어셈블리 내에 두면,

.NET CLR4 보안 모델 - 3. CLR4 보안 모델에서의 APTCA 역할
; https://www.sysnet.pe.kr/2/0/1682

dynamicMethod.CreateDelegate 단계까지 정상적으로 실행은 되지만 그렇게 해서 생성한 _GetThisThreadIdMethod 메서드를 호출하면 다음과 같은 예외가 발생합니다.

System.Security.VerificationException was caught
  _HResult=-2146233075
  _message=Operation could destabilize the runtime.
  HResult=-2146233075
  IsTransient=false
  Message=Operation could destabilize the runtime.
  Source=ClassLibrary1
  StackTrace:
       at ()
       at ClassLibrary1.Class1.GetThisThreadId()
  InnerException: 

원인은 DynamicMethod 메서드의 추가를 APTCA가 적용된 어셈블리 내에 있는 타입을 기준으로 했기 때문입니다.

var type = typeof(Class1);
DynamicMethod dynamicMethod = new DynamicMethod("", typeof(int), Type.EmptyTypes, type, true);

따라서, 해당 타입 대신 APTCA가 적용되지 않은 어셈블리에 정의된 타입을 대신 넣어주면 됩니다. 가령, 이런 식이겠지요.

// GAC 어셈블리의 GetThisThreadId를 호출할 때 별도의 타입을 지정

class Program
{
    static void Main(string[] args)
    {
        ClassLibrary1.Class1.GetThisThreadId(typeof(Program));
    }
}

// ClassLibrary1.Class1.GetThisThreadId에서는 외부의 타입을 기반으로 동적 메서드 추가

using System;
using System.Reflection.Emit;
using System.Runtime.InteropServices;

namespace ClassLibrary1
{
    [System.Security.SecuritySafeCritical]
    public class Class1
    {
        // ...[생략]...

        public static int GetThisThreadId(Type type)
        {
            long result = 0;

            // ...[생략]...

            DynamicMethod dynamicMethod = new DynamicMethod("", typeof(int), Type.EmptyTypes, type, true);

            // ...[생략]...

            GetThisThreadIdDelegate tempDelegate = dynamicMethod.CreateDelegate(typeof(GetThisThreadIdDelegate)) as GetThisThreadIdDelegate;
            _GetThisThreadIdMethod = tempDelegate;

            return _GetThisThreadIdMethod();
        }
    }
}

근데... 이런 식은 좀 번거로우니 의존성을 제거하기 위해 아예 어셈블리 및 타입도 동적으로 생성해 주는 방법이 있습니다.

AssemblyName myAssemblyName = new AssemblyName();
myAssemblyName.Name = "EmittedAssembly_" + Guid.NewGuid().ToString();
AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(myAssemblyName,
    AssemblyBuilderAccess.Run);

ModuleBuilder myModule = myAssembly.DefineDynamicModule("EmittedModule");
TypeBuilder helperClass = myModule.DefineType("Helper", TypeAttributes.Public);
Type type = helperClass.CreateType();

DynamicMethod dynamicMethod = new DynamicMethod("", typeof(int), Type.EmptyTypes, type, true);

어떤 것을 사용하든... 취향에 맞게! ^^

(첨부한 파일은 위의 예제 코드를 포함합니다.)




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 5/27/2024]

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

비밀번호

댓글 작성자
 




... 46  47  48  49  50  51  52  53  [54]  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12585정성태4/5/202116893개발 환경 구성: 563. 기본 생성된 kubeconfig 파일의 내용을 새롭게 생성한 인증서로 구성하는 방법
12584정성태4/1/202118070개발 환경 구성: 562. kubeconfig 파일 없이 kubectl 옵션만으로 실행하는 방법
12583정성태3/29/202118999개발 환경 구성: 561. kubectl 수행 시 다른 k8s 클러스터로 접속하는 방법
12582정성태3/29/202118368오류 유형: 709. Visual C++ - 컴파일 에러 error C2059: syntax error: '__stdcall'
12581정성태3/28/202118356.NET Framework: 1031. WinForm/WPF에서 Console 창을 띄워 출력하는 방법 (2) - Output 디버깅 출력을 AllocConsole로 우회 [2]
12580정성태3/28/202116206오류 유형: 708. SQL Server Management Studio - Execution Timeout Expired.
12579정성태3/28/202116785오류 유형: 707. 중첩 가상화(Nested Virtualization) - The virtual machine could not be started because this platform does not support nested virtualization.
12578정성태3/27/202117227개발 환경 구성: 560. Docker Desktop for Windows 기반의 Kubernetes 구성 (2) - WSL 2 인스턴스에 kind가 구성한 k8s 서비스 위치
12577정성태3/26/202118892개발 환경 구성: 559. Docker Desktop for Windows 기반의 Kubernetes 구성 - WSL 2 인스턴스에 kind 도구로 k8s 클러스터 구성
12576정성태3/25/202116918개발 환경 구성: 558. Docker Desktop for Windows에서 DockerDesktopVM 기반의 Kubernetes 구성 (2) - k8s 서비스 위치
12575정성태3/24/202115489개발 환경 구성: 557. Docker Desktop for Windows에서 DockerDesktopVM 기반의 Kubernetes 구성 [1]
12574정성태3/23/202120999.NET Framework: 1030. C# Socket의 Close/Shutdown 동작 (동기 모드)
12573정성태3/22/202118389개발 환경 구성: 556. WSL 인스턴스 초기 설정 명령어 [1]
12572정성태3/22/202117736.NET Framework: 1029. C# - GC 호출로 인한 메모리 압축(Compaction)을 확인하는 방법파일 다운로드1
12571정성태3/21/202115767오류 유형: 706. WSL 2 기반으로 "Enable Kubernetes" 활성화 시 초기화 실패 [1]
12570정성태3/19/202121084개발 환경 구성: 555. openssl - CA로부터 인증받은 새로운 인증서를 생성하는 방법
12569정성태3/18/202121441개발 환경 구성: 554. WSL 인스턴스 export/import 방법 및 단축 아이콘 설정 방법
12568정성태3/18/202114793오류 유형: 705. C# 빌드 - Couldn't process file ... due to its being in the Internet or Restricted zone or having the mark of the web on the file.
12567정성태3/17/202116856개발 환경 구성: 553. Docker Desktop for Windows를 위한 k8s 대시보드 활성화 [1]
12566정성태3/17/202116658개발 환경 구성: 552. Kubernetes - kube-apiserver와 REST API 통신하는 방법 (Docker Desktop for Windows 환경)
12565정성태3/17/202113421오류 유형: 704. curl.exe 실행 시 dll not found 오류
12564정성태3/16/202114277VS.NET IDE: 160. 새 프로젝트 창에 C++/CLI 프로젝트 템플릿이 없는 경우
12563정성태3/16/202117144개발 환경 구성: 551. C# - JIRA REST API 사용 정리 (3) jira-oauth-cli 도구를 이용한 키 관리
12562정성태3/15/202117930개발 환경 구성: 550. C# - JIRA REST API 사용 정리 (2) JIRA OAuth 토큰으로 API 사용하는 방법파일 다운로드1
12561정성태3/12/202116668VS.NET IDE: 159. Visual Studio에서 개행(\n, \r) 등의 제어 문자를 치환하는 방법 - 정규 표현식 사용
12560정성태3/11/202117732개발 환경 구성: 549. ssh-keygen으로 생성한 PKCS#1 개인키/공개키 파일을 각각 PKCS8/PEM 형식으로 변환하는 방법
... 46  47  48  49  50  51  52  53  [54]  55  56  57  58  59  60  ...