C# 调用 Win10/11 文件关联对话框
方法一:调用未公开接口 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 文件关联对话框的更多相关文章
- [VB.NET]调用系统的文件夹选择对话框
以下示例代码展示如何调用系统的文件夹选择对话框: Private Function SelectFolder(ByVal Describe As String, Optional ByVal Show ...
- LaTeX-WinEdt 编辑器和 PDF 文件的 Acrobat 11 程序关联
WinEdt 编辑器和 PDF 文件的 Acrobat 11 程序关联 CTeX 套装 2.8 版本以后,也就是09年9月以后的版本加入了SumatraPDF程序,将PDF文件与Acrobat程序取消 ...
- WPF中使用文件浏览对话框的几种方式
原文:WPF中使用文件浏览对话框的几种方式 WPF本身并没有为我们提供文件浏览的控件, 也不能直接使用Forms中的控件,而文件浏览对话框又是我们最常用的控件之一. 下面是我实现的方式 方式1: 使用 ...
- 。net 添加或获取文件关联
文件关联设置 2011-02-07 14:25:36| 分类: VB.net2008或2010 | 标签:文件关联 |举报|字号 订阅 原理:以后缀名为.txt为例 方式一: 1.在注册 ...
- CodeSmith使用总结--下拉列表和文件夹对话框属性
上一篇有点短了,因为实在没有什么可说的,这一篇会多一点.O(∩_∩)O~ 一.下拉列表 关于如何在CodeSmith中创建一个下拉列表的属性框其实很简单,是要使用C#中的枚举就行了,看操作. 首先定义 ...
- delphi调用外部程序打开文件
delphi调用外部程序打开文件 ShellExecute的各种用法 一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOper ...
- 文件对话框WPF(5)----文件浏览对话框
废话就不多说了,开始... WPF中文件浏览对话框的实现可以利用Windows API Code Pack,它是一个用于访问Windows Vista/7 特性的托管代码函数库,但并没有包含在.NET ...
- loadrunner 脚本开发-调用java jar文件远程操作Oracle数据库测试
调用java jar文件远程操作Oracle数据库测试 by:授客 QQ:1033553122 测试环境 数据库:linux 下Oracle_11g_R2 Loadrunner:11 备注:想学ora ...
- 迁移桌面程序到MS Store(4)——桌面程序调用Win10 API
上一篇我们讨论了如何在转制的桌面程序中,通过StartupTask来实现转制版本的开机自启动.实际操作中,我们通过编辑Packaging工程中的Package.appxmanifest文件,来添加自启 ...
- VC++ 打开文件或文件夹对话框的实现方法
实际工作开发中,由于各种应用,我们需要调用系统的打开文件对话框或者打开文件夹对话框,或两者兼有.特总结了常用的实现方法,仅供开发参考. 1. 打开文件对话框 常用的方法是使用系统的CFileDialo ...
随机推荐
- 《CUDA编程:基础与实践》读书笔记(5):统一内存编程
统一内存(unified memory)是一种逻辑上的概念,它既不是显存.也不是主机内存,而是CPU和GPU都可以访问并能保证一致性的虚拟存储器.使用统一内存对硬件有较高的要求: 对于所有功能,GPU ...
- 在shell脚本中为日志添加颜色
在 Shell 脚本中,可以通过添加 ANSI 转义序列来为日志输出添加颜色.以下是一个完整的 Shell 脚本示例,包含日志颜色定义.日志函数封装以及使用示例: 完整脚本:colored_logs. ...
- GeoServer加载Arcgis切片服务
使用GeoServer中的GeoWebCache加载Arcgis切片服务 下载安装 GeoServer和GeoWebCache的下载安装都非常简单,这里选择"独立于平台的二进制版本" ...
- UWP 系统通知测试
code: using System; using System.Collections.Generic; using System.IO; using System.Linq; using Syst ...
- cpa-审计
1.审计概述 2.审计计划 3.审计证据 4.审计抽样方法 5.信息技术对审计的影响 6.审计工作底稿 7.风险评估 8.风险应对 9.销售与收款循环的审计 10.采购与付款循环的审计 11.生产与存 ...
- R语言学习数据挖掘
1.用R计算数据基本统计量(均值) 学习机器学习和数据挖掘中的各种算法和模型,需要掌握统计学的基本概念.统计学是通过搜索.整理.分析数据等手段,以达到推断所测对象的本质,并预测对象未来走势的一门综合性 ...
- Robot Framework 自动化测试部署常见问题及处理方法(三)
书接上文 8.关于IE浏览器 IE浏览器必须是原生版,即Windows系统原版,非手动升级后的版本 9.用例执行过程中,遇到元素定位不到的情况 原因: ⑴xpath动态变化 ⑵有frame/ifram ...
- 第一届启航杯网络安全大赛部分wp
第一届启航杯 WEB Easy include <?php error_reporting(0); //flag in flag.php $file=$_GET['fil e']; if(iss ...
- SQL SERVER日常运维(二)
以下语句请使用SA用户或者有DBA权限的用户进行执行,否则可能会出现权限不足报错. 查看当前用户查看当前用户 select system_user; 检查SQL Agent是否开启 IF EXISTS ...
- brew切换数据源为阿里源
# 查看 brew.git 当前源 $ cd "$(brew --repo)" && git remote -v origin https://github.com ...