我制作了一个打开某个程序的程序,然后在x时间后按Ctrl+C它。
我现在正在使用这个
[System.Windows.Forms.SendKeys]::SendWait("^{c}")
。
这会针对某个窗口还是只是随机地将其发送到当前窗口?
如何更改为某个窗口?
这是我的代码:
Write-Host "Safe Botting V0.1"
Write-Host "Initializing..."
Start-Sleep -s 3
Write-Host "Program started successfully with no errors."
While($true)
{
Write-Host "Starting bot..."
Start-Sleep -s 3
Start-Process -FilePath E:\Documents\bot.exe
Write-Host "Bot started successfully"
$rnd = Get-Random -Minimum 1800 -Maximum 10800
Write-Host "The bot will run for:"
Write-Host $rnd
Start-Sleep -s $rnd
Write-Host "Bot will now stop!"
[System.Windows.Forms.SendKeys]::SendWait("^{c}")
Write-Host "Bot terminated"
Write-Host "Starting cooldown time"
$rnb = Get-Random -Minimum 14400 -Maximum 28800
Write-Host "The bot will cooldown for"
Write-host $rnb
Start-Sleep -s $rnb
Write-Host "Cooldown Finished, Restarting"
Start-Sleep -s 5
}
如果您有进程 ID,您可以向进程发送 CTRL_C_EVENT 信号。在你的情况下,你可以从 Start-Process 获取它(如果你不知道如何获取进程 ID,请阅读文档)。也可以从窗口句柄获取进程 ID:
发送信号并不简单,但感谢@Nemo1024、@KindDragon 和 Stack Overflow,它已经解决了:
我可以向 Windows 上的应用程序发送 ctrl-C (SIGINT) 吗?
不幸的是,使用我能找到的最佳方法也终止了调用 PowerShell 进程,我能想到的唯一解决方法是从我启动的新 PowerShell 实例发送信号。
在 PowerShell 中,它看起来像这样:
# be sure to set $ProcessID properly. Sending CTRL_C_EVENT signal can disrupt or terminate a process
$ProcessID = 1234
$encodedCommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes("Add-Type -Names 'w' -Name 'k' -M '[DllImport(""kernel32.dll"")]public static extern bool FreeConsole();[DllImport(""kernel32.dll"")]public static extern bool AttachConsole(uint p);[DllImport(""kernel32.dll"")]public static extern bool SetConsoleCtrlHandler(uint h, bool a);[DllImport(""kernel32.dll"")]public static extern bool GenerateConsoleCtrlEvent(uint e, uint p);public static void SendCtrlC(uint p){FreeConsole();AttachConsole(p);GenerateConsoleCtrlEvent(0, 0);}';[w.k]::SendCtrlC($ProcessID)"))
start-process powershell.exe -argument "-nologo -noprofile -executionpolicy bypass -EncodedCommand $encodedCommand"
是的,我知道这非常丑陋。
感谢 jimhark,我找到了一种方法使其可以工作,而无需生成单独的 PowerShell 进程来发送 Ctrl-C。如果发送 Ctrl-C 的 PowerShell 进程也生成,则它可以工作,例如使用 Start-Process,将 Ctrl-C 发送到的进程:
$ProcessID = 1234
$MemberDefinition = '
[DllImport("kernel32.dll")]public static extern bool FreeConsole();
[DllImport("kernel32.dll")]public static extern bool AttachConsole(uint p);
[DllImport("kernel32.dll")]public static extern bool GenerateConsoleCtrlEvent(uint e, uint p);
public static void SendCtrlC(uint p) {
FreeConsole();
AttachConsole(p);
GenerateConsoleCtrlEvent(0, p);
FreeConsole();
AttachConsole(uint.MaxValue);
}'
Add-Type -Name 'dummyName' -Namespace 'dummyNamespace' -MemberDefinition $MemberDefinition
[dummyNamespace.dummyName]::SendCtrlC($ProcessID) }
使事情有效的方法是将 GenerateConsoleCtrlEvent 发送到所需的进程组,而不是
all processes that share the console of the calling process
并将 AttachConsole 返回到 the console of the parent of the current process
。
刚刚在 VSCode 中执行的脚本中尝试了 @GeorgesZ 的解决方案,但它仅部分有效:
CTRL-C 被发送到所需的进程。效果很好。
但是我无法在 VSCode 中恢复我的控制台。我想我的调用脚本继续在某个地方执行,但我看不到任何输出。
无论如何,谢谢,这个主题并不容易。我最终使用@Jimhark 解决方案:它工作正常。