You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Standard 2.0类库中使用System.Windows.Forms.SendKeys

.NET Standard 2.0 类库实现按键控制的正确方案

方案1:使用P/Invoke调用Windows原生API实现(推荐,无额外依赖)

.NET Standard 2.0原生支持平台调用,你可以直接调用user32.dll的SendInput接口实现按键模拟,不需要依赖System.Windows.Forms程序集,完全兼容.NET Framework 4.8和.NET 5客户端。
核心实现代码参考:

using System;
using System.Runtime.InteropServices;

public static class KeySender
{
    [StructLayout(LayoutKind.Sequential)]
    private struct INPUT
    {
        public uint type;
        public InputUnion U;
        public static int Size => Marshal.SizeOf(typeof(INPUT));
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct InputUnion
    {
        [FieldOffset(0)]
        public MOUSEINPUT mi;
        [FieldOffset(0)]
        public KEYBDINPUT ki;
        [FieldOffset(0)]
        public HARDWAREINPUT hi;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct KEYBDINPUT
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MOUSEINPUT { /* 不需要鼠标输入可省略 */ }
    [StructLayout(LayoutKind.Sequential)]
    private struct HARDWAREINPUT { /* 不需要硬件输入可省略 */ }

    private const uint INPUT_KEYBOARD = 1;
    private const uint KEYEVENTF_KEYUP = 0x0002;

    [DllImport("user32.dll", SetLastError = true)]
    private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

    // 封装单个按键按下+抬起的方法
    public static void SendKey(ushort virtualKeyCode)
    {
        var inputs = new INPUT[2];
        // 按键按下
        inputs[0].type = INPUT_KEYBOARD;
        inputs[0].U.ki.wVk = virtualKeyCode;
        // 按键抬起
        inputs[1].type = INPUT_KEYBOARD;
        inputs[1].U.ki.wVk = virtualKeyCode;
        inputs[1].U.ki.dwFlags = KEYEVENTF_KEYUP;
        
        SendInput((uint)inputs.Length, inputs, INPUT.Size);
    }
}

这个方案优势:类库可以独立运行,不需要调用方做额外适配,也不需要引入WinForms相关依赖。


方案2:抽象接口+客户端注入实现(复用官方SendKeys逻辑)

如果你不想自己处理按键模拟的各种边界场景(比如组合键、特殊按键转义),可以通过抽象层让客户端注入原生SendKeys的实现:

  • 你的.NET Standard 2.0类库中定义公共接口:
public interface IKeySender
{
    void Send(string keys);
    void SendWait(string keys);
}
  • 分别在两个客户端项目中实现该接口,内部直接调用原生的System.Windows.Forms.SendKeys:
// .NET Framework 4.8 / .NET 5 客户端中实现
public class WinFormsKeySender : IKeySender
{
    public void Send(string keys) => System.Windows.Forms.SendKeys.Send(keys);
    public void SendWait(string keys) => System.Windows.Forms.SendKeys.SendWait(keys);
}
  • 客户端初始化时将实现实例注入到你的类库中,类库内部直接调用IKeySender的对应方法即可。
    这个方案的注意事项:.NET 5客户端需要在项目文件中添加<UseWindowsForms>true</UseWindowsForms>配置,开启WinForms支持,才能正常引用System.Windows.Forms.SendKeys。

通用注意事项

  • 按键模拟是Windows平台专属能力,两个客户端都只能运行在Windows系统下才能生效
  • 如果目标应用是以管理员权限运行的,你的客户端程序也需要以管理员权限启动,否则按键指令会被系统权限拦截
  • 不要在后台服务进程中使用按键模拟,服务进程的会话隔离会导致按键指令无法发送到用户桌面的应用程序

内容的提问来源于stack exchange,提问作者fwinterl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:06:04