Powershell wait for keypress - powershell

I would like to make this script to pause after typing "Hello this is a test" automatically and after pressing the enter key it should wait for F2 key to be pressed.
How can that be done?
function wait {
param([int]$stop = 3)
Start-Sleep -seconds $stop
}
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
& "$env:Windir\notepad.exe"
$a = Get-Process | Where-Object {$_.Name -eq "Notepad"}
wait
[System.Windows.Forms.SendKeys]::SendWait("Hello this is a test")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
wait
# here I want something like wait for F2 key to be pressed
# after the F2 key was pressed I want the script to continue
[System.Windows.Forms.SendKeys]::SendWait("This is After the key was pressed")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
exit

Here is a modified version of your script that achieves what you want. Keep in mind that this will not work in the PowerShell Integrated Scripting Editor (ISE).
$Wait = 3;
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
& "$env:Windir\notepad.exe"
$a = Get-Process | Where-Object {$_.Name -eq "Notepad"}
Start-Sleep -Seconds $Wait;
[System.Windows.Forms.SendKeys]::SendWait("Hello this is a test")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
Start-Sleep -Seconds $Wait;
while ([System.Console]::ReadKey().Key -ne [System.ConsoleKey]::F2) { };
[System.Windows.Forms.SendKeys]::SendWait("This is After the key was pressed")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
exit

The following will loop until F2 is pressed, with a prompt to the user.
do{ echo "Press F2";$x = [System.Console]::ReadKey() } while( $x.Key -ne "F2" )

Related

How to test for a keypress or continue in powershell

I have a basic powershell function that works as a spambot.
function Start-Spambot{
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,HelpMessage="The text you wish to spam.")]
[string]$text,
[Parameter(Mandatory=$True,HelpMessage="How many milliseconds between messages.")]
[decimal]$speed,
[Parameter(Mandatory=$True,HelpMessage="The tota ammout you want to spam.")]
[decimal]$number
)
$count = $number
Invoke-BalloonTip -Message "You have 3 seconds before the program starts spamming." -Title "Start-Spambot $text $speed $number"
Start-Sleep -Seconds 3
while ($count -gt 0){
[System.Windows.Forms.SendKeys]::SendWait("$text")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
Start-Sleep -Milliseconds $speed
$count -= 1
}
[System.Windows.Forms.SendKeys]::SendWait("$text")
Invoke-BalloonTip -Message "$text has been typed $number times." -Title "Start-Spambot $text $speed $number"
}
The thing i want to add is a kill switch in the while loop. If you press 'esc' for example the script should break the while loop and continue as normal. (invoke-balloontip will make a popup in the bottem right). I have looked at a bunch and googled for hours but they all are just looking to go if the key is pressed and not the other way arround.
Any of you have a simple script or function for this?
Note:
(All of you who are complaining i dont have the code that i tried. Why would i save the things that dont work?)
Edit:
If possible it should work outside of the terminal.
After more searching i finaly found this method:
Add-Type -AssemblyName WindowsBase
Add-Type -AssemblyName PresentationCore
1..10000000 | ForEach-Object {
"I am at $_"
$isDown = [Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::LeftShift)
if ($isDown){
Write-Warning "ABORTED!!"
break
}
start-sleep -Milliseconds 10
}
Edit:
It wont work in the ise wich is kinda anoying

Powershell - Allow user to exit or continue script

I'm a beginner at powershell script. I've written the following script but can't seem to get it to work. When the script is run, after every minute it should output the number of minutes elapsed into a notepad. This should continue non-stop until the user intervenes. If the user presses the "s" key then the script will pause and they'll be asked if they want to continue the script or exit the script. If they type "y" the script will continue from where it left off, else it will stop and exit.
Below is my code:
$myshell = New-Object -com "Wscript.Shell"
$i=1
do
{
$key = if ($host.UI.RawUI.KeyAvailable) {
$host.UI.RawUI.ReadKey('NoEcho, IncludeKeyDown')
}
if ($key.Character -eq 's') {
write-host -nonewline "Continue? (Y/N) "
$response = read-host
if ( $response -ne "Y" ) {exit}
}
Start-Sleep -Seconds 60
$myshell.sendkeys("$i.")
$i++
} while ($true)
This doesn't seem to do anything at all. Any assistance will be appreciated

After $IE.Quit(), the Internet Explorer still exists in Task manager

My case happens when I run $IE.quit() already, but internet explorer still exists in the task manager.
if I run the quit function at "quit IE 1" there, the Internet Explorer will close/end (not exits in Task Manager),
but when I run it at "quit IE 2" there, the IE not end (still exist in Task Manager)
if run with $IE.Visible = $true it has no such problem.
Environment: Windows Server 2016, PowerShell v5.1
May I know what may cause this?
May I know after the "confirm page loaded", what happened to $IE? And possibly cause IE not to quit.
Or how I can trace this kind of problem?
I do try to run this without try/catch, but the same thing happens. I try to put $IE = null, but the same, while, the $IE.Quit() description as to force the end of IE, suppose no wonder what is running on the IE. It will end the task.
Here is the PowerShell script:
$looping = 10
timenowhms = (Get-Date -f HH:mm:ss)
try {
$Url = "http://localhost:8080/commandcenter/checking.aspx"
$IE = New-Object -Com InternetExplorer.Application
$IE.Height = 700
$IE.Width = 750
$IE.Top = 10
$IE.Left = 10
$IE.Visible = $false; # can turn on for testing purpose
$IE.Navigate2($url);
$IEPID = [IntPtr]::Zero
[Win32Api]::GetWindowThreadProcessId($IE.HWND, [ref]$IEPID);
# quit IE 1
$IE.Quit();
} catch {
$timenowhms = (Get-Date -f HH:mm:ss);
echo "$td_date $timenowhms Open website failed";
if ((Get-Process -Name "iexplore*" | ? {$_.Id -eq $IEPID} | measure).Count -eq 1) {
Stop-Process -Id $IEPID -force
};
exit 1
}
# confirm page loaded
while ($ie.Busy -eq $true) {
if ($looping -eq 0) {
$timenowhms = (Get-Date -f HH:mm:ss);
echo "$td_date $timenowhms Timeout, page not show";
if ((Get-Process -Name "iexplore*" | ? {$_.Id -eq $IEPID} | measure).Count -eq 1) {
Stop-Process -Id $IEPID -Force
};
exit 1
} else {
Start-Sleep -Milliseconds 2500;
$looping--;
}
}
# quit IE 2
# $IE.Quit();
exit

How can I interrupt an executable invoked inside a script without interrupting the script itself?

Let's say you have the following script saved in a file outermost.ps1:
powershell.exe -Command "while ( 1 -eq 1 ) {} "
echo "Done"
When running outermost.ps1 you can only abort this by pressing Ctrl+C, and no output will be written to console. How can I modify it so that the outermost script continues and executes echo "Done" when Ctrl+C is pressed?
This is a simplified version of a real-life scenario where the inner script is actually an executable which only is stoppable by pressing Ctrl+C.
Edit: The script could also be:
everlooping.exe
echo "Done"
but I wanted to provide an example everyone could copy-paste into an editor if they wanted to "try at home".
Start your infinite command/statement as a job, make your PowerShell script process Ctrl+C as regular input (see here), and stop the job when that input is received:
[Console]::TreatControlCAsInput = $true
$job = Start-Job -ScriptBlock {
powershell.exe -Command "while ( 1 -eq 1 ) {} "
}
while ($true) {
if ([Console]::KeyAvailable) {
$key = [Console]::ReadKey($true)
if (($key.Modifiers -band [ConsoleModifiers]::Control) -and $key.Key -eq 'c') {
$job.StopJob()
break
}
}
Start-Sleep -Milliseconds 100
}
Receive-Job -Id $job.Id
Remove-Job -Id $job.Id
echo "Done"
If you need to retrieve output from the job while it's running, you can do so like this in an else branch to the outer if statement:
if ($job.HasMoreData) { Receive-Job -Id $job.Id }
The simplest solution to this is:
Start-Process -Wait "powershell.exe" -ArgumentList "while ( 1 -eq 1 ) {}"
echo "Done"
This will spawn a second window unlinke ansgar-wiechers solution, but solves my problem with the least amount of code.
Thanks to Jaqueline Vanek for the tip

Listen for a key press with Powershell, but don't wait for it

I'm trying to write a script that toggles the caps lock key periodically, but I also want to be able to toggle the script because it causes some issues with other functionality (like alt tabbing, and rolling over windows in the task bar to see a preview)
The script I have so far is
:outer while($true){
do{
echo "Toggle with F12";
$x = [System.Console]::ReadKey()
}while( $x.Key -ne "F12" )
while($true){
$wsh = New-Object -ComObject WScript.Shell
$wsh.SendKeys('{CAPSLOCK}')
sleep 0.3
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wsh)
Remove-Variable wsh
if ($Host.UI.RawUI.KeyAvailable) {
$key = $Host.UI.RawUI.ReadKey()
if($key.Key -ne "F12"){
break outer
}
}
}
}
The script waits for the user to press F12, and then once they press F12 I want it to start toggling the caps lock key ever 0.3 seconds until the user presses F12 again. Ideally, I want this to happen in the background, but I don't know if that's possible. I don't want the user to have to have the console window open to toggle the script.
The way this runs now, after the user presses F12 the script will toggle capslock once and then exit. If I remove the conditional after Remove-Variable, the script will run as I want it to except the only way it can be stopped is if the console window is closed.
Here is a try. BTW I changed the sleep to 1 second so it doesn't flash capslock too much while testing:
$continue = $true
while($continue)
{
if ([console]::KeyAvailable)
{
echo "Toggle with F12";
$x = [System.Console]::ReadKey()
switch ( $x.key)
{
F12 { $continue = $false }
}
}
else
{
$wsh = New-Object -ComObject WScript.Shell
$wsh.SendKeys('{CAPSLOCK}')
sleep 1
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wsh)| out-null
Remove-Variable wsh
}
}
add-type -Path '.\documents\WindowsPowerShell\VISE_WinKeyboardHook.dll'
$KeyboardInterceptor = new-object VISE.WinKeyboardHook.KeyboardInterceptor
function HandleKeyDown($keyId)
{
write-host $keyID.KeyCode
if($keyID.KeyCode -eq "Escape"){
$KeyboardInterceptor.StopCapturing()
}
}
Unregister-Event -SourceIdentifier KeyDown -ErrorAction SilentlyContinue
$keyevent = Register-ObjectEvent -InputObject $KeyboardInterceptor -EventName KeyDown -SourceIdentifier KeyDown -Action {HandleKeyDown($event.sourceEventArgs)}
$KeyboardInterceptor.StartCapturing()
Here is a C# assembly which provides event for global keyboard events.
https://ianmorrish.wordpress.com/v-ise/keyboard-hook/
Advantage of this is that it is non-blocking and also works in ISE.