2011. 3. 31. 09:25

Windows 확장자 등록 Helper 함수 공유


Windows의 확장자 등록하기 위해서는 HKLM이나 HKCU 등의 레지스트리에 값을 기입해야 합니다.
(MSDN을 통해 암만 찾아봐도 ShellAPI등 Win32 API로 지원되지는 않더군요.)

HKLM등에 쓰기 위해서는 권한등이 필요하고, HKCU값이 있다면, 해당 값으로 redirect되기 때문에,
되도록이면 HKCU에 값을 쓰는 것을 권장하고 싶습니다.

물론, 제품을 설치할때 HKLM에 써서 모든 사용자에게 영향을 주는 것도 좋다고 보지만,
Application에서 각자의 환경 설정을 통해, 확장자 등록 여부를 봐서 로그인한 계정에서만 영향을
주도록 HKCU에 값을 쓰는 것이 좀더 현명해 보입니다.

즉, Application에서는 프로그램 시작시,

  • 확장자 등록이 되어 있는가? (로그인한 계정으로) - (1)
  • 확장자 등록이 되어 있지 않다면, 확장자 등록 여부를 사용자에게 질의한다.
  • 사용자가 Yes 한다면, 확장자 등록한다.
  • 사용자가 No 한다면, 앞으로 (1) 과정을 실행하지 않는다.

와 같은 스텝을 밟도록 하는 것입니다.

그렇다면, 각 계정의 HKCU 값을 썻다면, 삭제시 이슈가 될 수 있습니다.
그래서, 삭제할 때는 모든 계정으로 Enum하면서 삭제하는 기능을 추가하였습니다.

DWORD RegisterExt
IN LPCTSTR lpszExtName
N LPCTSTR lpszAppClassName
IN LPCTSTR lpszLauncherPath
IN LPCTSTR lpszArgument

확장자를 등록합니다(HKCU).
lpszExtName : 등록할 확장자 이름. 예) "tst"
lpszAppClassName : 등록할 확장자가 연결될 Class 이름. 예) "my_application_name"
lpszLauncherPath : 실행될 경로. 예) "C:\Windows\notepad.exe"
lpszArgument : 실행될때의 Argument. 예) "%1"
리턴 : Win32 Error Code

BOOL IsRegisterExt
IN LPCTSTR lpszExtName,
OPTIONAL OUT LPBOOL pbDangling
확장자 등록 여부를 확인합니다(HKLM/HKCU).
여부 확인은 Win32 Shell API를 사용합니다. (AssocQueryString)
lpszExtName : 확장자 이름. 예) "tst"
pbDangling : 연결된 프로그램이 존재하는지 여부. NULL 전달 가능 (%windir%같은 경우 확장되지 못함)
리턴 : TRUE (등록되어 있음) / FALSE (등록되어 있지 않음)

VOID UnRegisterExt
IN LPCTSTR lpszExtName
IN LPCTSTR lpszAppClassName
OPTIONAL IN BOOL bDeleteAllUser
확장자 등록을 해제합니다. (HKCU, ALL USER, not HKLM)
lpszExtName : 삭제할 확장자 이름. 예) "tst"
lpszAppClassName : 삭제할 Class Name. 예) "my_application_name"
bDeleteAllUser : 모든 사용자에 대해서 삭제 여부. HKCU의 모든 사용자를 삭제할 때 사용. 단, Admin 권한 필요.

즉, 사용법은,
#include "apputil.h"
...
void somefunc(void)
{
...
 CAppUtil::RegisterExt(TEXT("abc"), TEXT("myapplication.ver.1"), TEXT("C:\myapp\myapp.exe"), TEXT("/load:%1"));
...
와 같습니다.

그리고, IsRegisterExt에서, 만약 등록된 경로가 %windir%같은 경우 체크가 되지 않으니 주의하시기 바랍니다.
(ExpandEnvironmentStrings(...)등을 사용하면 되니, 필요하면 코드를 수정하세요)

그리고, 삭제할 때, 만약, 동일 확장자로 다른 Application이 등록되어 있다면, 자칫 잘 못 될 수 있습니다.
현재 ClassName을 구해서 전달해야 할 듯 합니다. 필요한 경우 코드를 수정하세요.
또한, 삭제의 대상이 HKCU이기 떄문에 HKLM에도 등록되어 있다면, 해당 확장자의 등록 해제는 안됩니다.
(즉, CAppUtil의 API만 사용했떄 등록된 확장자에는 문제가 되지 않습니다. HKCU로만 썻기 때문입니다.)

그리고, 모든 User에 대해 삭제할 때에는 관리자권한에서 실행되어야 합니다.