2012-02-23 3 views
1

셸 확장 dll을 사용하여 폴더 경로를 캡처하는 방법, 사용자가 폴더의 빈 영역을 클릭하면 어떻게됩니까?셸 확장 DLL - 사용자가 폴더의 빈 영역을 클릭하면 폴더 경로를 캡처하는 방법?

+0

당신이 [GetCurrentDir] 호출 (HTTP를 시도 했 파일에 RegisterShellExtContextMenuHandler 및 UnregisterShellExtContextMenuHandler 기능을 업데이트 : //msdn.microsoft.com/en-us/library/aa364934%28VS.85%29.aspx)? –

+1

@dario_ramos : 잘못된 기능. _some_ 시스템에는 모든 Explorer 창에 대해 하나의 Explorer 프로세스가 있습니다. 두 개의 다른 폴더에 두 개의 창이 열리면'GetCurrentDir'은 _both_를 반환 할 수 없습니다. ("별도의 프로세스로 새 창 열기"를 사용하도록 설정 한 경우 작동 할 수 있습니다. 그러나 보장되지는 않습니다.) – MSalters

답변

5

셸 확장 dll을 구현하는 경우 IShellExtInit::Initialize( 메서드의 경로를 pidlFolder 매개 변수로 가져옵니다.

확장도 폴더 배경에 등록되어 있는지 확인하려면, 당신은 HKCR\Directory\Background\shellex\ContextMenuHandlers VC와

+0

폴더 안을 클릭하면 빈 영역이 생기고 "pidlFolder"는 NULL이됩니다. – Ullan

+0

셸 확장에 없습니다. 폴더 배경 (빈 영역)을 마우스 오른쪽 버튼으로 클릭하면 pidlFolder가 NULL이 아닙니다. – Stefan

+0

하지만 경로를 얻기 위해 pidlFolder를 사용하면 QueryContextMenu 함수가 하이 파이킹되지 않는 문제가 있습니다. – Ullan

0

하에서도 적절한 항목을 작성해야 ++ 언어이 문서를 참조하십시오 C 번호로 WinMerge는 소스도 코드 http://sourceforge.net/p/winmerge/code/HEAD/tree/trunk/ShellExtension/

를 참조하시기 바랍니다 http://www.codeproject.com/Articles/174369/How-to-Write-Windows-Shell-Extension-with-NET-Lang 와 울부 짖는 소리 어떤 장소를 업데이트 를 FileContextMenuExt.cs 파일에서 :

...............

#region Shell Extension Registration 

    [ComRegisterFunction()] 
    public static void Register(Type t) 
    { 
     try 
     { 
      ShellExtReg.RegisterShellExtContextMenuHandler(t.GUID, "Directory", 
       "CSShellExtContextMenuHandler.FileContextMenuExt Class"); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); // Log the error 
      throw; // Re-throw the exception 
     } 
    } 

    [ComUnregisterFunction()] 
    public static void Unregister(Type t) 
    { 
     try 
     { 
      ShellExtReg.UnregisterShellExtContextMenuHandler(t.GUID, "Directory"); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); // Log the error 
      throw; // Re-throw the exception 
     } 
    } 

    #endregion 
    ............... 

    public void Initialize(IntPtr pidlFolder, IntPtr pDataObj, IntPtr hKeyProgID) 
    { 
     if (pDataObj == IntPtr.Zero && pidlFolder == IntPtr.Zero) 
     { 
      throw new ArgumentException(); 
     } 

     FORMATETC fe = new FORMATETC(); 
     fe.cfFormat = (short)CLIPFORMAT.CF_HDROP; 
     fe.ptd = IntPtr.Zero; 
     fe.dwAspect = DVASPECT.DVASPECT_CONTENT; 
     fe.lindex = -1; 
     fe.tymed = TYMED.TYMED_HGLOBAL; 
     STGMEDIUM stm = new STGMEDIUM();   

     try 
     { 
      if (pDataObj != IntPtr.Zero) 
      { 
       // The pDataObj pointer contains the objects being acted upon. In this 
       // example, we get an HDROP handle for enumerating the selected files 
       // and folders. 
       IDataObject dataObject = (IDataObject)Marshal.GetObjectForIUnknown(pDataObj); 
       dataObject.GetData(ref fe, out stm); 

       // Get an HDROP handle. 
       IntPtr hDrop = stm.unionmember; 
       if (hDrop == IntPtr.Zero) 
       { 
        throw new ArgumentException(); 
       } 

       // Determine how many files are involved in this operation. 
       uint nFiles = NativeMethods.DragQueryFile(hDrop, UInt32.MaxValue, null, 0); 

       // This code sample displays the custom context menu item when only 
       // one file is selected. 
       if (nFiles == 1) 
       { 
        // Get the path of the file. 
        StringBuilder fileName = new StringBuilder(260); 
        if (0 == NativeMethods.DragQueryFile(hDrop, 0, fileName, 
         fileName.Capacity)) 
        { 
         Marshal.ThrowExceptionForHR(WinError.E_FAIL); 
        } 
        this.selectedFile = fileName.ToString(); 
       } 
       else 
       { 
        Marshal.ThrowExceptionForHR(WinError.E_FAIL); 
       } 
      } 

      if (pidlFolder != IntPtr.Zero) { 
       StringBuilder folderName = new StringBuilder(260); 
       if (0 == NativeMethods.SHGetPathFromIDList(pidlFolder, folderName)) 
       { 
        Marshal.ThrowExceptionForHR(WinError.E_FAIL); 
       } 
       this.selectedFile = folderName.ToString(); 
      } 
     } 
     finally 
     { 
      NativeMethods.ReleaseStgMedium(ref stm); 
     } 
    } 

ShellExtLib.cs 파일에서 folowing 소스 추가

[DllImport("shell32.dll")] 
    public static extern Int32 SHGetPathFromIDList(
     IntPtr pidl,    // Address of an item identifier list that 
     // specifies a file or directory location 
     // relative to the root of the namespace (the 
     // desktop). 
     StringBuilder pszPath);  // Address of a buffer to receive the file system 

을 그리고 ShellExtLib.cs이

public static void RegisterShellExtContextMenuHandler(Guid clsid, 
     string fileType, string friendlyName) 
    { 
     if (clsid == Guid.Empty) 
     { 
      throw new ArgumentException("clsid must not be empty"); 
     } 
     if (string.IsNullOrEmpty(fileType)) 
     { 
      throw new ArgumentException("fileType must not be null or empty"); 
     } 

     // If fileType starts with '.', try to read the default value of the 
     // HKCR\<File Type> key which contains the ProgID to which the file type 
     // is linked. 
     if (fileType.StartsWith(".")) 
     { 
      using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType)) 
      { 
       if (key != null) 
       { 
        // If the key exists and its default value is not empty, use 
        // the ProgID as the file type. 
        string defaultVal = key.GetValue(null) as string; 
        if (!string.IsNullOrEmpty(defaultVal)) 
        { 
         fileType = defaultVal; 
        } 
       } 
      } 
     } 
     else { 

      // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}. 
      string keyName1 = string.Format(@"{0}\Background\shellex\ContextMenuHandlers\{1}", 
       fileType, clsid.ToString("B")); 
      using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName1)) 
      { 
       // Set the default value of the key. 
       if (key != null && !string.IsNullOrEmpty(friendlyName)) 
       { 
        key.SetValue(null, friendlyName); 
       } 
      } 
     } 

     // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}. 
     string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}", 
      fileType, clsid.ToString("B")); 
     using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName)) 
     { 
      // Set the default value of the key. 
      if (key != null && !string.IsNullOrEmpty(friendlyName)) 
      { 
       key.SetValue(null, friendlyName); 
      } 
     } 
    } 


    public static void UnregisterShellExtContextMenuHandler(Guid clsid, 
     string fileType) 
    { 
     if (clsid == null) 
     { 
      throw new ArgumentException("clsid must not be null"); 
     } 
     if (string.IsNullOrEmpty(fileType)) 
     { 
      throw new ArgumentException("fileType must not be null or empty"); 
     } 

     // If fileType starts with '.', try to read the default value of the 
     // HKCR\<File Type> key which contains the ProgID to which the file type 
     // is linked. 
     if (fileType.StartsWith(".")) 
     { 
      using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType)) 
      { 
       if (key != null) 
       { 
        // If the key exists and its default value is not empty, use 
        // the ProgID as the file type. 
        string defaultVal = key.GetValue(null) as string; 
        if (!string.IsNullOrEmpty(defaultVal)) 
        { 
         fileType = defaultVal; 
        } 
       } 
      } 
     } 
     else { 
      // Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}. 
      string keyName1 = string.Format(@"{0}\Background\shellex\ContextMenuHandlers\{1}", 
       fileType, clsid.ToString("B")); 
      Registry.ClassesRoot.DeleteSubKeyTree(keyName1, false); 
     } 

     // Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}. 
     string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}", 
      fileType, clsid.ToString("B")); 
     Registry.ClassesRoot.DeleteSubKeyTree(keyName, false); 
    }