【问题标题】:Calling keybd_event in user32.dll from Powershell从 Powershell 调用 user32.dll 中的 keybd_event
【发布时间】:2015-11-11 05:00:03
【问题描述】:

我正试图阻止屏幕保护程序启动。 我试过发送击键,但它们都需要按标题抓取一个窗口。 如果桌面上没有打开的窗口,则没有什么可以抓取的。

所以我找到了一些可行的方法,但我不是 C# 向导。 它基于Simulating a keypress AND keyrelease in another application?

下面的代码应该发送 1,但我遗漏了一些东西。在我从 Powershell 调用新类型之前,我没有收到任何错误。 在这个工作之后,我想让它发送一个 F15 来重置屏幕保护程序倒计时但不修改屏幕上的东西。 (但我要先爬,先发送 1s)

Add-Type @"
using System.Runtime.InteropServices;

namespace ConsoleApplication1 
{
    public static class PressKeyForMe 
    { 
        [DllImport("user32.dll")] 
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

        //public static void Main(string[] args)
        public static void Main()
        {            
            //This code will press and hold the '1' button for 3 secs, and then will release for 1 second
            //VK_F15 0x7E
            keybd_event((byte)0x31, (byte)0x02, 0, UIntPtr.Zero);
            Thread.Sleep(3000);

            keybd_event((byte)0x31, (byte)0x82, (uint)0x2, UIntPtr.Zero);
            Thread.Sleep(1000);
        }
    }

}
"@
cls

#all of these give me: Unable to find type
[void] [PressKeyForMe]::Main()
[void] [ConsoleApplication1]::PressKeyForMe()
[void] [PressKeyForMe.Main]
[void] [ConsoleApplication1.Main]
[void] [ConsoleApplication1.PressKeyForMe]::Main()

【问题讨论】:

    标签: c# powershell


    【解决方案1】:

    您似乎在该类型定义中缺少一些using-statements:

    Add-Type @"
    using System;
    using System.Threading;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1 
    {
        public static class PressKeyForMe 
        { 
            [DllImport("user32.dll")] 
            static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
    
            //public static void Main(string[] args)
            public static void Main()
            {            
                //This code will press and hold the '1' button for 3 secs, and then will release for 1 second
                //VK_F15 0x7E
                keybd_event((byte)0x31, (byte)0x02, 0, UIntPtr.Zero);
                Thread.Sleep(3000);
    
                keybd_event((byte)0x31, (byte)0x82, (uint)0x2, UIntPtr.Zero);
                Thread.Sleep(1000);
            }
        }
    
    }
    "@
    

    现在应该可以工作了:

    [ConsoleApplication1.PressKeyForMe]::Main()
    

    您也可以只添加方法并将自动生成的类型分配给变量:

    $KeyPresser = Add-Type -MemberDefinition @"
    [DllImport("user32.dll")]
    static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
    
    public static void PressOne(int press, int release)
    {
        //This code will press and hold the '1' button for 3 secs, and then will release for 1 second
        //VK_F15 0x7E
        keybd_event((byte)0x31, (byte)0x02, 0, UIntPtr.Zero);
        Thread.Sleep(press);
    
        keybd_event((byte)0x31, (byte)0x82, (uint)0x2, UIntPtr.Zero);
        Thread.Sleep(release);
    }
    
    public static void PressOne()
    {
        PressOne(3000, 1000);
    }
    "@ -Name PressKeyForMe -UsingNamespace System.Threading -PassThru
    

    现在您可以在没有完整类型名称的情况下调用该方法:

    PS C:\> $KeyPresser::PressOne() 
    PS C:\> $KeyPresser::PressOne(400,120) # you really need to press 3 seconds?
    

    【讨论】:

    • 谢谢马蒂亚斯!这行得通。不,我不需要疯狂地按住那个键 3 秒钟。我只是不确定在事情破裂之前我可以改变什么。
    • @Mr.Annoyed Cool :) 如果这解决了您的问题,请单击左侧的复选标记将答案标记为“已接受”
    • 在这里我正在寻找一个绿色的大框,上面写着“接受这个解决方案”一个月左右..
    【解决方案2】:

    感谢 Mathias 修复了我上面的代码。我能够完成我的脚本!

    出于好奇,下面是我如何让 F15 键工作的方法。 只需每隔几分钟使用[ScreenSpender.PressKeyForMe]::Main() 即可保持屏幕保护程序处于关闭状态。 感谢 John Savard 在键盘扫描代码方面提供的帮助。

    #The following is an attempt to prevent the SceenSaver from kicking-in during installation
    #We call it using this
    #[ScreenSpender.PressKeyForMe]::Main()
    
    Add-Type @"
    using System;
    using System.Threading;
    using System.Runtime.InteropServices;
    
    namespace ScreenSpender 
    {
        public static class PressKeyForMe 
        { 
            [DllImport("user32.dll")] 
            static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
    
            //public static void Main(string[] args)
            public static void Main()
            {
                //bScan = PS/2 scan code. (We happen to be using Set 1)
                // Make  = when you press the key
                // Break = when you release the key
                //VK_F15 0x7E
                //SC_F15 0x5D   (Scan code set 1) (or 0x64) (http://www.quadibloc.com/comp/scan.htm  - by John Savard)
                //private const int KEYEVENTF_KEYUP = 0x02;
                //This code will press and hold the 'F15' key for 250 Milliseconds, and then will release for 200 Milliseconds
                keybd_event((byte)0x7E, (byte)0x5D, 0, UIntPtr.Zero);
                Thread.Sleep(250);
    
                // Release for 200 Milliseconds
                keybd_event((byte)0x7E, (byte)0x5D, (uint)0x2, UIntPtr.Zero);
                Thread.Sleep(200);
            }
        }
    }
    "@
    

    【讨论】:

      猜你喜欢
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 2012-03-23
      • 1970-01-01
      • 2020-12-13
      • 2012-10-14
      • 2019-04-26
      相关资源
      最近更新 更多