#c# #powershell
#c# #powershell
Вопрос:
Это то, что я собрал воедино, и я не могу понять, почему это не работает. Смысл скрипта в том, что он должен открыть google-chrome и разместить его в правой части экрана.
Я не лучший в powershell, поэтому я надеюсь, что вы, ребята, сможете помочь мне понять, почему это не работает. И помогите мне найти решение.
$source = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyboardSend
{
public class KeyboardSend
{
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KEYEVENTF_EXTENDEDKEY = 1;
private const int KEYEVENTF_KEYUP = 2;
public static void KeyDown(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY, 0);
}
public static void KeyUp(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
}
"@
Add-Type -TypeDefinition $source -ReferencedAssemblies "System.Windows.Forms"
Function Win ($Key)
{
[KeyboardSend.KeyboardSend]::KeyDown("LWin")
[KeyboardSend.KeyboardSend]::KeyDown("$Key")
[KeyboardSend.KeyboardSend]::KeyUp("LWin")
}
$chrome = 'C:Program FilesGoogleChromeApplicationchrome.exe'
$url = 'www.google.com'
amp; $chrome $url
$wshell = New-Object -ComObject wscript.shell;
[KeyboardSend.KeyboardSend]::KeyDown("LWin")
sleep 1
$wshell.SendKeys('{RIGHT}')
[KeyboardSend.KeyboardSend]::KeyUp("LWin")
Ответ №1:
# 1: Похоже, вы пытаетесь выполнить несколько действий для выполнения одной и той же функции. Например. Win()
функция, the $wshell.SendKeys
и the KeyUp/KeyDown
из C #.
Чтобы исправить это, мы представим простую новую функцию C # для замены SendKeys:
public static void KeyPress(Keys vKey)
{
KeyDown(vKey);
KeyUp(vKey);
}
Итак, теперь вы можете отправлять свои Win Right
подобные сообщения:
KeyDown("LWin");
KeyPress("Right");
KeyUp("LWin");
# 2: Для отправки ключей приложениям Windows требует, чтобы окно приложения было готово и активно на переднем плане. Если вы попытаетесь отправить слишком быстро после выполнения, это не сработает. Если вы попытаетесь, пока окно находится в фоновом режиме, это не сработает.
Чтобы справиться с этим, мы будем использовать Windows API:
[DllImport("User32.dll")]
static extern int SetForegroundWindow(IntPtr hWnd);
public static bool SetForeground(string processName)
{
Process proc = null;
var procs = Process.GetProcessesByName(processName);
// Wait until a window handle is available.
// Some apps like Chrome spawns MANY processes, but only
// one will have a MainWindowHandle.
System.Threading.Tasks.Task.Run(() =>
{
while (proc == null)
proc = procs.FirstOrDefault(p => p.MainWindowHandle != IntPtr.Zero);
}).Wait(2000); // Quit if none found in this time
if (proc == null) return false;
SetForegroundWindow(proc.MainWindowHandle);
return true;
}
И вы можете просто использовать его следующим образом:
SetForeground("chrome");
Теперь полный код.
ПРИМЕЧАНИЕ: я использую msedge
, поскольку у меня не установлен Chrome. Вы должны быть в состоянии найти 2 ссылки на edge и заменить их обе на chrome
.
$source = @"
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyboardSend
{
public class KeyboardSend
{
private const int KEYEVENTF_EXTENDEDKEY = 1;
private const int KEYEVENTF_KEYUP = 2;
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
[DllImport("User32.dll")]
static extern int SetForegroundWindow(IntPtr hWnd);
public static bool SetForeground(string processName)
{
Process proc = null;
var procs = Process.GetProcessesByName(processName);
// Wait until a window handle is available.
// Some apps like Chrome spawns MANY processes, but only
// one will have a MainWindowHandle.
System.Threading.Tasks.Task.Run(() =>
{
while (proc == null)
proc = procs.FirstOrDefault(p => p.MainWindowHandle != IntPtr.Zero);
}).Wait(2000); // Quit if none found in this time
if (proc == null) return false;
SetForegroundWindow(proc.MainWindowHandle);
return true;
}
public static void KeyDown(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY, 0);
}
public static void KeyUp(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
public static void KeyPress(Keys vKey)
{
KeyDown(vKey);
KeyUp(vKey);
}
}
}
"@
Add-Type -TypeDefinition $source -ReferencedAssemblies "System.Windows.Forms"
# Start your app
$chrome = 'msedge.exe' #change to chrome
$url = 'about:blank'
Start-Process -PassThru $chrome $url
# Wait for window to be available and pull to front.
[KeyboardSend.KeyboardSend]::SetForeground("msedge"); #change to chrome
# May wanna wrap in an IF statement in case it failed.
# Send your keys
[KeyboardSend.KeyboardSend]::KeyDown("LWin");
[KeyboardSend.KeyboardSend]::KeyPress("Right");
[KeyboardSend.KeyboardSend]::KeyUp("LWin");
# You may need to send escape if Windows10 asks you
# what you want to snap to the other side.
sleep -Milliseconds 200
[KeyboardSend.KeyboardSend]::KeyPress("Escape");