当 Visual Studio 具有焦点时(或任何以管理员身份运行的应用程序),keybd_event 和 PostMessage win32 不起作用

2024-04-06

这是我使用过的一个程序,与旧的 XP 时代相比进行了许多更改 这是一个命令行程序,可以更改媒体应用程序(Spotify、vlc、mediaPlayer)中的曲目,就像带有下一个/上一个曲目按钮的键盘一样。

目前我使用的是微软自然键盘,它没有这些按钮,但有执行此程序的可编程键。

这一切都有效,除非 Visual Studio 2012/2013 具有焦点(Windows 7)(尚未尝试其他版本),并且它在 Sql Management Studio 中有效。

using System;
using System.Runtime.InteropServices;

namespace NxtTrack
{    
class Program
{
    [DllImport("user32.dll")]
    private static extern bool PostMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll")]
    public static extern void keybd_event(byte vkCode, byte scanCode, int flags, IntPtr extraInfo);

    enum TrackMove
    {
        Previous,Next
    }

    static void Main(string[] args)
    {

        TrackMove trackMove;

        try
        {
            if(args[0].ToLower().Contains("previous"))
                trackMove = TrackMove.Previous;
            else if(args[0].ToLower().Contains("next"))
                trackMove = TrackMove.Next;
            else
            {
                throw new Exception("wrong param");
            }
        }
        catch
        {
            Console.WriteLine("Params needed: Next or Previous");
            return;
        }
        TrackKeys(trackMove);
    }

    private static void TrackKeys(TrackMove trackMove)
    {
        //http://msdn.microsoft.com/en-us/library/dd375731%28v=VS.85%29.aspx

        byte msg = trackMove == TrackMove.Previous ? (byte)0xB1 : (byte)0xB0;
        keybd_event(msg, 0x45, 0, IntPtr.Zero);
    }
}
}

这些是 VK_MEDIA_NEXT_TRACK 和 VK_MEDIA_PREV_TRACK 虚拟键。它们的处理非常复杂:

  • 无论哪个程序拥有前台窗口,当它调用 GetMessage() 时,都会从其消息队列中检索他的击键
  • 该程序消息循环中的 TranslateMessage() 调用将击键转换为WM_APPCOMMAND 消息 http://msdn.microsoft.com/en-us/library/windows/desktop/ms646275%28v=vs.85%29.aspx、 APPCOMMAND_MEDIA_NEXTTRACK 或 APPCOMMAND_MEDIA_PREVIOUSTRACK 并将其发送到具有焦点的子窗口
  • 子窗口不会使用它并将消息传递给 DefWindowProc()
  • 它将消息传递给子窗口的父窗口。子窗口嵌套时,此过程会重复多次,最终到达顶层窗口
  • 当它调用 DefWindowProc 时,Windows 会调用 shell 挂钩来触发任何为 WH_SHELL 挂钩、HSHELL_APPCOMMAND 通知调用 SetWindowsHookEx() 的程序中的回调。像 Windows Media Player 这样的程序将使用它
  • 如果没有钩子拦截它,它最终将作为最后一个钩子出现在资源管理器中,然后最终执行操作。

这里的解决方案是不发送击键,而是向上移动先前列出的处理链。如果可以直接调用 shell 挂钩但不公开该功能,那就太好了。下一步是发送 WM_APPCOMMAND 消息。

这需要选择一个窗口来发送消息。如今,由于 UAC,这是一个困难的问题,一项名为 UIPI(用户界面权限隔离)的功能可防止未提升的程序向提升的程序发送消息。因此,您不能只使用前台的窗口,它很可能是一个以管理员权限运行的应用程序。与 Visual Studio 一样,当您尝试使用 PostMessage 和 keybd_event() 时,它们可能失败的原因。

诀窍是将其发送到一个窗口you自己的。您使用的是控制台模式项目,这让您变得困难。这是可以解决的。项目 + 添加引用,选择 System.Windows.Forms。将新类添加到您的项目中并粘贴下面所示的代码。将您的 keybd_event() 调用替换为,例如

  AppCommand.Send(AppCommands.MediaNext);  

我把你可以发送的所有命令都放进去了。我提供了一个 Cleanup() 方法来释放资源,没有必要调用它。该代码与 .NET 版本 2.0 至 4.5.1 兼容

using System;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public enum AppCommands {
    BrowserBack = 1,
    BrowserForward = 2,
    BrowserRefresh = 3,
    BrowserStop = 4,
    BrowserSearch = 5,
    BrowserFavorite = 6,
    BrowserHome = 7,
    VolumeMute = 8,
    VolumeDown = 9,
    VolumeUp = 10,
    MediaNext = 11,
    MediaPrevious = 12,
    MediaStop = 13,
    MediaPlayPause = 14,
    LaunchMail = 15,
    LaunchMediaSelect = 16,
    LaunchApp1 = 17,
    LaunchApp2 = 18,
    BassDown = 19,
    BassBoost = 20,
    BassUp = 21,
    TrebleUp = 22,
    TrebleDown = 23,
    MicrophoneMute = 24,
    MicrophoneVolumeUp = 25,
    MicrophoneVolumeDown = 26,
    Help = 27,
    Find = 28,
    New = 29,
    Open = 30,
    Close = 31,
    Save = 32,
    Print = 33,
    Undo = 34,
    Redo = 35,
    Copy = 36,
    Cut = 37,
    Paste = 38,
    ReplyToMail = 39,
    ForwardMail = 40,
    SendMail = 41,
    SpellCheck = 42,
    Dictate = 43,
    MicrophoneOnOff = 44,
    CorrectionList = 45,
    MediaPlay = 46,
    MediaPause = 47,
    MediaRecord = 48,
    MediaFastForward = 49,
    MediaRewind = 50,
    MediaChannelUp = 51,
    MediaChannelDown = 52,
    Delete = 53,
    Flip3D = 54
}

public static class AppCommand {
    public static void Send(AppCommands cmd) {
        if (frm == null) Initialize();
        frm.Invoke(new MethodInvoker(() => SendMessage(frm.Handle, WM_APPCOMMAND, frm.Handle, (IntPtr)((int)cmd << 16))));
    }

    private static void Initialize() {
        // Run the message loop on another thread so we're compatible with a console mode app
        var t = new Thread(() => {
            frm = new Form();
            var dummy = frm.Handle; 
            frm.BeginInvoke(new MethodInvoker(() => mre.Set()));
            Application.Run();
        });
        t.SetApartmentState(ApartmentState.STA);
        t.IsBackground = true;
        t.Start();
        mre.WaitOne();
    }
    public static void Cleanup() { 
        if (frm != null) {
            frm.BeginInvoke(new MethodInvoker(() => { 
                frm.Close();
                Application.ExitThread();
                mre.Set(); 
            }));
            mre.WaitOne();
            frm = null;
        }
    }

    private static ManualResetEvent mre = new ManualResetEvent(false);
    private static Form frm;

    // Pinvoke
    private const int WM_APPCOMMAND = 0x319;
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当 Visual Studio 具有焦点时(或任何以管理员身份运行的应用程序),keybd_event 和 PostMessage win32 不起作用 的相关文章

  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐

  • 对数组元素(带有数字的字符串)进行排序,自然排序

    我有一个像这样的数组 IL0 Foo PI0 Bar IL10 Baz IL3 Bob says hello 并且需要对其进行排序 使其看起来像 IL0 Foo IL3 Bob says hello IL10 Baz PI0 Bar 我尝试
  • PHP 循环动态变量

    我正在尝试创建一个动态变量 我有一个循环 我希望它循环记录并为每个记录创建一个变量 我的代码 ct 1 foreach record as rec var ct rec Name ct ct 1 echo var1 当我尝试使用上面的代码时
  • 将 ToolBar 添加到 UITableView 的正确方法是什么?

    我正在编写一个基于导航的 iPhone 应用程序 我希望将 UIToolBar 停靠在屏幕底部 并在工具栏和导航栏之间滚动 UITableView 我见过几个论坛 其中有人建议处理此视图的视图控制器应该是标准 UIViewControlle
  • 车道检测器分隔线 C ++ 与 OpenCV

    现在我一直在用OpenCV进行图像分析 我想做的是识别车道分割线 我所做的如下 1 I receive a image 2 Then transform it to grayscale 3 I apply the GaussianBlur
  • 将 CodeMirror 与 Angular2 集成(打字稿)

    我目前正在致力于将 CodeMirror 编辑器添加到项目中 更准确地说是 Angular2 项目 但我做起来有困难 我的编辑器的实例化似乎无法正常工作 我的代码如下 编辑器 组件 ts import Component from angu
  • C++ 交换值的最有效方法

    我想知道在 C 中交换整数的最有效的操作方式是什么 为什么 是这样的 int a b a a b b a b a a b 比使用临时的更有效 还有其他更有效的方法吗 不只是要求其他方法来交换整数 以及为什么它们会更有效 赋值总是比进行算术运
  • 调整 UILabel 大小以适应自动换行

    这是 iPhone 应用程序的一部分 但通常应该适用于用 objC 编写的 Cocoa 我有一个 UILabel 保存各种数量的文本 从单个字符到几个句子 文本应始终以适合 UILabel 中所有文本的尽可能大的字体显示 最大行数设置为 4
  • List 复杂排序

    我有一个List
  • 使用 gradle 创建一个包含 web 应用程序中的类的 JAR

    IE 有没有等价的archiveClasses maven war plugin 的 true 设置 https maven apache org plugins maven war plugin faq html attached对于 W
  • 如何为谷歌云存储服务帐户进行密钥轮换?

    我已经编写了用于访问 GCS 存储桶的代码 以通过 java 中的 API 存储文件 该 API 需要 JSON 凭证文件 我已经从 google 控制台创建了该 JSON 文件 我需要每 90 天自动执行一次 JSON 文件或密钥轮换 如
  • ModalBottomSheetLayout 在返回导航上闪烁 (Jetpack Compose)

    我在用着ModalBottomSheetLayout import androidx compose material ModalBottomSheetLayout 并在模式表布局中有一些项目 当我按下一个项目时 它会导航到下一个屏幕 但是
  • 使用循环使用 Dataframe Pandas 创建 Excel 工作表

    我正在开发这个函数 它可以抓取网站上的 Fantasy Football 信息并将其写入 Excel 文件 最终 我希望在 Excel 工作簿的单独工作表中包含每周的信息 下面发布的代码可以完美运行 直到我想将其写入 Excel 工作簿 该
  • 使用 Nginx 为 Angular2 CLI 构建的应用程序提供服务会抛出 404、403

    我使用 Angular CLI 创建一个测试应用程序并使用 Nginx 为其提供服务 得到 404 或 403 我猜这是我的 Nginx 配置的问题 但为了额外确定 我已经提供了达到这一点所执行的所有步骤 这些是我遵循的步骤 安装的角度 c
  • 如何使用scala从apache Spark中的kafka主题读取json数据

    我是新的 Spark 您能否让我知道如何使用 scala 从 apache Spark 中的 kafka 主题读取 json 数据 Thanks 最简单的方法是使用 Spark 附带的 DataFrame 抽象 val sqlContext
  • 确保从父 CRTP 类派生的类实现功能

    Brief 我想确保派生类实现父 CRTP 类中的函数所需的成员函数 Detail 我有一些这样的代码 class Base public class Params public virtual Params virtual void my
  • 应用内计费安全

    我已经完成了在应用程序计费 v3 中使用的应用程序的开发 我的应用程序是一个考试帮助应用程序 其中包含插入数据库的问题列表 让我担心的是安全性 因为除了 proguard 之外几乎没有其他东西了 我的应用程序查询已购买商品的库存 因此存储购
  • 无法检测数据库类型

    我正在尝试使用创建一个 Spring Boot 应用程序sqljdbc4 https mvnrepository com artifact com microsoft sqlserver sqljdbc4具有此配置的驱动程序 spring
  • laravel Eloquent 模型更新事件未触发

    圣诞快乐伙计们 我是 Laravel 的新手 当我尝试使用服务提供者和模型事件来记录更新信息时 有一个初学者的问题 正在关注在线文档 https laravel com docs 5 3 eloquent events https lara
  • 如何使用 GWT Designer 配置 Ext GWT?

    我在使用 GWT Designer 配置 GXT 时遇到问题 我拥有 Eclipse GWT 插件和 GXT 的所有新版本 但无法配置 GXT 以与 GWT Designer 一起使用 我设置了我的项目 以便可以编译我的 GXT 项目并在浏
  • 当 Visual Studio 具有焦点时(或任何以管理员身份运行的应用程序),keybd_event 和 PostMessage win32 不起作用

    这是我使用过的一个程序 与旧的 XP 时代相比进行了许多更改 这是一个命令行程序 可以更改媒体应用程序 Spotify vlc mediaPlayer 中的曲目 就像带有下一个 上一个曲目按钮的键盘一样 目前我使用的是微软自然键盘 它没有这