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);

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

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




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 2/15/2024]

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

비밀번호

댓글 작성자
 




... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
11915정성태5/24/201914741Linux: 11. 리눅스의 환경 변수 관련 함수 정리 - putenv, setenv, unsetenv
11914정성태5/24/201914454Linux: 10. 윈도우의 GetTickCount와 리눅스의 clock_gettime파일 다운로드1
11913정성태5/23/201912082.NET Framework: 838. C# - 숫자형 타입의 bit(2진) 문자열, 16진수 문자열 구하는 방법파일 다운로드1
11912정성태5/23/201911751VS.NET IDE: 137. Visual Studio 2019 버전 16.1부터 리눅스 C/C++ 프로젝트에 추가된 WSL 지원
11911정성태5/23/201910827VS.NET IDE: 136. Visual Studio 2019 - 리눅스 C/C++ 프로젝트에 인텔리센스가 동작하지 않는 경우
11910정성태5/23/201919461Math: 50. C# - MathNet.Numerics의 Matrix(행렬) 연산 [1]파일 다운로드1
11909정성태5/22/201913894.NET Framework: 837. C# - PLplot 사용 예제 [1]파일 다운로드1
11908정성태5/22/201912286.NET Framework: 836. C# - Python range 함수 구현파일 다운로드1
11907정성태5/22/201910086오류 유형: 541. msbuild - MSB4024 The imported project file "...targets" could not be loaded
11906정성태5/21/201910024.NET Framework: 835. .NET Core/C# - 리눅스 syslog에 로그 남기는 방법
11905정성태5/21/201910677.NET Framework: 834. C# - 폴더 경로 문자열에서 "..", "." 표기를 고려한 최종 문자열을 얻는 방법 - 두 번째 이야기
11904정성태5/21/201916907.NET Framework: 833. C# - Open Hardware Monitor를 이용한 CPU 온도 정보 [1]파일 다운로드1
11903정성태5/21/201911893오류 유형: 540. .NET Core - System.PlatformNotSupportedException: The named version of this synchronization primitive is not supported on this platform.
11902정성태5/21/201911066오류 유형: 539. mstest 실행 시 "The directory name is invalid." 오류 발생
11901정성태5/21/201912186오류 유형: 538. msbuild 오류 - Could not find a part of the path '%LOCALAPPDATA%\Temp\2\.NETFramework,Version=v4.0.AssemblyAttributes.cs'
11900정성태5/18/201911475오류 유형: 537. "sfc /scannow" 실행 중 시스템이 부팅되는 현상
11899정성태5/17/201912496Linux: 9. Linux에서 윈도우의 OutputDebugString 대신 사용할 수 있는 syslog [1]
11898정성태5/16/201913875VC++: 130. C++ string의 c_str과 data 함수의 차이점 [3]
11897정성태5/16/201920527오류 유형: 536. Visual Studio - "Developer Pack"을 설치했는데도 "대상 프레임워크" 목록에 나오지 않는 경우 [2]
11896정성태5/15/201915254개발 환경 구성: 440. C#, C++ - double의 Infinity, NaN 표현 방식파일 다운로드1
11895정성태5/12/201913634.NET Framework: 832. ML.NET Model Builder - 회귀(Regression), 다중 분류(Multi-class classification) 예제파일 다운로드1
11894정성태5/10/201914775VS.NET IDE: 135. Visual Studio - ML.NET Model Builder 소개 [5]
11893정성태5/10/201912422오류 유형: 535. C# 6.0 이상의 문법을 컴파일 시 오류가 발생한다면?
11892정성태5/10/201912460웹: 38. HTTP Cookie의 expires 시간 형식(RFC7231)
11891정성태5/9/201914963.NET Framework: 831. (번역글) .NET Internals Cookbook Part 12 - Memory structure, attributes, handles
11890정성태5/8/201910714개발 환경 구성: 439. "Visual Studio Enterprise is required to execute the test." 메시지와 관련된 코드 기록
... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...