需要在批处理文件中模拟 Win 键
needing to emulate Win key in a batch file
我一直在努力寻找答案,但我的研究并没有得出太多对我的情况有帮助的结果。我需要在我正在创建的批处理文件中模拟 Windows 键。这是为了帮助我最大化 window,以及在不使用鼠标的情况下轻松地在显示器之间移动它。该批次将自动运行的工作站将无法使用鼠标或物理键盘。
这是我正在使用的代码。
@if (@CodeSection == @Batch) @then
@echo off
rem Use %SendKeys% to send keys to the keyboard buffer
set SendKeys=CScript //nologo //E:JScript "%~F0"
rem Start the other program in the same Window
Start "Progam"
rem the script only works if the application in question is the active window. Set a timer
timeout /t 10
rem use the tab key to move the cursor to the login and password inputs.
%SendKeys% "This would be the username{TAB}"
%SendKeys% "this would be the password{ENTER}"
rem I then have a timer to let the login happen
timeout /t 10
rem this where I am now trying to maximize and move the active window around.
goto :EOF
@end
// JScript section
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
好问题!是的,前段时间我不得不自己战斗。我想在启动时自动启动从 Microsoft Store 安装的应用程序,出于某种原因,最简单的方法是将它固定到我的任务栏,然后模拟点击 ⊞+1 启动它。我假设现在的情况和当时一样,但是没有办法 SendKeys()
Windows 元键。但是感谢LandOfTheLostPass on reddit,我发现了SendKeys()
的替代方法:发送键盘扫描码。
我修改了 reddit 的代码,让我可以模拟按下多个键,然后释放它们。如果我没记错的话,reddit 上的代码只会模拟按下然后一次释放一个键。我只修改了多键连击的扫码功能。现在重新检查代码,看来我可能破坏了 SendChars()
函数。不过反正我没用过。
<# : win+1.bat -- Batch portion
@echo off & setlocal
powershell -window minimized -noprofile "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell chimera #>
# https://www.reddit.com/r/PowerShell/comments/3qk9mc/keyboard_keypress_script/
Add-Type @"
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class KBEmulator {
public enum InputType : uint {
INPUT_MOUSE = 0,
INPUT_KEYBOARD = 1,
INPUT_HARDWARE = 3
}
[Flags]
internal enum KEYEVENTF : uint
{
KEYDOWN = 0x0,
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
SCANCODE = 0x0008,
UNICODE = 0x0004
}
[Flags]
internal enum MOUSEEVENTF : uint
{
ABSOLUTE = 0x8000,
HWHEEL = 0x01000,
MOVE = 0x0001,
MOVE_NOCOALESCE = 0x2000,
LEFTDOWN = 0x0002,
LEFTUP = 0x0004,
RIGHTDOWN = 0x0008,
RIGHTUP = 0x0010,
MIDDLEDOWN = 0x0020,
MIDDLEUP = 0x0040,
VIRTUALDESK = 0x4000,
WHEEL = 0x0800,
XDOWN = 0x0080,
XUP = 0x0100
}
// Master Input structure
[StructLayout(LayoutKind.Sequential)]
public struct lpInput {
internal InputType type;
internal InputUnion Data;
internal static int Size { get { return Marshal.SizeOf(typeof(lpInput)); } }
}
// Union structure
[StructLayout(LayoutKind.Explicit)]
internal struct InputUnion {
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
// Input Types
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEINPUT
{
internal int dx;
internal int dy;
internal int mouseData;
internal MOUSEEVENTF dwFlags;
internal uint time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBDINPUT
{
internal short wVk;
internal short wScan;
internal KEYEVENTF dwFlags;
internal int time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct HARDWAREINPUT
{
internal int uMsg;
internal short wParamL;
internal short wParamH;
}
private class unmanaged {
[DllImport("user32.dll", SetLastError = true)]
internal static extern uint SendInput (
uint cInputs,
[MarshalAs(UnmanagedType.LPArray)]
lpInput[] inputs,
int cbSize
);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern short VkKeyScan(char ch);
}
internal static short VkKeyScan(char ch) {
return unmanaged.VkKeyScan(ch);
}
internal static uint SendInput(uint cInputs, lpInput[] inputs, int cbSize) {
return unmanaged.SendInput(cInputs, inputs, cbSize);
}
public static void SendScanCodeCombo(short[] scanCodes) {
lpInput[] KeyInputs = new lpInput[1];
lpInput KeyInput = new lpInput();
Enum[] actions = { KEYEVENTF.KEYDOWN, KEYEVENTF.KEYUP };
// Generic Keyboard Event
KeyInput.type = InputType.INPUT_KEYBOARD;
KeyInput.Data.ki.wScan = 0;
KeyInput.Data.ki.time = 0;
KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;
// Press and release the correct key combination
foreach (KEYEVENTF action in actions) {
foreach (short scanCode in scanCodes) {
KeyInput.Data.ki.wVk = scanCode;
KeyInput.Data.ki.dwFlags = action;
KeyInputs[0] = KeyInput;
SendInput(1, KeyInputs, lpInput.Size);
}
}
return;
}
public static void SendChars(char[] keys) {
lpInput[] KeyInputs = new lpInput[1];
lpInput KeyInput = new lpInput();
Enum[] actions = { KEYEVENTF.KEYDOWN, KEYEVENTF.KEYUP };
// Generic Keyboard Event
KeyInput.type = InputType.INPUT_KEYBOARD;
KeyInput.Data.ki.wScan = 0;
KeyInput.Data.ki.time = 0;
KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;
foreach (KEYEVENTF action in actions) {
foreach (char ch in keys) {
// Press the key
KeyInput.Data.ki.wVk = VkKeyScan(ch);
KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYDOWN;
KeyInputs[0] = KeyInput;
SendInput(1, KeyInputs, lpInput.Size);
// Release the key
KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYUP;
KeyInputs[0] = KeyInput;
SendInput(1, KeyInputs, lpInput.Size);
}
}
return;
}
}
"@ # end Add-Type
# Send LWin+1
[KBEmulator]::SendScanCodeCombo(@(0x5B, 0x31))
请参阅 Virtual-Key Codes on Microsoft Docs 查找其他键的扫描码。
顺便说一下,Windows API 提供了 other ways 最大化和移动 windows 而无需模拟键盘快捷键。 (请不要过于苛刻地判断。我在学习如何编写 Batch + PowerShell 混合脚本或在 PowerShell 中包含 .NET 代码之前写了那个 hack。)
你可以使用 http://nircmd.nirsoft.net/
nircmd sendkeypress key
我一直在努力寻找答案,但我的研究并没有得出太多对我的情况有帮助的结果。我需要在我正在创建的批处理文件中模拟 Windows 键。这是为了帮助我最大化 window,以及在不使用鼠标的情况下轻松地在显示器之间移动它。该批次将自动运行的工作站将无法使用鼠标或物理键盘。
这是我正在使用的代码。
@if (@CodeSection == @Batch) @then
@echo off
rem Use %SendKeys% to send keys to the keyboard buffer
set SendKeys=CScript //nologo //E:JScript "%~F0"
rem Start the other program in the same Window
Start "Progam"
rem the script only works if the application in question is the active window. Set a timer
timeout /t 10
rem use the tab key to move the cursor to the login and password inputs.
%SendKeys% "This would be the username{TAB}"
%SendKeys% "this would be the password{ENTER}"
rem I then have a timer to let the login happen
timeout /t 10
rem this where I am now trying to maximize and move the active window around.
goto :EOF
@end
// JScript section
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
好问题!是的,前段时间我不得不自己战斗。我想在启动时自动启动从 Microsoft Store 安装的应用程序,出于某种原因,最简单的方法是将它固定到我的任务栏,然后模拟点击 ⊞+1 启动它。我假设现在的情况和当时一样,但是没有办法 SendKeys()
Windows 元键。但是感谢LandOfTheLostPass on reddit,我发现了SendKeys()
的替代方法:发送键盘扫描码。
我修改了 reddit 的代码,让我可以模拟按下多个键,然后释放它们。如果我没记错的话,reddit 上的代码只会模拟按下然后一次释放一个键。我只修改了多键连击的扫码功能。现在重新检查代码,看来我可能破坏了 SendChars()
函数。不过反正我没用过。
<# : win+1.bat -- Batch portion
@echo off & setlocal
powershell -window minimized -noprofile "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell chimera #>
# https://www.reddit.com/r/PowerShell/comments/3qk9mc/keyboard_keypress_script/
Add-Type @"
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class KBEmulator {
public enum InputType : uint {
INPUT_MOUSE = 0,
INPUT_KEYBOARD = 1,
INPUT_HARDWARE = 3
}
[Flags]
internal enum KEYEVENTF : uint
{
KEYDOWN = 0x0,
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
SCANCODE = 0x0008,
UNICODE = 0x0004
}
[Flags]
internal enum MOUSEEVENTF : uint
{
ABSOLUTE = 0x8000,
HWHEEL = 0x01000,
MOVE = 0x0001,
MOVE_NOCOALESCE = 0x2000,
LEFTDOWN = 0x0002,
LEFTUP = 0x0004,
RIGHTDOWN = 0x0008,
RIGHTUP = 0x0010,
MIDDLEDOWN = 0x0020,
MIDDLEUP = 0x0040,
VIRTUALDESK = 0x4000,
WHEEL = 0x0800,
XDOWN = 0x0080,
XUP = 0x0100
}
// Master Input structure
[StructLayout(LayoutKind.Sequential)]
public struct lpInput {
internal InputType type;
internal InputUnion Data;
internal static int Size { get { return Marshal.SizeOf(typeof(lpInput)); } }
}
// Union structure
[StructLayout(LayoutKind.Explicit)]
internal struct InputUnion {
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
// Input Types
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEINPUT
{
internal int dx;
internal int dy;
internal int mouseData;
internal MOUSEEVENTF dwFlags;
internal uint time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBDINPUT
{
internal short wVk;
internal short wScan;
internal KEYEVENTF dwFlags;
internal int time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct HARDWAREINPUT
{
internal int uMsg;
internal short wParamL;
internal short wParamH;
}
private class unmanaged {
[DllImport("user32.dll", SetLastError = true)]
internal static extern uint SendInput (
uint cInputs,
[MarshalAs(UnmanagedType.LPArray)]
lpInput[] inputs,
int cbSize
);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern short VkKeyScan(char ch);
}
internal static short VkKeyScan(char ch) {
return unmanaged.VkKeyScan(ch);
}
internal static uint SendInput(uint cInputs, lpInput[] inputs, int cbSize) {
return unmanaged.SendInput(cInputs, inputs, cbSize);
}
public static void SendScanCodeCombo(short[] scanCodes) {
lpInput[] KeyInputs = new lpInput[1];
lpInput KeyInput = new lpInput();
Enum[] actions = { KEYEVENTF.KEYDOWN, KEYEVENTF.KEYUP };
// Generic Keyboard Event
KeyInput.type = InputType.INPUT_KEYBOARD;
KeyInput.Data.ki.wScan = 0;
KeyInput.Data.ki.time = 0;
KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;
// Press and release the correct key combination
foreach (KEYEVENTF action in actions) {
foreach (short scanCode in scanCodes) {
KeyInput.Data.ki.wVk = scanCode;
KeyInput.Data.ki.dwFlags = action;
KeyInputs[0] = KeyInput;
SendInput(1, KeyInputs, lpInput.Size);
}
}
return;
}
public static void SendChars(char[] keys) {
lpInput[] KeyInputs = new lpInput[1];
lpInput KeyInput = new lpInput();
Enum[] actions = { KEYEVENTF.KEYDOWN, KEYEVENTF.KEYUP };
// Generic Keyboard Event
KeyInput.type = InputType.INPUT_KEYBOARD;
KeyInput.Data.ki.wScan = 0;
KeyInput.Data.ki.time = 0;
KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;
foreach (KEYEVENTF action in actions) {
foreach (char ch in keys) {
// Press the key
KeyInput.Data.ki.wVk = VkKeyScan(ch);
KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYDOWN;
KeyInputs[0] = KeyInput;
SendInput(1, KeyInputs, lpInput.Size);
// Release the key
KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYUP;
KeyInputs[0] = KeyInput;
SendInput(1, KeyInputs, lpInput.Size);
}
}
return;
}
}
"@ # end Add-Type
# Send LWin+1
[KBEmulator]::SendScanCodeCombo(@(0x5B, 0x31))
请参阅 Virtual-Key Codes on Microsoft Docs 查找其他键的扫描码。
顺便说一下,Windows API 提供了 other ways 最大化和移动 windows 而无需模拟键盘快捷键。 (请不要过于苛刻地判断。我在学习如何编写 Batch + PowerShell 混合脚本或在 PowerShell 中包含 .NET 代码之前写了那个 hack。)
你可以使用 http://nircmd.nirsoft.net/
nircmd sendkeypress key