Introduction

이번시간에는 "찌니남편"님께서 방명록을 통해 질문해주신 내용대로, 네트워크 상의 컴퓨터 목록을 가져오는 방법에 대해 소개합니다. 윈도우를 제어하는 작업이다보니 이를 구현하는 방법은 다양하지만 이번시간에는 간단히 .Net Framework상에서 제공하는 기능들을 이용해 네트워크 상에 존재하는 컴퓨터이름, 아이피주소, 연결상태등을 확인하는 방법에 대해 설명드리겠습니다. 아래는 이번시간에 구현할 내용의 결과물 이미지 입니다.

Using Active Directory Services Interfaces

Active Directory Service Interfaces(ADSI)는 여러 네트워크 공급업체들이 제공하는 다양한 디렉터리 서비스의 기능을 이용해 네트워크 자원을 관리하는 디렉터리 서비스 인터페이스 집합으로, 간단하게 네트워크 디렉토리에 접근하고 제어 할 수 있도록 돕습니다. .Net Framework에서도 System.DirectoryServices 네임스페이스를 통해 ADSI를 사용할 수 있기 때문에, 이번시간에는 이를 통해 구현해보도록 하겠습니다.

※ System.DirectoryServices 네임스페이스는 System.DirectoryServices어셈블리를 참조 추가 한 뒤 사용할 수 있습니다.

사용법은 매우 간단합니다. WinNT를 이용해 네트워크영역을 DirectoryEntry를 생성하고 Workgroup을 탐색해가며 네트워크 상에 연결된 컴퓨터의 목록을 가져올 수 있습니다. 아래는 소스코드입니다.


위 코드를 간단히 설명하면, DirecotryEntry를 이용해 네트워크상의 컴퓨터 이름을 가져온뒤 DNS를 이용해 해당 컴퓨터의 IP주소 목록을 가져옵니다. 그리고 Ping을 통해 대상 컴퓨터의 상태와 응답속도를 확인합니다. 소스가 크게 복잡하지 않기 때문에 코드에 대한 설명은 여기까지로 하며, 혹시 더 궁금하신 부분이나 문의 사항은 이메일이나 댓글로 남겨주시면 답변드리도록 하겠습니다.

신고

Introduction

.Net Framework를 이용해 COM객체를 사용하다보면, Object 형식으로 객체가 리턴되는 경우가 있는데 이 객체를 활용하기 위해서는 적절한 Type으로 캐스팅이 필요한 상황이 됩니다. 다행히 Object객체가 어떤 Type의 객체인지 알고 있는 상황이라면 간단하게 캐스팅문법을 이용해 캐스팅 해서 사용할 수 있지만, Type을 모르고 있다면 문제가 발생합니다.

일반적인 .Net Framework환경에서 였다면 간단히 GetType메서드를 통해 해당 객체의 Type을 확인 할 수 있지만, COM 객체의 경우 GetType메서드를 호출하게 되면 System.__ComObject 를 리턴하기 때문에 확인 할 수가 없습니다.

Microsoft KB문서(http://support.microsoft.com/kb/320523)에 보면 as 연산자를 이용해 하나씩 캐스팅을 할수 있다고 하지만, 이렇게 할경우 Type이 많아질 수록 더 많은 체크 루틴을 작성해야 하기 때문에 적합한 방법은 아닌것 같습니다.

이번시간에 소개할 내용은 이러한 상황에서 COM객체의 Type을 확인 할 수 있는 방법에대해 소개합니다.

GetTypeFromComObject Method

COM 객체의 Type을 가져오기 위해서 몇 가지 COM객체의 특성을 이용합니다. 첫째로 COM객체는 GetType메서드를 호출하면 System.__ComObject타입을 리턴한다는 점과, 둘째로 COM Interop Type은 Interface이고, 고유의 GUID를 갖는다는 점을 이용합니다. 소스코드에 대한 설명은 주석으로 대체합니다.



위 코드에서는 Type을 확인 하기 위한 객체와, 해당 COM객체의 Interop Assembly를 입력해 Assembly에 정의된 Type들 중 QueryInterface가 가능한 객체를 검색하는 과정을 수행합니다.
 
 

신고

Introduction

이번 시간에는 전역 후킹(Global Hooking)에 대해서 알아보도록 하겠습니다.

C/C++ 에서는 Win32 API를 이용하여 손쉽게 전역 후킹을 할 수 있습니다. 물론 .NET 에서도 Win32 API의 DLL 파일을 Import 하여 후킹이 가능합니다. 하지만 약간의 문제가 있습니다. 지역 후킹이 아닌 전역 후킹에서는 CallBack Procedure 를 DLL 파일로 만들어야 한다는 것이지요. 이런 이유로 .NET 에서는 전역 후킹이 안된다는 이야기가 많이 있습니다. 저 역시 초기에 이런 문제에 부딪혔습니다.


Microsoft 에서 전역 후킹에 대해서 찾아보니 심지어 이런 내용이 있었습니다.

물론 이 이야기가 맞습니다. .NET 에서 전역 후킹(Global Hooking)을 하려면, 이 DLL 을 C/C++ 과 같이 네이트브 코드로 만들고, 이것을 호출하는 방법 밖엔 없습니다.

하지만, 마우스와 키보드에 대한 전역 후킹은 .NET 에서 가능합니다. 다시 말하자면, 마우스와 키보드 이외에는 전역후킹이 불가능 하다는 이야기가 되겠습니다 :) 이 방식은 WH_MOUSE_LL, WH_KEYBOARD_LL 만 지원한다는 이야기입니다.

즉, WH_MOUSE 나 WH_KEYBOARD 는 지원하지 않습니다. 저 역시 예전엔 이 idHook 을 사용하고 왜 안될까 고민했던 것 같습니다.
코드는 다음과 같이 매우 간단합니다. 가독성을 위해서 partial 로 나누어 놓았습니다. 오해 없으시기 바랍니다.


Example


[Win32 API Wrapper]


[구조체 / idHook]


[Start Hook]



 



 

신고

Introduction

이번시간에는 .Net Framework에서 제공하는 GZipStream을 이용해 간단하게 데이터를 압축하고 압축을 푸는 동작에 대해 소개합니다. GZipStream은 파일을 손실 없이 압축하거나 압축을 풀기 위해 사용되는 gzip 데이터 형식을 사용합니다. gzip 형식에 대한 자세한 내용은 RFC 1952, "GZIP file format specification 4.3"에서 확인 하실 수 있습니다. 참고로 GZip에서는 4GB이상의 파일 압축을 지원하지 않습니다.

Compress/Decompress Extension Method

아래 코드는 BaseStream에 저장된 내용을 압축하거나, 압축을 푼뒤 결과를 OutputStream에 저장하는 Extension Method입니다.

그리고 아래 코드는 압축 / 압축해제 결과를 MemoryStream 로 출력하거나, File로 출력하기 위한 코드입니다.


신고

Introduction

Application을 개발할때 여러 프로젝트에서 동일한 기능을 공유하거나, 관리상의 목적으로 하여금 DLL 형태로 분리해 개발을 하는 경우가 있습니다. .Net으로 개발된 Application은 참조된 DLL(Assembly)을 로드할때 기본적으로 System32나, Application Root, GAC에 등록되어 있는 DLL을 검색하는데,  검색에 실패할경우 "FileNotFoundException"을 발생시킵니다.
만약, Application에서 참조하는 DLL(Assembly)의 경로가 위에서 언급한 위치와 다른 위치에 설치하고자 한다면 AppDomain을 이용해 런타임에 직접 Assembly를 Load하는 방식으로 해결 할 수 있습니다.

What is AppDomain?

AppDomain이란 .Net 환경에서 Application이 실행되는 환경을 의미하며, .Net 플랫폼에서는 AppDomain단위로 여러 프로세스들을 구분하고 격리함으로서 각 프로세스간의 안정성을 확보 할 수 있도록 도와줍니다. 서로다른 프로세스를 격리시킨다는 점에서 Win32와 유사하다고 할 수 있지만, AppDomain에는 보안, 버전, 어셈블리 관리등을 위한 기능을 제공합니다.

Load Assembly in Runtime using AppDomain

AppDomain에 접근하기 위해 System.AppDomain 클래스를 이용할 수 있습니다. AppDomain클래스의 Static멤버인 CurrentDomain 속성을 이용하면 현재 프로세스가 실행중인 AppDomain에 접근 할 수 있습니다. AppDomain에는 Assembly와 관련하여 AssemblyLoad이벤트와 AssemblyResolve이벤트를 제공하는데, AssemblyLoad이벤트는 AppDomain내에서 Assembly가 Load되었을때 발생하며, AssemblyResolve는 AppDomain내에서 Load하고자 하는 Aseembly를 발견하지 못했을 경우 발생합니다.
Application에서 참조하는 DLL(Assembly)을 발견하지 못했을 경우에도 AssemblyResolve이벤트가 발생을 하는데요, AssemblyResolve 이벤트에서 참조하는 Assembly를 직접 생성해 줌으로서 기본위치에 등록되어 있지 않은 Assembly를 사용할 수 있습니다. 아래는 AppDomain의 AssemblyResolve이벤트를 통해 동적으로 Assembly를 Load하는 내용의 코드입니다.


위 코드에서는 Assembly 클래스의 LoadFile 메서드를 이용해 파일로부터 Assembly를 생성했지만, AssemblyResolve 이벤트 부분을 아래와 같이 구현하여 현재 Assembly내에 포함된 Resource에서  Assembly를 Load 할 수도 있습니다.

Development Tip

이번 강좌에서는 AppDomain을 이용해 Runtime에 Assembly를 Load하는 하는 방법에 대해 소개했지만, 단순히 DLL(Assembly)를 특정 폴더에 위치시키고 관리하고자 하는 경우에는 App.Config 에 아래와 같이 probing path를 명시하는 방법으로도 해결 할 수 있습니다.



 

신고