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

Adobe Acrobat 应该是调用的未公开接口方法
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6A283FE2-ECFA-4599-91C4-E80957137B26")]
interface IOpenWithLauncher
{
[PreserveSig]
int Launch(IntPtr hWndParent,
[MarshalAs(UnmanagedType.LPWStr)] string lpszPath,
IMMERSIVE_OPENWITH flags);
} [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);
}
}

方法二:通过模拟点击属性对话框“更改”打开方式

此方法来自两年前我的自问自答,代码引用了 《C# 窗口过程消息处理 WndProc》 中的附加到其他窗口辅助类

Bandizip 使用的这种方法
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
static extern bool SHObjectProperties(IntPtr hWnd, SHOP shopObjectType, string pszObjectName, string pszPropertyPage); enum SHOP
{
PRINTERNAME = 1,
FILEPATH = 2,
VOLUMEGUID = 4
} [DllImport("kernel32.dll")]
static extern int GetCurrentProcessId(); [DllImport("user32.dll")]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); [DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")]
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) => // 枚举窗口
{
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) =>
{
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);
}

相关资料

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

https://learn.microsoft.com/en-us/windows/win32/controls/psm-changed

C# 调用 Win10/11 文件关联对话框的更多相关文章

  1. [VB.NET]调用系统的文件夹选择对话框

    以下示例代码展示如何调用系统的文件夹选择对话框: Private Function SelectFolder(ByVal Describe As String, Optional ByVal Show ...

  2. LaTeX-WinEdt 编辑器和 PDF 文件的 Acrobat 11 程序关联

    WinEdt 编辑器和 PDF 文件的 Acrobat 11 程序关联 CTeX 套装 2.8 版本以后,也就是09年9月以后的版本加入了SumatraPDF程序,将PDF文件与Acrobat程序取消 ...

  3. WPF中使用文件浏览对话框的几种方式

    原文:WPF中使用文件浏览对话框的几种方式 WPF本身并没有为我们提供文件浏览的控件, 也不能直接使用Forms中的控件,而文件浏览对话框又是我们最常用的控件之一. 下面是我实现的方式 方式1: 使用 ...

  4. 。net 添加或获取文件关联

    文件关联设置 2011-02-07 14:25:36|  分类: VB.net2008或2010 |  标签:文件关联  |举报|字号 订阅     原理:以后缀名为.txt为例 方式一: 1.在注册 ...

  5. CodeSmith使用总结--下拉列表和文件夹对话框属性

    上一篇有点短了,因为实在没有什么可说的,这一篇会多一点.O(∩_∩)O~ 一.下拉列表 关于如何在CodeSmith中创建一个下拉列表的属性框其实很简单,是要使用C#中的枚举就行了,看操作. 首先定义 ...

  6. delphi调用外部程序打开文件

    delphi调用外部程序打开文件 ShellExecute的各种用法 一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOper ...

  7. 文件对话框WPF(5)----文件浏览对话框

    废话就不多说了,开始... WPF中文件浏览对话框的实现可以利用Windows API Code Pack,它是一个用于访问Windows Vista/7 特性的托管代码函数库,但并没有包含在.NET ...

  8. loadrunner 脚本开发-调用java jar文件远程操作Oracle数据库测试

    调用java jar文件远程操作Oracle数据库测试 by:授客 QQ:1033553122 测试环境 数据库:linux 下Oracle_11g_R2 Loadrunner:11 备注:想学ora ...

  9. 迁移桌面程序到MS Store(4)——桌面程序调用Win10 API

    上一篇我们讨论了如何在转制的桌面程序中,通过StartupTask来实现转制版本的开机自启动.实际操作中,我们通过编辑Packaging工程中的Package.appxmanifest文件,来添加自启 ...

  10. VC++ 打开文件或文件夹对话框的实现方法

    实际工作开发中,由于各种应用,我们需要调用系统的打开文件对话框或者打开文件夹对话框,或两者兼有.特总结了常用的实现方法,仅供开发参考. 1. 打开文件对话框 常用的方法是使用系统的CFileDialo ...

随机推荐

  1. 《CUDA编程:基础与实践》读书笔记(5):统一内存编程

    统一内存(unified memory)是一种逻辑上的概念,它既不是显存.也不是主机内存,而是CPU和GPU都可以访问并能保证一致性的虚拟存储器.使用统一内存对硬件有较高的要求: 对于所有功能,GPU ...

  2. 在shell脚本中为日志添加颜色

    在 Shell 脚本中,可以通过添加 ANSI 转义序列来为日志输出添加颜色.以下是一个完整的 Shell 脚本示例,包含日志颜色定义.日志函数封装以及使用示例: 完整脚本:colored_logs. ...

  3. GeoServer加载Arcgis切片服务

    使用GeoServer中的GeoWebCache加载Arcgis切片服务 下载安装 GeoServer和GeoWebCache的下载安装都非常简单,这里选择"独立于平台的二进制版本" ...

  4. UWP 系统通知测试

    code: using System; using System.Collections.Generic; using System.IO; using System.Linq; using Syst ...

  5. cpa-审计

    1.审计概述 2.审计计划 3.审计证据 4.审计抽样方法 5.信息技术对审计的影响 6.审计工作底稿 7.风险评估 8.风险应对 9.销售与收款循环的审计 10.采购与付款循环的审计 11.生产与存 ...

  6. R语言学习数据挖掘

    1.用R计算数据基本统计量(均值) 学习机器学习和数据挖掘中的各种算法和模型,需要掌握统计学的基本概念.统计学是通过搜索.整理.分析数据等手段,以达到推断所测对象的本质,并预测对象未来走势的一门综合性 ...

  7. Robot Framework 自动化测试部署常见问题及处理方法(三)

    书接上文 8.关于IE浏览器 IE浏览器必须是原生版,即Windows系统原版,非手动升级后的版本 9.用例执行过程中,遇到元素定位不到的情况 原因: ⑴xpath动态变化 ⑵有frame/ifram ...

  8. 第一届启航杯网络安全大赛部分wp

    第一届启航杯 WEB Easy include <?php error_reporting(0); //flag in flag.php $file=$_GET['fil e']; if(iss ...

  9. SQL SERVER日常运维(二)

    以下语句请使用SA用户或者有DBA权限的用户进行执行,否则可能会出现权限不足报错. 查看当前用户查看当前用户 select system_user; 检查SQL Agent是否开启 IF EXISTS ...

  10. brew切换数据源为阿里源

    # 查看 brew.git 当前源 $ cd "$(brew --repo)" && git remote -v origin https://github.com ...