반응형
처음에 셸 위의 사용자의 활동 이력을 로그에 남기고 싶다고 생각한 적은 없을까요.예를 들어, 애플리케이션의 편의를 위해, 크래시나 블로킹 오류를 리버스 엔지니어링하기 위해, 사용자 활동을 감시하기 위해 등 로그를 기록하는 이유는 여러 가지가 있을 수 있습니다.이러한 로그 기능을 구현하는데 있어서 열쇠가 되는 것은 매우 단순하고, 종종 과소평가되고 있는 IShell Execute Hook이라고 하는 COM 인터페이스입니다.이 인터페이스를 공개할 COM 오브젝트를 생성하고 적절하게 등록을 하면 윈도 쉘 위에서의 처리실행방법을 제어하고 경우에 따라서는 영향을 줄 수 있게 됩니다.필요한 환경 이 IShell ExecuteHook 쉘 확장은 Windows 98과 Windows 2000에서 지원되며 Windows 95와 Windows NT 4.0에서도 Active Desktop Shell Update가 설치되어 있는 경우에만 지원됩니다.후자의 시스템에서는, IE 4.01의 셋업을 통해서만(심지어 필요한 옵션을 온으로 했을 경우만) Active Desktop 을 인스톨 할 수 있다고 하는 점에 주의해 주세요.Shell Execute 함수와 Shell Execute Ex함수 IShell Execute Hook을 구현한 COM 개체는 Shell Execute 및 Shell Execute Ex 호출에 대한 훅을 실현하는 셸 확장입니다.이 두 API 함수에는 매우 재미있는 기능이 몇 가지 있습니다.먼저, 이러한 함수에서는 명령줄에 나와있는 파일 이름을 받고 연관된 실행 가능 파일의 이름을 얻을 수 있습니다.관리자에 의해 설정된 시스템 정책을 따를 수 있습니다.예를 들어 어떤 권한 세트를 가진 사용자에 대해서는 시스템 정책에서 정의되어 있는 특정 그룹의 응용 프로그램을 실행시키고 싶지 않습니다.ShellExecute와 ShellExecuteEx를 사용하면 새 프로세스를 작성하기 전에 시스템 정책을 조사할 수 있습니다(CreateProcess나 WinExec에는 이 기능이 없습니다).이 두 함수의 대략적인 실행 흐름은 다음과 같습니다.실행할 실행 가능 파일의 이름을 가져온다.이 이름은 실파라미터로서 건네지거나, 레지스트리로부터 취득된다(파일명을 인수로서 건네주었을 경우).
취득한 실행 가능 파일의 이름을 실행 시스템 정책과 대조한다.
등록되어 있는 모든 IShell Execute Hook 확장을 호출한다.
모든 것이 속행 가능할 경우에는 새로운 프로세스를 생성하여 제어를 반환한다.Shell Execute와 Shell Execute Ex는 주로 Windows 셸이 탐색기 상의 다양한 일반적 조작을 시작할 때 사용됩니다.폴더 항목을 더블 클릭하기, 폴더의 컨텐츠를 보기, 문서를 인쇄 또는 편집하기, 속성 대화 상자를 표시하기, 컨텍스트 메뉴에서 항목을 선택하기와 같은 일반적인 조작 사이사이에는 이 중 하나의 함수가 호출되고 있습니다.또,[스타트]메뉴의[파일명을 지정해 실행]다이알로그 박스도, ShellExecuteEx 를 통해서 프로그램을 실행하고 있습니다.MS-DOS 프롬프트에서 사용할 수 있는 start.exe 명령줄 유틸리티도 마찬가지입니다.즉, 사용자가 셸을 통해 행하는 조작은 모두 이 Shell Execute 훅에 의해 포착된다는 것입니다.또한 이 훅은 프로그램적으로 야기된 셸 조작도 검출합니다.셸 로깅 유틸리티 작성 셸 로깅 유틸리티를 작성하려면 먼저 ATL을 사용하여 최소한의 COM 개체를 만듭니다.여기서 필요한 것은 단순한 COM 인 프로세스 오브젝트이기 때문에, 생의 C++도 사용하도록 하겠습니다.이 ATL 컴포넌트는 수작업으로 작성한 ′IShell Execute Hook Impl.h′ 헤더 파일에서 IShell Execut Hook 인터페이스를 상속받는 형태로 이 인터페이스를 구현하고 있음을 주의해 주십시오.리스트1
# include
# include < ShlObj . h >
class ATL _ NO _ VTABLE
IShellExecuteHookImpl : public IShellExecuteHook
{
public :
// IUnknown
//
STDMETHOD ( QueryInterface ) ( REFIID riid , void ** ppvObject ) = 0;
_ ATL _ DEBUG _ ADDREF _ RELEASE _ IMPL ( IShellExecuteHookImpl )
// IShellExecuteHook
//
STDMETHOD ( Execute ) ( LPSHELLEXECUTEINFO lpsei )
{ return S _ FALSE ; }
}; 리스트 1은 ATL 객체의 헤더 파일의 완전한 소스 코드를 보여 줍니다.IShell ExecuteHook 인터페이스를 퍼블릭으로 정의하고 Execute 메서드를 오버라이드하고 있음을 주목하십시오.BEGIN _ COM _ MAP ( CLogger )
COM _ INTERFACE _ ENTRY ( ILogger )
COM _ INTERFACE _ ENTRY ( IShellExecuteHook )
END_COM_MAP()리스트 2
// ILogger
public :
STDMETHOD(Execute)(LPSHELL EXE CUTE INFO lpsei); 리스트 2는 셸을 통해 실행되는 모든 조작을 검출하고 로그에 기록하는데 필요한 코드를 나타내고 있습니다.이 셸 확장을 적절하게 등록하면(자세한 내용은 후술), 머신 상에서 동작하는 소프트웨어가 ShellExecute 또는 ShellExecuteEx를 호출할 때마다 이 예의 Execute 메서드가 자동으로 호출됩니다.Execute 메서드는 어떤 처리든 실행시킬 수 있고 조작 자체를 중지할 수도 있습니다.Execute 메서드는 SHELL EXECUTE INFO라고 하는 구조체를 인수로 받습니다.SHELL EXE CUTE INFO 구조체
typedef struct _ SHELLEXECUTEINFO {
DWORD cbSize ;
ULONG fMask ;
HWND hwnd ;
LPCTSTR lpVerb ;
LPCTSTR lpFile ;
LPCTSTR lpParameters ;
LPCTSTR lpDirectory ;
int nCmdShow ;
HINSTANCE hInstApp ;
// Optional members
LPVOID lpIDList ;
LPCSTR lpClass ;
HKEY hkeyClass ;
DWORD dwHotKey ;
HANDLE hIcon ;
HANDLE hProcess ;
} SHELL EXE CUTEINFO, FAR * LPSHELL EXE CUTEINFO; 이제 실행하고자 하는 조작은 lpVerb 구성원으로 나타납니다.또한 lp File 구성원은 처리 대상 파일의 이름이 포함됩니다.조작은 단순한 문자열로, 일부의 쉘 관련의 문서에서는, 이것을 「verb(동사:일본어판에서는 액션)」라고 부르기도 합니다.조작을 나타내는 문자열에는 open
edit
explore
properties
find 등 컨텍스트 메뉴 항목의 이름을 사용할 수 있습니다.Execute메서드는 셰일이 시작하려는 실행 가능 파일 앞으로 하는 조작에 대한 정보를 받습니다.단, 경우에 따라서는 lp File 구성원에 실행가능 파일명이 포함되어 있지 않을 수 있습니다.이러한 상황이 되는 것은 Shell Execute가 문서 파일명을 받았을 때입니다.사용자가 .txt 파일을 더블 클릭했을 때는 실제로는 그 텍스트 파일을 실행하도록 셸에게 요구하게 됩니다.그 때문에 Windows는, 그 텍스트 파일명을 실행 가능 파일명으로서 지정하고, ShellExecute 를 호출합니다.ShellExecute는 .txt 클래스의 문서에 관련지어져 있는 「.exe」 파일의 이름을 내부적으로 취득해, 그 「.exe」 파일을 실행합니다.이 이름을 반환하는 것이 Find Executable이라고 하는 API 함수입니다.간단히 말하면, Execute메서드는 사용자가 실행하려는 실행 가능 파일 그 인수 작업 디렉토리, 액티베ー션후라그을 받습니다.단, 예외인 nCmdShow를 제외하고는 기본 동작을 변경하기 위해서 그 자리에서 수정할 수 있는 것은 없습니다. nCmdShow는 호출원 어플리케이션의 메인 창을 여는 방법을 정의하는 인수이며, 최소화, 극대화, 원래 크기 등을 나타냅니다.이것은 그 자리에서 수정할 수 있는 유일한 파라미터입니다.수행 가능한 파일의 이름이나 기타 명령줄 인수에 대해 추가한 변경은 유감스럽게도 무시됩니다.따라서 Execute 내에서 할 수 있는 일은 거의 두 가지로 압축됩니다.앞으로 일어날 것을 매복하는데 그치느냐, 그 조작을 자신의 책임으로 완료시키느냐입니다.조작의 프리 프로세스가 완료되면 셸에게 이미 정해진 태스크를 계속 수행하거나 그 이상의 처리가 필요하지 않음을 셸에게 알릴 수 있습니다.이것은 Execute가 반환되는 값에 따라 결정됩니다.자,그럼첫번째방법을좀더자세히살펴보도록하겠습니다.Execute의 반환가는 ′조작이 끝났는지 여부′라는 질문에 대한 답을 나타냅니다.답이 S_FALSE인 경우는 그 명령어에 관련지어져 있는 기본 동작을 셸이 계속하고 있습니다.답이 S_OK이면 셸 확장에 의해 조작이 올바르게 완료된 것이며 셸은 아무 것도 수행하지 않습니다.반환값이 오류 코드일 경우 또는 기타 미지의 값일 경우에는 오류 메시지가 반환됩니다.그럼 이걸 어떻게 이용하면 되죠?이 기능의 이용 예로서 생각할 수 있는 것은 특정 파라미터가 지정되었을 때, 또는 특정 유저로부터 실행되었을 때 특정 실행가능 파일의 실행을 저지하는 것입니다.그러면 개인적인 정책 매니저를 작성할 수 있습니다.예를 들어 다음 코드 예에서는 레지스트리 설정에 관계없이 모든 .bmp 파일의 실행을 저지하고 있습니다.strlwr (( LPSTR ) lpsei - > lpFile ) ;
if ( strstr ( lpsei - > lpFile , _ T ( ′ . bmp ′ )))
return S_OK; 쉘 로깅 유틸리티에서 수행해야 하는 처리는 저장해야 할 모든 정보를 수집하고 로그 파일을 새로 고치는 것뿐입니다.TCHAR szText [ BUFSIZE ] ;
wsprintf ( szText , _ T ( ′ % s : % s at % s r n ′ ) ,
lpsei->lpVerb, lpsei->lpfile, szTime); 위 코드는 다음과 같은 행을 포함하는 로그 파일을 생성합니다. open: C:WINNTexplorer.exe at 5:41:18 PM 사용자 이름 및 기타 데이터를 필요에 따라 추가하면 됩니다.일반적으로 셸이 수행하고 있는 특정 파일을 처리하는 방법이나 특정 작업을 해결하는 방법이 마음에 들지 않을 경우 자체적으로 실행할 수 있습니다.예를 들어, 어떤 특정 프로그램에서 아이콘의 속성 대화상자에는 일절 나타나지 않는(사용자로 보이지 않는) 명령줄을 사용하고 싶습니다.개발자는 올바른 명령줄을 사용하여 프로그램을 실행할 수 있으며 실행 후에는 더 이상의 처리를 하지 않도록 셸에게 지시할 수 있습니다.단 이 경우에는 ShellExecute 또는 ShellExecuteEx를 사용하여 실행 가능 파일을 실행할 수 없습니다.실제로 이를 행하면 ShellExecute 또는 ShellExecuteEx 함수에 대한 새로운 호출이 ShellExecute 훅에 대한 새로운 호출을 생성하기 때문에 무한 루프에 들어가 버립니다.실행 가능 파일을 실행하려면 CreateProcess 또는 WinExec을 통해 수정된 명령줄을 사용해야 합니다.이들 함수는 ShellExecute 훅에서는 검출되지 않습니다.프로세스를 생성한 후에는 셸에 S_OK를 반환하고 종료합니다.Shell Execute 훅의 등록 Shell Execute 훅을 기능시키려면 일련의 적절한 레지스트리 키가 필요합니다.다음 소스 코드는 ATL 프로젝트의 RGS 파일에 추가하는 ATL 스크립트입니다.레지스트리 등록용 ATL 스크립트
HKLM {
SOFTWARE {
Microsoft {
Windows {
CurrentVersion {
Explorer {
ShellExecuteHooks {
val { CLSID } = s ′ Description ′
}}}}{CLSID}문자열부분을실제ATL객체의CLSID로교체하여컴포넌트에대한설명을기술합니다.설명을 추가하는 것은 필수는 아니지만 알기 쉽게 하기 위해서는 추가하는 것이 좋습니다.CLSID는 결코 이해하기 쉬운 것이 아니기 때문에 여러 개의 셸 훅을 추가하게 되면 어느 것이 어느 것인지 식별하는 것이 매우 어려워집니다.위 스크립트에서는 ′HKEY_LOCAL_MACHINE′ 아래에 트리를 만들고 ′Explorer′ 노드 아래에 있는 ′Shell Execute Hooks′ 항목에 사용할 수 있는 모든 훅 목록을 정리합니다.Windows 의 인스톨 직후는, 훅은 1개도 인스톨 되어 있지 않습니다.그러나, 사용하고 있는 사이에 몇 개의 Shell Execute 훅이 작성될 수 있습니다.이 경우 셸이 어떤 논리를 바탕으로 훅을 로드하고 있는지는 밝혀지지 않았습니다.제 추측으로는 셸 확장 시간표에 따라 오래된 것부터 순서대로 로딩하고 있는 것이 아닐까 생각합니다.레지스트리 키의 타임스탬프는 RegEnumKeyEx API 함수를 사용하여 얻을 수 있습니다.그러나 여기에서 중요한 것은 셸 확장이 S_OK를 반환했을 때 기타 호출을 셸에 정지시키는 것입니다.셸의 동작을 가상 코드로 나타내면 다음과 같이 됩니다.For Each extension In ShellExecuteHooks
Load extension
Invoke Execute ( )
If return _ value Is S _ OK Then Exit
Next의 상상과 같이 이 방식은 특정 확장을 확실히 해야 하는 경우에는 문제가 됩니다.이 문제의 회피책을 생각해 봅시다.한 가지 방법은 당신이 작성한 셸 확장을 셋업할 때 기존의 셸 확장을 모두 기록한 후 삭제하는 것입니다.그런 다음 당신의 셸 확장을 등록하고 다른 셸 확장에 대해 다시 작성합니다.이렇게 하면 셸 측은 당신의 셸 확장을 가장 오래된 것으로 인식합니다.Shell Execute 훅에 대한 주의 Shell Execute 훅은 모든 상황에서 시스템을 감시하는 완벽한 툴이 아니라는 점에 주의하십시오.이것은 Shell Execute와 Shell Execute Ex의 본체에 커스텀 코드를 삽입하기 위한 수단에 지나지 않습니다.이 두 함수는 주로 셸 내에서 사용되지만 탐색기 내에서 발생할 수 있는 모든 이벤트를 제어할 수 있는 것은 아닙니다.예를 들어 컨텍스트 메뉴에서 사용할 수 있는 명령어는 모두 ShellExecute를 통해 실행된다고 생각하는 사람도 있을 수 있습니다만 그것은 컨텍스트 메뉴의 [속성] 명령에 관해서는 잘못되었습니다.[프로퍼티]다이알로그 박스를 인터셉트 해 리다이렉트하기 위해서 Shell Execute 훅을 작성했을 경우는, 그것이 잘 작동하지 않는다는 것을 알게 될 것입니다.유저가 임의의 폴더내의 임의의 파일을 오른쪽 클릭해[프로퍼티]를 선택했을 때는, SHELLEXE CUTEINFO의 lpVerb 필드가 properties로 설정될 것입니다.그러나 유감스럽게도 사용자가 작업을 수행해도 셸 확장은 트리거되지 않으며 따라서 이벤트를 훅할 수도 없습니다.놀랍게도, 약간의 C++ 코드를 기술하고, 다음과 같이 「properties」를 동사로 지정하고 Shell Execute 또는 Shell Execute Ex를 호출하면, Shell Execute (NULL,
′ properties ′ ,
′ foo . txt ′ ,
NULL ,
NULL ,
SW_SHOW); 후크는 정상적으로 호출됩니다.이건 대체 뭘 의미하는 걸까요?그것은, 셸은[프로퍼티]다이알로그 박스를 표시할 경우에 ShellExecute 를 사용하고 있지 않다고 하는 것입니다.IShell ExecuteHook 인터페이스는 유용하며, 몇몇 상황에서는 큰 도움이 됩니다.그러나 이 인터페이스 사용을 상사에게 제안하기 전에 그것으로 정말 문제가 해결되는지 확인해 두는 것이 좋습니다.왜냐하면 예전에 저는 이것을 사용해서 언뜻 보기에는 불가능했던 문제를 해결했지만, 그래서 실패한 적도 여러 번 있기 때문입니다.
취득한 실행 가능 파일의 이름을 실행 시스템 정책과 대조한다.
등록되어 있는 모든 IShell Execute Hook 확장을 호출한다.
모든 것이 속행 가능할 경우에는 새로운 프로세스를 생성하여 제어를 반환한다.Shell Execute와 Shell Execute Ex는 주로 Windows 셸이 탐색기 상의 다양한 일반적 조작을 시작할 때 사용됩니다.폴더 항목을 더블 클릭하기, 폴더의 컨텐츠를 보기, 문서를 인쇄 또는 편집하기, 속성 대화 상자를 표시하기, 컨텍스트 메뉴에서 항목을 선택하기와 같은 일반적인 조작 사이사이에는 이 중 하나의 함수가 호출되고 있습니다.또,[스타트]메뉴의[파일명을 지정해 실행]다이알로그 박스도, ShellExecuteEx 를 통해서 프로그램을 실행하고 있습니다.MS-DOS 프롬프트에서 사용할 수 있는 start.exe 명령줄 유틸리티도 마찬가지입니다.즉, 사용자가 셸을 통해 행하는 조작은 모두 이 Shell Execute 훅에 의해 포착된다는 것입니다.또한 이 훅은 프로그램적으로 야기된 셸 조작도 검출합니다.셸 로깅 유틸리티 작성 셸 로깅 유틸리티를 작성하려면 먼저 ATL을 사용하여 최소한의 COM 개체를 만듭니다.여기서 필요한 것은 단순한 COM 인 프로세스 오브젝트이기 때문에, 생의 C++도 사용하도록 하겠습니다.이 ATL 컴포넌트는 수작업으로 작성한 ′IShell Execute Hook Impl.h′ 헤더 파일에서 IShell Execut Hook 인터페이스를 상속받는 형태로 이 인터페이스를 구현하고 있음을 주의해 주십시오.리스트1
# include
# include < ShlObj . h >
class ATL _ NO _ VTABLE
IShellExecuteHookImpl : public IShellExecuteHook
{
public :
// IUnknown
//
STDMETHOD ( QueryInterface ) ( REFIID riid , void ** ppvObject ) = 0;
_ ATL _ DEBUG _ ADDREF _ RELEASE _ IMPL ( IShellExecuteHookImpl )
// IShellExecuteHook
//
STDMETHOD ( Execute ) ( LPSHELLEXECUTEINFO lpsei )
{ return S _ FALSE ; }
}; 리스트 1은 ATL 객체의 헤더 파일의 완전한 소스 코드를 보여 줍니다.IShell ExecuteHook 인터페이스를 퍼블릭으로 정의하고 Execute 메서드를 오버라이드하고 있음을 주목하십시오.BEGIN _ COM _ MAP ( CLogger )
COM _ INTERFACE _ ENTRY ( ILogger )
COM _ INTERFACE _ ENTRY ( IShellExecuteHook )
END_COM_MAP()리스트 2
// ILogger
public :
STDMETHOD(Execute)(LPSHELL EXE CUTE INFO lpsei); 리스트 2는 셸을 통해 실행되는 모든 조작을 검출하고 로그에 기록하는데 필요한 코드를 나타내고 있습니다.이 셸 확장을 적절하게 등록하면(자세한 내용은 후술), 머신 상에서 동작하는 소프트웨어가 ShellExecute 또는 ShellExecuteEx를 호출할 때마다 이 예의 Execute 메서드가 자동으로 호출됩니다.Execute 메서드는 어떤 처리든 실행시킬 수 있고 조작 자체를 중지할 수도 있습니다.Execute 메서드는 SHELL EXECUTE INFO라고 하는 구조체를 인수로 받습니다.SHELL EXE CUTE INFO 구조체
typedef struct _ SHELLEXECUTEINFO {
DWORD cbSize ;
ULONG fMask ;
HWND hwnd ;
LPCTSTR lpVerb ;
LPCTSTR lpFile ;
LPCTSTR lpParameters ;
LPCTSTR lpDirectory ;
int nCmdShow ;
HINSTANCE hInstApp ;
// Optional members
LPVOID lpIDList ;
LPCSTR lpClass ;
HKEY hkeyClass ;
DWORD dwHotKey ;
HANDLE hIcon ;
HANDLE hProcess ;
} SHELL EXE CUTEINFO, FAR * LPSHELL EXE CUTEINFO; 이제 실행하고자 하는 조작은 lpVerb 구성원으로 나타납니다.또한 lp File 구성원은 처리 대상 파일의 이름이 포함됩니다.조작은 단순한 문자열로, 일부의 쉘 관련의 문서에서는, 이것을 「verb(동사:일본어판에서는 액션)」라고 부르기도 합니다.조작을 나타내는 문자열에는 open
edit
explore
properties
find 등 컨텍스트 메뉴 항목의 이름을 사용할 수 있습니다.Execute메서드는 셰일이 시작하려는 실행 가능 파일 앞으로 하는 조작에 대한 정보를 받습니다.단, 경우에 따라서는 lp File 구성원에 실행가능 파일명이 포함되어 있지 않을 수 있습니다.이러한 상황이 되는 것은 Shell Execute가 문서 파일명을 받았을 때입니다.사용자가 .txt 파일을 더블 클릭했을 때는 실제로는 그 텍스트 파일을 실행하도록 셸에게 요구하게 됩니다.그 때문에 Windows는, 그 텍스트 파일명을 실행 가능 파일명으로서 지정하고, ShellExecute 를 호출합니다.ShellExecute는 .txt 클래스의 문서에 관련지어져 있는 「.exe」 파일의 이름을 내부적으로 취득해, 그 「.exe」 파일을 실행합니다.이 이름을 반환하는 것이 Find Executable이라고 하는 API 함수입니다.간단히 말하면, Execute메서드는 사용자가 실행하려는 실행 가능 파일 그 인수 작업 디렉토리, 액티베ー션후라그을 받습니다.단, 예외인 nCmdShow를 제외하고는 기본 동작을 변경하기 위해서 그 자리에서 수정할 수 있는 것은 없습니다. nCmdShow는 호출원 어플리케이션의 메인 창을 여는 방법을 정의하는 인수이며, 최소화, 극대화, 원래 크기 등을 나타냅니다.이것은 그 자리에서 수정할 수 있는 유일한 파라미터입니다.수행 가능한 파일의 이름이나 기타 명령줄 인수에 대해 추가한 변경은 유감스럽게도 무시됩니다.따라서 Execute 내에서 할 수 있는 일은 거의 두 가지로 압축됩니다.앞으로 일어날 것을 매복하는데 그치느냐, 그 조작을 자신의 책임으로 완료시키느냐입니다.조작의 프리 프로세스가 완료되면 셸에게 이미 정해진 태스크를 계속 수행하거나 그 이상의 처리가 필요하지 않음을 셸에게 알릴 수 있습니다.이것은 Execute가 반환되는 값에 따라 결정됩니다.자,그럼첫번째방법을좀더자세히살펴보도록하겠습니다.Execute의 반환가는 ′조작이 끝났는지 여부′라는 질문에 대한 답을 나타냅니다.답이 S_FALSE인 경우는 그 명령어에 관련지어져 있는 기본 동작을 셸이 계속하고 있습니다.답이 S_OK이면 셸 확장에 의해 조작이 올바르게 완료된 것이며 셸은 아무 것도 수행하지 않습니다.반환값이 오류 코드일 경우 또는 기타 미지의 값일 경우에는 오류 메시지가 반환됩니다.그럼 이걸 어떻게 이용하면 되죠?이 기능의 이용 예로서 생각할 수 있는 것은 특정 파라미터가 지정되었을 때, 또는 특정 유저로부터 실행되었을 때 특정 실행가능 파일의 실행을 저지하는 것입니다.그러면 개인적인 정책 매니저를 작성할 수 있습니다.예를 들어 다음 코드 예에서는 레지스트리 설정에 관계없이 모든 .bmp 파일의 실행을 저지하고 있습니다.strlwr (( LPSTR ) lpsei - > lpFile ) ;
if ( strstr ( lpsei - > lpFile , _ T ( ′ . bmp ′ )))
return S_OK; 쉘 로깅 유틸리티에서 수행해야 하는 처리는 저장해야 할 모든 정보를 수집하고 로그 파일을 새로 고치는 것뿐입니다.TCHAR szText [ BUFSIZE ] ;
wsprintf ( szText , _ T ( ′ % s : % s at % s r n ′ ) ,
lpsei->lpVerb, lpsei->lpfile, szTime); 위 코드는 다음과 같은 행을 포함하는 로그 파일을 생성합니다. open: C:WINNTexplorer.exe at 5:41:18 PM 사용자 이름 및 기타 데이터를 필요에 따라 추가하면 됩니다.일반적으로 셸이 수행하고 있는 특정 파일을 처리하는 방법이나 특정 작업을 해결하는 방법이 마음에 들지 않을 경우 자체적으로 실행할 수 있습니다.예를 들어, 어떤 특정 프로그램에서 아이콘의 속성 대화상자에는 일절 나타나지 않는(사용자로 보이지 않는) 명령줄을 사용하고 싶습니다.개발자는 올바른 명령줄을 사용하여 프로그램을 실행할 수 있으며 실행 후에는 더 이상의 처리를 하지 않도록 셸에게 지시할 수 있습니다.단 이 경우에는 ShellExecute 또는 ShellExecuteEx를 사용하여 실행 가능 파일을 실행할 수 없습니다.실제로 이를 행하면 ShellExecute 또는 ShellExecuteEx 함수에 대한 새로운 호출이 ShellExecute 훅에 대한 새로운 호출을 생성하기 때문에 무한 루프에 들어가 버립니다.실행 가능 파일을 실행하려면 CreateProcess 또는 WinExec을 통해 수정된 명령줄을 사용해야 합니다.이들 함수는 ShellExecute 훅에서는 검출되지 않습니다.프로세스를 생성한 후에는 셸에 S_OK를 반환하고 종료합니다.Shell Execute 훅의 등록 Shell Execute 훅을 기능시키려면 일련의 적절한 레지스트리 키가 필요합니다.다음 소스 코드는 ATL 프로젝트의 RGS 파일에 추가하는 ATL 스크립트입니다.레지스트리 등록용 ATL 스크립트
HKLM {
SOFTWARE {
Microsoft {
Windows {
CurrentVersion {
Explorer {
ShellExecuteHooks {
val { CLSID } = s ′ Description ′
}}}}{CLSID}문자열부분을실제ATL객체의CLSID로교체하여컴포넌트에대한설명을기술합니다.설명을 추가하는 것은 필수는 아니지만 알기 쉽게 하기 위해서는 추가하는 것이 좋습니다.CLSID는 결코 이해하기 쉬운 것이 아니기 때문에 여러 개의 셸 훅을 추가하게 되면 어느 것이 어느 것인지 식별하는 것이 매우 어려워집니다.위 스크립트에서는 ′HKEY_LOCAL_MACHINE′ 아래에 트리를 만들고 ′Explorer′ 노드 아래에 있는 ′Shell Execute Hooks′ 항목에 사용할 수 있는 모든 훅 목록을 정리합니다.Windows 의 인스톨 직후는, 훅은 1개도 인스톨 되어 있지 않습니다.그러나, 사용하고 있는 사이에 몇 개의 Shell Execute 훅이 작성될 수 있습니다.이 경우 셸이 어떤 논리를 바탕으로 훅을 로드하고 있는지는 밝혀지지 않았습니다.제 추측으로는 셸 확장 시간표에 따라 오래된 것부터 순서대로 로딩하고 있는 것이 아닐까 생각합니다.레지스트리 키의 타임스탬프는 RegEnumKeyEx API 함수를 사용하여 얻을 수 있습니다.그러나 여기에서 중요한 것은 셸 확장이 S_OK를 반환했을 때 기타 호출을 셸에 정지시키는 것입니다.셸의 동작을 가상 코드로 나타내면 다음과 같이 됩니다.For Each extension In ShellExecuteHooks
Load extension
Invoke Execute ( )
If return _ value Is S _ OK Then Exit
Next의 상상과 같이 이 방식은 특정 확장을 확실히 해야 하는 경우에는 문제가 됩니다.이 문제의 회피책을 생각해 봅시다.한 가지 방법은 당신이 작성한 셸 확장을 셋업할 때 기존의 셸 확장을 모두 기록한 후 삭제하는 것입니다.그런 다음 당신의 셸 확장을 등록하고 다른 셸 확장에 대해 다시 작성합니다.이렇게 하면 셸 측은 당신의 셸 확장을 가장 오래된 것으로 인식합니다.Shell Execute 훅에 대한 주의 Shell Execute 훅은 모든 상황에서 시스템을 감시하는 완벽한 툴이 아니라는 점에 주의하십시오.이것은 Shell Execute와 Shell Execute Ex의 본체에 커스텀 코드를 삽입하기 위한 수단에 지나지 않습니다.이 두 함수는 주로 셸 내에서 사용되지만 탐색기 내에서 발생할 수 있는 모든 이벤트를 제어할 수 있는 것은 아닙니다.예를 들어 컨텍스트 메뉴에서 사용할 수 있는 명령어는 모두 ShellExecute를 통해 실행된다고 생각하는 사람도 있을 수 있습니다만 그것은 컨텍스트 메뉴의 [속성] 명령에 관해서는 잘못되었습니다.[프로퍼티]다이알로그 박스를 인터셉트 해 리다이렉트하기 위해서 Shell Execute 훅을 작성했을 경우는, 그것이 잘 작동하지 않는다는 것을 알게 될 것입니다.유저가 임의의 폴더내의 임의의 파일을 오른쪽 클릭해[프로퍼티]를 선택했을 때는, SHELLEXE CUTEINFO의 lpVerb 필드가 properties로 설정될 것입니다.그러나 유감스럽게도 사용자가 작업을 수행해도 셸 확장은 트리거되지 않으며 따라서 이벤트를 훅할 수도 없습니다.놀랍게도, 약간의 C++ 코드를 기술하고, 다음과 같이 「properties」를 동사로 지정하고 Shell Execute 또는 Shell Execute Ex를 호출하면, Shell Execute (NULL,
′ properties ′ ,
′ foo . txt ′ ,
NULL ,
NULL ,
SW_SHOW); 후크는 정상적으로 호출됩니다.이건 대체 뭘 의미하는 걸까요?그것은, 셸은[프로퍼티]다이알로그 박스를 표시할 경우에 ShellExecute 를 사용하고 있지 않다고 하는 것입니다.IShell ExecuteHook 인터페이스는 유용하며, 몇몇 상황에서는 큰 도움이 됩니다.그러나 이 인터페이스 사용을 상사에게 제안하기 전에 그것으로 정말 문제가 해결되는지 확인해 두는 것이 좋습니다.왜냐하면 예전에 저는 이것을 사용해서 언뜻 보기에는 불가능했던 문제를 해결했지만, 그래서 실패한 적도 여러 번 있기 때문입니다.
반응형