본문 바로가기

망각/Windows Shell

SHChangeNotifyRegister 사용중 의문점

첫번째- PIDL 관련, simple PIDL?

::SHChangeNotifyRegister(hwnd, SHCNRF_ShellLevel, SHCNE_RENAMEFOLDER, MY_MESSAGE, 1, &entry);
위 처럼 폴더의 이름변경을 알기 위해 메시지를 등록했다. 전에 글에서 적은 것처럼 메시지의 WPARAM로 변경된 폴더 관련 PIDL이 넘어온다. 이 PIDL(absolute)을 이용해 ::SHBindToParent() 함수에서 부모폴더의 IShellFolder 인터페이스와 부모폴더에 상대적인 PIDL을 얻었다.
::SHBindToParent(fullyPidl, IID_IShellFolder, (void**)&iparent, (LPCITEMIDLIST*)&childPidl))

iparent->BindToObject(childPidl, 0, IID_IShellFolder, (void**)&ifolder); ///< 여기서 실패
문제는 여기서 자식 PIDL을 이용해 폴더의 IShellFolder 인터페이스를 구하고 할 때 발생한다. 부모폴더의 IShellFolder::BindToObject() 메서드에 PIDL을 전달했는데 호출이 실패한다. HRESULT 에러 값을 보면 해당 객체를 찾을 수 없다고 한다.
왜 그럴까? 왜 그럴까?
_M#]

두번째- 하드 드라이브 이름변경 관련

이름변경 메시지가 전달되면 WPARAM을 이용해 기존 PIDL과 새 PIDL을 얻고 이를 이용해 변경 전의 폴더이름과 변경 후의 폴더이름을 얻을 수 있다. 헌데 My Computer의 하위 노드들인 C:\, D:\ 같은 드라이브의 이름을 바꾸면 기존 PIDL로도 변경된 폴더이름이 얻어진다. :-0

일단 다른 탐색기에서 이름이 변경된 폴더의 경우, 그 폴더와 하위 폴더들의 PIDL과 IShellFolder 인터페이스들을 그대로 사용할시 에러가 발생한다. 내 탐색기 트리에서 이름 변경된 노드와 열려진 그 하위노드들에 설정된 IShellFolder 인터페이스들을 모두 갱신해주지 않고 CreateViewObject를 호출하면 쉘이 해당 폴더를 찾을 수 없다는 에러메시지 박스를 뿌리고 호출에 실패한다.

웃긴게, 이 드라이브들은 내 탐색기에서 이름변경과 PIDL, IShellFolder 인터페이스 갱신도 못했는데, 기존 IShellFolder 페이스를 사용해 CreateViewObject 인터페이스를 생성해도 에러박스가 뜨지 않고 메서드호출이 성공한다는 것!

왜 한가지 방법으로 다 안되는 것일까, 예외 사항이 너무 많다.
참으로 어찌된 상황인지 궁금하지 않을 수 가 없다.~

세번째- 메시지 전달 횟수 관련

SHCNE_RMDIRSHCNE_MKDIR, SHCNE_RENAMEFOLDER 통지를 받기 위해 사용중인데,
이벤트가 일어난 폴더 위치에 따라 각 이벤트의 경우마다 등록한 메시지 전달 횟수가 다르다.
내 시스템에서(XP64)에서
'내 컴퓨터'나 '내 문서'처럼 가상 폴더가 아닌 경우 메시지 전달 수
  • SHCNE_RMDIR - 한번
  • SHCNE_MKDIR - 한번
  • SHCNE_RENAMEFOLDER - 두번
'바탕화면'의 경우
  • SHCNE_RMDIR - 두번
  • SHCNE_MKDIR - 두번
  • SHCNE_RENAMEFOLDER - 다섯번
'내 문서'의 경우
  • SHCNE_RMDIR - 세번
  • SHCNE_MKDIR - 세번
  • SHCNE_RENAMEFOLDER - 열번
메시지가 여러번 보내지는 이유는 정확히 모르겠지만, 실제 폴더를 말고도 가상폴더나 다른 곳에 어떻게든 물려있는 수만큼 보내지는 듯 하다. 다른 시스템에서도 몇번 전달되는지 확인해보자(시스템 환경마다 다른 듯하다).

가상 폴더라고 썼는데 했는데, 자세한 건 이곳에서 살펴보자.

네번째 - 콘솔(cmd.exe)에서의 변경 확인 안됨

콘솔에서 폴더작업(생성,삭제,이름변경)시 반응이 없다(SHCNE_RENAMEFOLDER, SHCNE_MKDIR, SHCNE_RMDIR). 예외적으로 '바탕화면' 아래 있는 경로상의 폴더 작업은 SHCNE_UPDATEDIR을 사용해서 확인이 되고, 이 통지의 대상 폴더는 '바탕화면'이다(넘어오는 PIDL).
  1. Desktop으로부터의 절대적 경로를 따지는 absolute PIDL(fully PIDL)을 말하는 것이 아니라, 관련 정보를 모두 가진 PIDL이라는 뜻. [본문으로]