首页 > 解决方案 > 通过资源管理器启动 ms-screenclip 并获取句柄或等待退出

问题描述

如何启动 Windows 10 的最新屏幕截图工具(“ms-screenclip:”或快捷键 Windows + Shift + S)并获取句柄进行检查或等到它再次关闭。

.net 原生

Process.Start("ms-screenclip:)

确实启动了应用程序,但返回了一个空的进程对象。我猜是由于正在执行的应用程序已经在运行。

ShellExecute API 确实有效

ShellExecute(Nothing, "open", "explorer.exe","ms-screenclip:", Nothing, 1)

都不返回句柄

ShellExecuteEx 也运行,但我不知道如何返回句柄:

<Runtime.InteropServices.DllImport("shell32.dll", CharSet:=Runtime.InteropServices.CharSet.Auto)>
Shared Function ShellExecuteEx(ByRef lpExecInfo As SHELLEXECUTEINFO) As IntPtr
End Function


<StructLayout(LayoutKind.Sequential)>
Public Structure SHELLEXECUTEINFO
    Public cbSize As Integer
    Public fMask As UInteger
    Public hwnd As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)>
    Public lpVerb As String
    <MarshalAs(UnmanagedType.LPTStr)>
    Public lpFile As String
    <MarshalAs(UnmanagedType.LPTStr)>
    Public lpParameters As String
    <MarshalAs(UnmanagedType.LPTStr)>
    Public lpDirectory As String
    Public nShow As Integer
    Public hInstApp As IntPtr
    Public lpIDList As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)>
    Public lpClass As String
    Public hkeyClass As IntPtr
    Public dwHotKey As UInteger
    Public hIcon As IntPtr
    Public hProcess As IntPtr
End Structure

我错过了什么重要的东西吗?

谢谢你。

标签: .netvb.net

解决方案


我现在也面临着同样的挑战。不幸的是,我还没有找到一个真正干净的解决方案。

在我的用例中有效的是使用 Win32 API:

显然这不是一个干净的解决方案,不应在生产代码中使用。

  • 听 EVENT_SYSTEM_FOREGROUND (SetWinEventHook)
  • 存储窗口句柄(您也可以检查活动窗口的标题)
  • 监听 EVENT_OBJECT_DESTROY 并检查它是否与存储的句柄匹配 --> 窗口关闭
  • 然后我正在检查剪贴板中是否有新图像。

我还使用计时器进行超时检查。

如果我设法解决了这个问题,我会告诉你的。


编辑:适用于我的用例的最终解决方案:

var appDataFolder = Environment.GetEnvironmentVariable("LocalAppData");
var packagesFolderPath = appDataFolder + @"\Packages\";
var taskDirectory = new DirectoryInfo(packagesFolderPath);
var packageDirs = taskDirectory.GetDirectories();
var shellExperienceDirs = packageDirs
    .Where(dir => dir.Name.StartsWith("Microsoft.Windows.ShellExperienceHost_"));
foreach (var dir in shellExperienceDirs)
{
    string screenclipFolderPath = dir.FullName + @"\TempState\ScreenClip";
    if (Directory.Exists(screenclipFolderPath))
    {
        var watcher = new FileSystemWatcher
        {
            Path = screenclipFolderPath,
            Filter = "*.png",
            EnableRaisingEvents = true
        };
        watcher.Created += OnChanged; // <--- triggers my logic
        fileSystemWatchers.Add(watcher);
    }  
}

该应用程序创建两个图像(其中一个是弹出窗口的“缩略图”)。我正在等待两张新图像并处理较大的一张。


推荐阅读