C# 调用 Win10/11 文件关联对话框

打印 上一主题 下一主题

主题 1885|帖子 1885|积分 5655

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
方法一:调用未公开接口 IOpenWithLauncher

Adobe Acrobat 应该是调用的未公开接口方法
  1. [ComImport]
  2. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  3. [Guid("6A283FE2-ECFA-4599-91C4-E80957137B26")]
  4. interface IOpenWithLauncher
  5. {
  6.     [PreserveSig]
  7.     int Launch(IntPtr hWndParent,
  8.          [MarshalAs(UnmanagedType.LPWStr)] string lpszPath,
  9.          IMMERSIVE_OPENWITH flags);
  10. }
  11. [Flags]
  12. enum IMMERSIVE_OPENWITH
  13. {
  14.     NONE = 0,
  15.     OVERRIDE = 0x1,
  16.     DONOT_EXEC = 0x4,
  17.     PROTOCOL = 0x8,
  18.     URL = 0x10,
  19.     USEPOSITION = 0x20,
  20.     DONOT_SETDEFAULT = 0x40,
  21.     ACTION = 0x80,
  22.     ALLOW_EXECDEFAULT = 0x100,
  23.     NONEDP_TO_EDP = 0x200,
  24.     EDP_TO_NONEDP = 0x400,
  25.     CALLING_IN_APP = 0x800,
  26. };
  27. public static void ShowSetAssocDialog(string extension)
  28. {
  29.     var CLSID_ExecuteUnknown = new Guid("{E44E9428-BDBC-4987-A099-40DC8FD255E7}");
  30.     var obj = Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_ExecuteUnknown));
  31.     if (obj is IOpenWithLauncher launcher)
  32.     {
  33.         launcher.Launch(IntPtr.Zero, extension, IMMERSIVE_OPENWITH.DONOT_EXEC);
  34.         Marshal.ReleaseComObject(launcher);
  35.     }
  36. }
复制代码
方法二:通过模拟点击属性对话框“更改”打开方式

此方法来自两年前我的自问自答,代码引用了 《C# 窗口过程消息处置惩罚 WndProc》 中的附加到其他窗口辅助类
Bandizip 使用的这种方法
  1. [DllImport("shell32.dll", CharSet = CharSet.Auto)]
  2. static extern bool SHObjectProperties(IntPtr hWnd, SHOP shopObjectType, string pszObjectName, string pszPropertyPage);
  3. enum SHOP
  4. {
  5.     PRINTERNAME = 1,
  6.     FILEPATH = 2,
  7.     VOLUMEGUID = 4
  8. }
  9. [DllImport("kernel32.dll")]
  10. static extern int GetCurrentProcessId();
  11. [DllImport("user32.dll")]
  12. static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
  13. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  14. static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
  15. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  16. static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  17. [DllImport("user32.dll")]
  18. static extern bool SetForegroundWindow(IntPtr hWnd);
  19. [DllImport("user32.dll")]
  20. static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
  21. delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
  22. public static void ShowSetAssocDialog(string extension)
  23. {
  24.     string fileName = Path.ChangeExtension(Path.GetRandomFileName(), extension);
  25.     string filePath = Path.Combine(Path.GetTempPath(), fileName);
  26.     fileName = Path.GetFileNameWithoutExtension(fileName);
  27.     File.WriteAllText(filePath, string.Empty); // 创建临时文件
  28.     var frame = new DispatcherFrame();
  29.     int pid = GetCurrentProcessId();
  30.     SHObjectProperties(IntPtr.Zero, SHOP.FILEPATH, filePath, null); // 显示属性对话框
  31.     while (true)
  32.     {
  33.         bool found = !EnumWindows((hWnd, lParam) => // 枚举窗口
  34.         {
  35.             GetWindowThreadProcessId(hWnd, out int id);
  36.             if (id == pid) // 比较进程 id
  37.             {
  38.                 const int MAX_PATH = 260;
  39.                 var sb = new StringBuilder(MAX_PATH);
  40.                 GetClassName(hWnd, sb, sb.Capacity);
  41.                 if (sb.ToString() == "#32770") // 对话框类名
  42.                 {
  43.                     GetWindowText(hWnd, sb, sb.Capacity);
  44.                     if (sb.ToString().Contains(fileName)) // 对话框标题是否包含文件名
  45.                     {
  46.                         SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP.HIDEWINDOW);// 隐藏属性对话框
  47.                         MessageHooker.AddHook(hWnd, (ref Message m) =>
  48.                         {
  49.                             const int PSM_CHANGED = 0x400 + 104;
  50.                             if (m.Msg == PSM_CHANGED)// 监测属性表页更改
  51.                             {
  52.                                 frame.Continue = false;
  53.                                 PostMessage(hWnd, WM.CLOSE, 0, 0); // 等效 EndDialog(hWnd, 0)
  54.                             }
  55.                             return false;
  56.                         });
  57.                         SetForegroundWindow(hWnd);
  58.                         SendKeys.SendWait("%C");// ALT + C 快捷键
  59.                         return false;
  60.                     }
  61.                 }
  62.             }
  63.             return true;
  64.         }, IntPtr.Zero);
  65.         if (found) break;
  66.     }
  67.     File.Delete(filePath); // 删除临时文件
  68.     Dispatcher.PushFrame(frame);
  69. }
复制代码
干系资料

Redirecting Open With in Properties Dialog in Windows 10
How to call the "Open With" dialog used to associate file formats in Windows 10 or 11?

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

愛在花開的季節

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表