风吹惊沙 發表於 2025-4-2 15:32:00

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

<h2 id="方法一调用未公开接口iopenwithlauncher">方法一:调用未公开接口&nbsp;IOpenWithLauncher</h2>
<details open="">
<summary>Adobe Acrobat 应该是调用的未公开接口方法</summary>
<pre><code class="language-csharp">


interface IOpenWithLauncher
{
   
    int Launch(IntPtr hWndParent,
          string lpszPath,
         IMMERSIVE_OPENWITH flags);
}


enum IMMERSIVE_OPENWITH
{
    NONE = 0,
    OVERRIDE = 0x1,
    DONOT_EXEC = 0x4,
    PROTOCOL = 0x8,
    URL = 0x10,
    USEPOSITION = 0x20,
    DONOT_SETDEFAULT = 0x40,
    ACTION = 0x80,
    ALLOW_EXECDEFAULT = 0x100,
    NONEDP_TO_EDP = 0x200,
    EDP_TO_NONEDP = 0x400,
    CALLING_IN_APP = 0x800,
};

public static void ShowSetAssocDialog(string extension)
{
    var CLSID_ExecuteUnknown = new Guid("{E44E9428-BDBC-4987-A099-40DC8FD255E7}");
    var obj = Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_ExecuteUnknown));
    if (obj is IOpenWithLauncher launcher)
    {
      launcher.Launch(IntPtr.Zero, extension, IMMERSIVE_OPENWITH.DONOT_EXEC);
      Marshal.ReleaseComObject(launcher);
    }
}
</code></pre>
</details>
<h2 id="方法二通过模拟点击属性对话框更改打开方式">方法二:通过模拟点击属性对话框“更改”打开方式</h2>
<blockquote>
<p>此方法来自两年前我的自问自答,代码引用了&nbsp;《C#&nbsp;窗口过程消息处理&nbsp;WndProc》 中的附加到其他窗口辅助类</p>
</blockquote>
<details open="">
<summary>Bandizip&nbsp;使用的这种方法</summary>
<pre><code class="language-csharp">
static extern bool SHObjectProperties(IntPtr hWnd, SHOP shopObjectType, string pszObjectName, string pszPropertyPage);

enum SHOP
{
    PRINTERNAME = 1,
    FILEPATH = 2,
    VOLUMEGUID = 4
}


static extern int GetCurrentProcessId();


static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);


static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);


static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);


static extern bool SetForegroundWindow(IntPtr hWnd);


static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

public static void ShowSetAssocDialog(string extension)
{
    string fileName = Path.ChangeExtension(Path.GetRandomFileName(), extension);
    string filePath = Path.Combine(Path.GetTempPath(), fileName);
    fileName = Path.GetFileNameWithoutExtension(fileName);
    File.WriteAllText(filePath, string.Empty); // 创建临时文件
    var frame = new DispatcherFrame();
    int pid = GetCurrentProcessId();
    SHObjectProperties(IntPtr.Zero, SHOP.FILEPATH, filePath, null); // 显示属性对话框
    while (true)
    {
      bool found = !EnumWindows((hWnd, lParam) =&gt; // 枚举窗口
      {
            GetWindowThreadProcessId(hWnd, out int id);
            if (id == pid) // 比较进程 id
            {
                const int MAX_PATH = 260;
                var sb = new StringBuilder(MAX_PATH);
                GetClassName(hWnd, sb, sb.Capacity);
                if (sb.ToString() == "#32770") // 对话框类名
                {
                  GetWindowText(hWnd, sb, sb.Capacity);
                  if (sb.ToString().Contains(fileName)) // 对话框标题是否包含文件名
                  {
                        SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP.HIDEWINDOW); // 隐藏属性对话框
                        MessageHooker.AddHook(hWnd, (ref Message m) =&gt;
                        {
                            const int PSM_CHANGED = 0x400 + 104;
                            if (m.Msg == PSM_CHANGED) // 监测属性表页更改
                            {
                              frame.Continue = false;
                              PostMessage(hWnd, WM.CLOSE, 0, 0); // 等效 EndDialog(hWnd, 0)
                            }
                            return false;
                        });
                        SetForegroundWindow(hWnd);
                        SendKeys.SendWait("%C"); // ALT + C 快捷键
                        return false;
                  }
                }
            }
            return true;
      }, IntPtr.Zero);
      if (found) break;
    }
    File.Delete(filePath); // 删除临时文件
    Dispatcher.PushFrame(frame);
}
</code></pre>
</details>
<h2 id="相关资料">相关资料</h2>
<p>Redirecting Open With in Properties Dialog in Windows 10</p>
<p>How to call the "Open With" dialog used to associate file formats in Windows 10 or 11?</p><br><br>
来源:https://www.cnblogs.com/BluePointLilac/p/18806046
頁: [1]
查看完整版本: C# 调用 Win10/11 文件关联对话框