如何使用 PowerShell 捕获全局击键?

2024-05-26

Powershell 可以监听并捕获按键吗?

是否可以编写一个 PowerShell 脚本,例如自动热键 https://www.autohotkey.com/,位于托盘中并等待您按下预定义的键盘键才开始执行?并且每次按下所述键时可能不会返回而是触发?

我想要实现的是 - 仅在启动脚本后按下按钮才执行预定义的脚本操作,因此将其放在桌面上并定义快捷键是行不通的。

例如:
我希望每次按“x”键时输入 3 次文本“TEST”,但我希望仅当执行此操作的脚本正在运行时才会发生这种情况。因此,当脚本未运行时 - 按“x”不会执行任何操作。

基本上,AutoHotkey 可以完全做到这一点,但如果可能的话,我想在 PowerShell 中执行此操作,而无需编写大量 C# 代码,因为那样我只需为此编写一个小型 C# 托盘应用程序。


也许不能直接在 PowerShell 中运行,但由于您几乎可以运行任何 C# 代码,因此这里是一个基于Peter Hinchley 的出色解决方案 https://hinchley.net/articles/creating-a-key-logger-via-a-global-system-hook-using-powershell/:

Add-Type -TypeDefinition '
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace KeyLogger {
  public static class Program {
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;

    private static HookProc hookProc = HookCallback;
    private static IntPtr hookId = IntPtr.Zero;
    private static int keyCode = 0;

    [DllImport("user32.dll")]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll")]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll")]
    private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    public static int WaitForKey() {
      hookId = SetHook(hookProc);
      Application.Run();
      UnhookWindowsHookEx(hookId);
      return keyCode;
    }

    private static IntPtr SetHook(HookProc hookProc) {
      IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
      return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0);
    }

    private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
      if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
        keyCode = Marshal.ReadInt32(lParam);
        Application.Exit();
      }
      return CallNextHookEx(hookId, nCode, wParam, lParam);
    }
  }
}
' -ReferencedAssemblies System.Windows.Forms

while ($true) {
    $key = [System.Windows.Forms.Keys][KeyLogger.Program]::WaitForKey()
    if ($key -eq "X") {
        Write-Host "Do something now."
    }
}

版本2

(使用回调):

Add-Type -TypeDefinition '
  using System;
  using System.IO;
  using System.Diagnostics;
  using System.Runtime.InteropServices;
  using System.Windows.Forms;

  namespace PowerShell {
    public static class KeyLogger {
      private const int WH_KEYBOARD_LL = 13;
      private const int WM_KEYDOWN = 0x0100;

      private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

      private static Action<Keys> keyCallback;
      private static IntPtr hookId = IntPtr.Zero;

      [DllImport("user32.dll")]
      private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

      [DllImport("user32.dll")]
      private static extern bool UnhookWindowsHookEx(IntPtr hhk);

      [DllImport("user32.dll")]
      private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

      [DllImport("kernel32.dll")]
      private static extern IntPtr GetModuleHandle(string lpModuleName);

      public static void Run(Action<Keys> callback) {
        keyCallback = callback;
        hookId = SetHook();
        Application.Run();
        UnhookWindowsHookEx(hookId);
      }

      private static IntPtr SetHook() {
        IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
        return SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, moduleHandle, 0);
      }

      private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
          var key = (Keys)Marshal.ReadInt32(lParam);
          keyCallback(key);
        }
        return CallNextHookEx(hookId, nCode, wParam, lParam);
      }
    }
  }
' -ReferencedAssemblies System.Windows.Forms

[PowerShell.KeyLogger]::Run({
  param($key)
  if ($key -eq "X") {
    Write-Host "Do something now."
  }
})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 PowerShell 捕获全局击键? 的相关文章

  • 获取在特定日期之后修改的一组文件

    有没有人有一个方便的 powershell 脚本根据修改日期从 TFS 获取一组文件 我想说 给我这个文件夹 或子文件夹 中在 X Y ZZZZ 之后修改的所有文件 并将这些文件转储到它们通常所在的文件夹之外的文件夹中 我知道足够的 pow
  • 如何在 Windows Docker 容器中启动 PowerShell (x86)?

    我正在尝试从 PowerShell 启动 Windows Docker 容器中的 PowerShell x86 但它不会启动新的 shell 我正在从 AWS Windows EC2 运行 DockerWindows Server 2019
  • PowerShell:检索AppPool中的应用程序数量

    如何通过 PowerShell 命令检索与特定 IIS AppPool 关联的应用程序数量 我们可以使用以下命令手动查看关联的应用程序 Get Item IIS AppPools AppPoolName 但是 如果我们想要手动选择Appli
  • 如何在不安装 AWS SDK 的情况下通过 Powershell 从 S3 下载文件?

    我想使用 Windows Powershell 从我的 AWS S3 存储桶下载文件 我无法安装任何 AWS 软件 需要创建一个 API 才能访问 AWS S3 中的文件 我使用Postman测试该文件是否可访问并且成功 鉴于这一成功 我尝
  • 如何使用PowerShell批量调用Update-Database

    我们使用 Azure 弹性池生成多个客户端数据库和一个引用客户端数据库的主数据库 我们已经拥有多个数据库 并且正在开发新版本的代码 我们使用 EF6 代码优先 当我们更改模型 添加属性 时 我们创建迁移文件并需要调用Update Datab
  • Powershell从Linux客户端连接到Windows远程

    我正在尝试从我的 Linux 工作站远程连接到 Windows 计算机 我在 Arch Linux 工作站上安装了 powershell 目前正在尝试连接到主机 在主机上 Enable PSRemoting 然后允许所有主机Set Item
  • 查询计算机列表 - 输出上次登录用户和上次登录日期

    我正在创建一个脚本来从 txt 文件中检索所有计算机名称 然后对它们进行查询 计算机名 用户名 最后登录计算机的用户名 上次登录 使用的日期 这就是我所拥有的 Clear Host machines Get Content Path C U
  • 使用 powershell 执行 .sql 脚本并将输出存储在 .sql 文件中

    我正在尝试从 powershell 运行 sql 脚本 sql 文件并将结果保存到 sql 文件中 概述 SQL 数据库恢复需要用户和权限备份预恢复 一旦恢复完成 我们需要在数据库上执行输出 我们预恢复的用户权限备份 这是我的脚本 当我执行
  • 如何在 Visual Studio 中调试 Windows PowerShell 模块?

    我正在尝试使用 Visual Studio 2015 将 PowerShell 模块编写为 VB NET 项目 我已经能够将一些命令放在一起 将类库编译到 DLL 中 将模块导入到 PowerShell 会话中并调用我创建的命令 到目前为止
  • 如何在 PowerShell 中获取当前活动/前台窗口

    我知道这可以通过使用 alt tab 轻松完成 但创建此脚本的主要目的是自学一些 PowerShell 基础知识 我正在编写一个脚本 运行时会在 powershell 和当前前台窗口之间切换前台窗口 我读这个问题 https stackov
  • 根据字符串列表查找第一个可用的序列号?

    给定一个字符串列表 例如 apple01 apple02 and apple04 banana02 cherry01 你会如何想出first可用序列号each类型 也就是说 apple03如果我问apple or banana01如果我问b
  • 如何使用 PowerShell 将多个文本文件的列合并到一个 csv 文件中?

    我有多个测量文件 每个文件包含一列数字数据 Update 该脚本应该适用于可变数量的测量文件 数据1 dat 1 0 2 0 3 0 数据2 dat 10 0 20 0 30 0 数据N dat 1 1 1 如何使用以下命令将这些数据文件合
  • 命令提示符 con 的 Powershell 通讯员?

    例如 我想在屏幕上显示输出并将其复制到剪贴板 dir tee con clip 上面的方法不起作用 因为con在 PowerShell 的文件系统中不被识别为控制台 还可能存在以下场景 Get LongLongOutput tee con
  • 如何在 PowerShell 中键入 TAB 字符?

    Task 默认情况下 在 Windows 命令提示符中按 TAB 键将输出文件名 而在 PowerShell 中则不会执行任何操作 我希望能够在交互模式下键入 TAB 字符 而不是通过脚本 Research 我在这个网站上和通过谷歌搜索发现
  • 用于验证 IIS 设置的 Powershell 脚本

    是否可以使用 Power Shell 脚本获取 IIS 设置 我希望使用脚本获取 检查以下信息 检查 Windows 身份验证提供程序是否正确列出 协商 NTLM 检查是否启用了 Windows 身份验证 Windows 身份验证高级设置
  • 通过PowerShell检索Azure AD应用程序的“API权限”

    出于报告和监视的目的 我想检索应用程序 应用程序注册 的 Azure 门户中显示的信息以获取 API 权限 我尝试过以下代码 app Get AzureADApplication ObjectId aa7e174d 2639 4ac7 9b
  • 在 Windows 上不使用 OpenSSL 从 pfx 文件或证书存储中提取私钥

    正如标题所示 我想在不使用 OpenSSL 或任何其他第三方工具的情况下导出我的私钥 如果我需要一个 cer文件或 pfx我可以通过 MMC 或 PowerShell 轻松导出这些文件pkiclient但我找不到获取私钥的方法 https
  • 检测 PowerShell 开关

    我正在用 C 开发 PowerShell cmdlet 并且有 true false switch 语句 我注意到 如果我希望 bool 为 true 我需要指定 SwitchName true 否则我会得到 Missing an argu
  • 有没有更快的方法来使用Powershell解析Excel文档?

    我正在与一个接口MS Excel文件通过Powershell 每个 Excel 文档可能有大约 1000 行数据 目前这个脚本似乎读取了Excel文件并以每 0 6 秒 1 条记录的速率将值写入屏幕 乍一看 这似乎非常慢 这是我第一次阅读E
  • 使用 powershell 获取短路径

    我正在尝试在 powershell 中使用以下代码来获取短路径 对于某些文件夹它有效 对于某些人来说它不起作用 a New Object ComObject Scripting FileSystemObject f a GetFile C

随机推荐