코드가 공유 DLL 또는 exe에서 실행되고 있는지 프로그래밍 방식으로 감지하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1633490

문제

A에는 전역 단축키 처리를 단순화하는 C# 클래스가 있습니다.이 클래스는 Win32-API 함수를 사용합니다. RegisterHotKey() 단축키를 등록하려면

MSDN에 따르면이 기능은 응용 프로그램에서 호출 할 때 0x0000에서 0xBFFF 범위의 ID 값이 필요하며 공유 DLL에서 호출 할 때 0xc000에서 0xffff 범위의 ID 값이 필요합니다. GlobalAddAtom() DLL에서 실행되는 경우 ID를 얻는 데 사용할 수 있습니다.

클래스 사용자 와이 차이를 숨기려면 클래스 자체가 핫 키를 등록 할 때 어떤 ID 범위를 사용할 것인지 결정해야합니다.글쎄,이를 위해 클래스는 코드가 응용 프로그램 내에서 또는 공유 DLL 내에서 실행 중인지 여부를 감지 할 수 있어야합니다.

하지만 어떻게 해야 할까요?이를 수행하는 가장 좋은 C#/.NET 방법은 무엇입니까?

도움이 되었습니까?

해결책

이 시도:

bool isDll = this.GetType().Assembly.EntryPoint == null;

MSDN :

어셈블리. 엔트리 포인트 속성

"속성 값이 어셈블리의 진입 점을 나타내는 MethodInfo 객체입니다. 진입 점이 발견되지 않으면 (예 : 어셈블리는 DLL), 널 참조 (비주얼 기본의 아무것도 없음)가 반환됩니다."

다른 팁

그것은 당신의 수업 - 알잖아 당신이 그것을 어디에 두고 있는지.

공유하지 않는 경우 0xBFFF 아래의 ID를 선택하고 완료하세요.

클래스가 여러 애플리케이션에서 공유할 수 있는 DLL에 속하는 경우...또는 제어할 수 없어 ID를 정렬할 수 없는 코드로 간단히 공유할 수도 있습니다.그런 다음 사용 GlobalAddAtom() 신분증을 받으려면 (그리고 전화하는 것을 잊지 마세요) GlobalDeleteAtom() 당신 후 단축키 등록 취소).


설명

두 개의 서로 다른 ID 범위가 있는 이유와 API 문서에서 사용을 권장하는 이유에 대해 잠시 시간을 내어 생각해 볼 가치가 있을 것입니다. GlobalAddAtom() 공유 DLL에 대해 후자 범위의 ID를 얻으려면매개변수에 대한 문서부터 시작하겠습니다. RegisterHotKey():

ID
【인】 단축키의 식별자를 지정합니다.hWnd 매개변수가 NULL이면 단축키는 특정 창보다는 현재 스레드와 연관됩니다.동일한 hWnd 및 id 매개변수를 가진 단축키가 이미 존재하는 경우 취한 조치에 대한 설명을 참조하세요.

이를 통해 우리는 핫키가 두 가지 잠재적인 정보 쌍 중 하나에 의해 고유하게 식별된다는 것을 추측할 수 있습니다.스레드 또는 창 핸들 및 임의의 16비트 숫자.창 핸들(HWND), 그 다음에 메시지 해당 창으로 전송됩니다.그렇지 않으면 스레드로 전송됩니다.

그래서...등록만 하면 하나 특정 창에 대한 단축키, ID는 실제로 중요하지 않습니다.1;다른 누구도 해당 창에 대한 단축키를 등록할 수 없으며, 다른 창에 대한 단축키 이벤트가 해당 창에 게시됩니다.마찬가지로, 특정 스레드에 대해 창 없는 단축키를 하나만 등록하면 해당 단축키에 대한 메시지만 받게 됩니다. 애플리케이션의 모든 코드를 제어하는 ​​경우 단축키에 원하는 ID를 선택할 수 있습니다., 할당하려는 기술을 사용합니다.아무도 그들을 밟지 않을 것이다. 왜냐하면 당신은 모든 코드를 소유하고 있습니다 그럴 것이다 할 수 있는 그들을 밟아라!

하지만 다른 코드에서 호출할 수 있는 범용 루틴을 작성하는 경우에는 어떻게 될까요?그러면 호출자가 잠재적으로 해당 ID를 이미 사용하고 있을 수 있고 동일한 창이나 스레드도 사용하고 있다면 결국 핫키를 다시 정의하게 되므로 상수 ID를 안정적으로 선택할 수 없습니다.아니면 (귀하의 경우처럼) 런타임까지 얼마나 많은 단축키가 등록될지 모른다면 어떻게 될까요?

런타임에 선택한 ID가 다른 사람이 사용하지 않는 ID인지 확인하는 방법이 필요합니다. 이곳은 GlobalAddAtom() 시작됩니다 :문자열을 전달하면 해당 문자열에만 해당하고 다른 문자열에는 해당하지 않는다는 보장이 있는 ID가 제공됩니다.이는 다른 사람이 동일한 문자열을 전달하지 않는 한 시스템에 대해 사실상 고유하며, 아마도 고유한 문자열을 생각해 낼 수 있습니다.회사 이름이나 주민등록번호, 그리고 필요한 새로운 원자마다 증가하는 접두사를 사용하세요.또는 편집증이 심한 경우 GUID를 사용하십시오.

진실 뒤에 숨겨진 진실

그 방법을 사용하여 약간의 혼란을 해결해 보겠습니다.Windows는 호출하는 코드가 실제로 실행되는지 여부를 신경 쓰지 않습니다. RegisterHotKey() DLL에 있습니다.그것 캔트.다음 루틴을 고려해보세요.

void RegisterSuperHappyFunHotKey(HWND hWnd, int id, 
                                 unsigned int fsModifiers, unsigned int vk)
{
   RegisterHotKey(hWnd, id, fsModifiers, vk);
}

이 루틴은 아무것도 아님 하지만 해당 매개변수를 WinAPI 함수로 전달합니다. 그 중 어느 것도 호출 모듈을 식별하지 않습니다.DLL에 있는 경우 애플리케이션 자체에 컴파일된 것처럼 동작합니다.Windows에서는 호출이 어디서 발생했는지 알 수 있는 신뢰할 수 있는 방법이 없으며 단축키 자체는 DLL 내부 또는 외부의 코드로 제어할 수 있는 창과 스레드(또는 스레드만)에 연결되어 있습니다.물론 이제 앱 또는 라이브러리별 요구 사항이 있을 수 있습니다.DLL이 창을 생성하고 이에 대한 단축키를 설정하는 경우 창을 삭제할 때 해당 단축키 등록을 취소해야 합니다.하지만 당신이 적절하다고 생각하는 대로 처리하는 것은 당신 자신의 관심사입니다.

MSDN은 한 가지 이유 때문에 두 가지 ID 범위를 지정합니다.DLL 작성자가 애플리케이션 작성자가 사용하는 ID를 밟지 않도록 권장합니다.당신이 애플리케이션 작성자라면, 세상은 당신의 굴이다 - 애플리케이션 프로세스에서 어떤 코드가 로드되고 실행되는지 (대부분) 제어하므로 어떤 ID를 사용할지 결정할 수 있습니다. 그러나 당신이 적합하다고 생각하는:0부터 시작하여 새로운 단축키마다 증가하는 것은 완벽하게 허용됩니다.하지만 일단 ID의 상위 범위에 들어가면 다음을 사용해야 합니다. GlobalAddAtom() 마치 DLL인 것처럼 - 또는 DLL에서 로드된 제3자 코드에 의해 이런 방식으로 생성된 ID와 충돌할 위험이 있습니다.그것은 ... 사회 계약 일종의.

요약:

여기서 "공유 DLL" 비트는 매우 위험합니다.애플리케이션에 등록된 모든 단축키의 ID를 알 수 있다면 0xBFFF 아래의 숫자를 선택하여 사용하세요.그렇게 할 수 없다면 귀하의 코드는 여러 발신자가 사용하게 되므로(귀하의 코드는...) 다음을 사용하여 ID를 얻으십시오. GlobalAddAtom() 그리고 그것을 사용하십시오.

추천

이러한 이유로 나는 당신에게 다음을 권합니다. 하다 사용 GlobalAddAtom() 당신이 디자인하고 있는 클래스에 대해, 당신이 자신의 디자인 응용 프로그램(사용되는 ID를 제어하는 ​​곳)이나 DLL로 빌드할지 여부를 현재로서는 알 수 없는 것처럼 들리기 때문입니다. 다른 앱에서 로드하려면(여기서 하지 마라).걱정하지 마세요. 계약을 위반하는 것은 아닙니다. 가장하고있는 DLL 호출자에 대해 설정된 규칙을 따르는 한 DLL이 됩니다.


1네, 주의해야 할 몇 가지 시스템 정의 단축키 ID가 있습니다...

Philip 답변 완료 :

기능을 호출하는 어셈블리에 대한 참조를 가져와야하므로 코드는 다음과 같아야합니다.

Assembly assembly = Assembly.GetCallingAssembly();
Boolean isDll = assembly.EntryPoint == null;

도움이 되었기를 바랍니다.

Ricardo Lacerda Castelo Branco

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top