2011-12-26 2 views

답변

4

모든 셸 확장 처리기는 in-process COM (구성 요소 개체 모델) 개체입니다. 셸 확장 핸들러 등록에 설명 된대로 GUID를 할당하고 등록해야합니다. DLL로 구현되며 다음 표준 함수를 내 보내야합니다. DllMain. DLL에 대한 표준 진입 점입니다. DllGetClassObject. 오브젝트의 클래스 팩토리를 공개합니다. DllCanUnloadNow. COM이이 함수를 호출하여 개체가 클라이언트에 서비스 중인지 여부를 확인합니다. 그렇지 않은 경우, 시스템은 DLL을 언로드하고 연관된 메모리를 해제 할 수 있습니다. 모든 COM 개체와 마찬가지로 셸 확장 처리기는 IUnknown 인터페이스와 클래스 팩터 리를 구현해야합니다. 또한 대부분은 Windows XP 또는 이전 버전에서 IPersistFile 또는 IShellExtInit 인터페이스를 구현해야합니다. Windows Vista에서 IInitializeWithStream, IInitializeWithItem 및 IInitializeWithFile로 대체되었습니다. 셸에서는 이러한 인터페이스를 사용하여 처리기를 초기화합니다. IPersistFile 인터페이스는 다음에 의해 구현해야합니다

  • 아이콘 핸들러
  • 데이터 핸들러
  • 드롭 핸들러

IShellExtInit 인터페이스는 다음에 의해 구현해야합니다

  • 바로 가기 메뉴 처리기
  • 드래그 앤 드롭 핸들러
  • 속성 시트 핸들러

구현 IPersistFile IPersistFile 인터페이스는 객체에서로드 또는 디스크 파일에 저장할 수 있도록 설계되었습니다. IUnknown 이외에 6 가지 방법, 5 가지 방법과 IPersist에서 상속하는 GetClassID 방법이 있습니다. 셸 확장을 사용하면 IPersist는 셸 확장 처리기 개체를 초기화하는 데에만 사용됩니다. 일반적으로 디스크를 읽거나 쓸 필요가 없으므로 GetClassID 및 Load 메서드 만 비공개 구현이 필요합니다. 셸은 먼저 GetClassID를 호출하고이 함수는 확장 프로그램 처리기 개체의 클래스 식별자 (CLSID)를 반환합니다. 그런 다음 셸은 Load를 호출하고 두 값을 전달합니다. 첫 번째 pszFile은 Shell이 ​​작동 할 파일 또는 폴더의 이름을 가진 유니 코드 문자열입니다. 두 번째는 파일 액세스 모드를 나타내는 dwMode입니다. 일반적으로 파일에 액세스 할 필요가 없기 때문에 dwMode는 일반적으로 0입니다. 이 메서드는 나중에 참조 할 수 있도록 필요에 따라이 값을 저장합니다. 다음 코드 단편에서는 일반적인 셸 확장 처리기에서 GetClassID 및 Load 메서드를 구현하는 방법을 보여줍니다. ANSI 또는 유니 코드를 처리하도록 설계되었습니다. CLSID_SampleExtHandler는 확장 처리기 개체의 GUID이며 CSampleShellExtension은 인터페이스를 구현하는 데 사용되는 클래스의 이름입니다. m_szFileName 및 m_dwMode 변수는 파일의 이름 및 액세스 플래그를 저장하는 데 사용되는 개인 변수입니다.

class CSampleShellExtension : public IPersistFile 
{ 
    // Method declarations not included 

    private: 
    WCHAR m_szFileName[MAX_PATH]; // The file name 
    DWORD m_dwMode;     // The file access mode 
} 

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID) 
{ 
    *pCLSID = CLSID_SampleExtHandler; 
} 

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode) 
{ 
    m_dwMode = dwMode; 
    return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile); 
} 

// 구현 샘플은 다음 섹션에서 계속됩니다.

구현 IShellExtInit IShellExtInit 인터페이스의 IUnknown 외에도 하나의 방법, IShellExtInit :: 초기화가 있습니다. 이 메서드에는 셸이 다양한 유형의 정보를 전달하는 데 사용할 수있는 세 가지 매개 변수가 있습니다. 전달 된 값은 핸들러 유형에 따라 다르며 일부는 NULL로 설정할 수 있습니다. pidlFolder는 항목 식별자 목록 (PIDL)에 대한 폴더의 포인터를 보유합니다. 이것은 절대 PIDL입니다. 속성 시트 확장의 경우이 값은 NULL입니다. 바로 가기 메뉴 확장의 경우 바로 가기 메뉴가 표시되는 항목이 포함 된 폴더의 PIDL입니다. 기본이 아닌 끌어서 놓기 처리기의 경우 대상 폴더의 PIDL입니다. pDataObject는 데이터 객체의 IDataObject 인터페이스에 대한 포인터를 보유합니다. 데이터 객체는 하나 이상의 파일 이름을 CF_HDROP 형식으로 유지합니다. hRegKey는 파일 개체 또는 폴더 유형에 대한 레지스트리 키를 보유합니다. IShellExtInit :: Initialize 메서드는 나중에 사용할 수 있도록 파일 이름, IDataObject 포인터 및 레지스트리 키를 저장합니다. 다음 코드 단편은 IShellExtInit :: Initialize의 구현을 보여줍니다. 간단히하기 위해이 예제에서는 데이터 객체가 하나의 파일 만 포함한다고 가정합니다. 일반적으로 데이터 객체에는 여러 파일이 포함될 수 있으며 각 파일은 추출해야합니다.

// This code continues the CSampleShellExtension sample shown in the 
// "Implementing IPersistFile" section above. 

class CSampleShellExtension : public IShellExtInit { 
    // Method declarations not included 

    private: 
    // IDList of the folder for extensions invoked on the folder, such as 
    // background context menu handlers or nondefault drag-and-drop handlers. 
    PIDLIST_ABSOLUTE m_pidlFolder; 

    // The data object contains an expression of the items that the handler is 
    // being initialized for. Use SHCreateShellItemArrayFromDataObject to 
    // convert this object to an array of items. Use SHGetItemFromObject if you 
    // are only interested in a single Shell item. If you need a file system 
    // path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...). 
    IDataObject *m_pdtobj; 

    // For context menu handlers, the registry key provides access to verb 
    // instance data that might be stored there. This is a rare feature to use 
    // so most extensions do not need this variable. 
    HKEY m_hRegKey;    } 
     // This method must be very efficient. Do not do any unnecessary work here. 
    // Use Initialize to acquire resources that will be used later. 
    IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTEpidlFolder,__in_opt IDataObject *pDataObject, __in_opt HKEY hRegKey) 
    { 
    // In some cases,handlers are initialized multiple times. Therefore, 
    // clear any previous state here. 
    CoTaskMemFree(m_pidlFolder); 
    m_pidlFolder = NULL; 

    if (m_pdtobj) 
    { 
     m_pdtobj->Release(); 
    } 

    if (m_hRegKey) 
    { 
     RegCloseKey(m_hRegKey); 
     m_hRegKey = NULL; 
    } 

    // Capture the inputs for use later. 
    HRESULT hr = S_OK; 

    if (pidlFolder) 
    { 
     m_pidlFolder = ILClone(pidlFolder); // Make a copy to use later. 
     hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY; 
    } 

    if (SUCCEEDED(hr)) 
    { 
     // If a data object pointer was passed into the method, save it and 
     // extract the file name. 
     if (pDataObject) 
     { 
      m_pdtobj = pDataObject; 
      m_pdtobj->AddRef(); 
     } 

     // It is uncommon to use the registry handle, but if you need it, 
     // duplicate it now. 
     if (hRegKey) 
     { 
      LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey); 
      hr = HRESULT_FROM_WIN32(result); 
     } 
    } 

    return hr; } 

셸 확장 처리기를 만들거나 변경할 때마다 변경 한 사항을 시스템에 알리는 것이 중요합니다. 그렇게하려면 SHChangeNotify를 호출하고 SHCNE_ASSOCCHANGED 이벤트를 지정하십시오. SHChangeNotify를 호출하지 않으면 시스템이 다시 부팅 될 때까지 변경 내용이 인식되지 않을 수 있습니다. Windows 2000 시스템에 적용되는 몇 가지 추가 요소가 있습니다. 자세한 내용은 Windows 2000 시스템에서 셸 확장 핸들러 등록 섹션을 참조하십시오. 모든 COM (Component Object Model) 개체와 마찬가지로 Windows SDK (Software Development Kit)와 함께 제공되는 Guidgen.exe와 같은 도구를 사용하여 처리기에 대한 GUID를 만들어야합니다. 해당 GUID의 문자열 형식 인 HKEY_CLASSES_ROOT \ CLSID 아래에 하위 키를 만듭니다. 셸 확장 처리기가 in-process 서버이기 때문에 처리기의 DLL 경로로 설정된 (기본값) 값을 사용하여 해당 GUID 하위 키에서 InprocServer32 하위 키를 만들어야합니다. 아파트 스레딩 모델을 사용하십시오. 예는 여기에 표시됩니다 :

HKEY_CLASSES_ROOT CLSID 
     {00021500-0000-0000-C000-000000000046} 
      InprocServer32 
      (Default) = %windir%\System32\Example.dll 
      ThreadingModel = Apartment 

셸 쉘 확장 핸들러를 포함 할 수있는 작업을 수행 할 때마다, 그것은 적절한 레지스트리 하위 키를 확인합니다. 확장명 처리기가 등록되는 하위 키를 호출하면 해당 하위 키가 제어됩니다. 예를 들어, 셸이 파일 형식의 멤버에 대한 바로 가기 메뉴를 표시 할 때 호출되는 바로 가기 메뉴 처리기를 갖는 것이 일반적입니다. 이 경우 처리기는 파일 형식의 ProgID 하위 키 아래에 등록되어 있어야합니다.

+1

이것은 [더 기본적인 질문] (http://stackoverflow.com/questions/8438066)에서 그런 개요를 원했던 정말 대단한 대답입니다. 너가 현상금을 얻을 것 같아. 그러나 카테고리는 어디에서 변경할 수 있습니까? 스크린 샷의 빨간색 상자. – rekire

+1

훌륭한 분석 .... 정말 도움이됩니다. –