时间:2025-04-02 15:32
人气:
作者:admin
[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》 中的附加到其他窗口辅助类
[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);
}
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?
Microsoft Agent Framework Skills 执行 Scripts(实
EF Core 原生 SQL 实战:FromSql、SqlQuery 与对