Powershell keeps sending key - powershell

Hi I recently made this script that presses a key in powershell:
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('~')
Now I wonder if I can make the script so: The current script above presses the key one time (virtual), I want it to keep the key mentiont pressed (virtual) until I tell the script to let go the key (virtual)

Related

How to send keyboard input only to a specific application

I'm very new to Powershell. I wrote a simple script basically to automate grinding in a video game when I'm away from my computer. I wanted to know if there's a way instead to 'target' the button presses to a particular window/application/etc. while still working on the same machine in other windows. As it stands, I have to have the game window focused for the script to work so it's only really useful if I'm AFK. But if I could have it running in the background while working on other things that would be useful.
$WShell = New-Object -Com Wscript.Shell
while (1) {sleep 1; [System.Windows.Forms.SendKeys]::SendWait("{LEFT}"*80);
[System.Windows.Forms.SendKeys]::SendWait("{RIGHT}"*80);sleep 1;
[System.Windows.Forms.SendKeys]::SendWait("{C}"*20)}
Since I'm new to Powershell I'm not sure if this is doable or not. If not, it's no problem, this is a pretty frivolous use case, I was just curious.
Think about what you're currently doing. . .it's almost the same as tying the shoe laces on a pair of shoes, just to put on different ones;) You're not using the $wShell anywhere in your script.
. . .but, you're almost there already. We can start by loading the required assemblies, and then have it point to the application which you want to interact with:
Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
[Microsoft.VisualBasic.Interaction]::AppActivate('Notepad')
Start-Sleep -Milliseconds 1000
[System.Windows.Forms.SendKeys]::SendWait("H")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("E")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("L")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("L")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("O")
Take note of notepad in [Microsoft.VisualBasic.Interaction]::AppActivate('Notepad'), as it will be what ever program you're trying to interact with. In this case, you're just sending "HELLO" to the notepad that's already on started.

Powershell SendKeys No Input

I'm working on a dual pc stream setup and would like to use my elgato stream deck on my gaming pc for some specific functions. The only problem is, no obs control. I was combing through reddit and came across the suggestion to use SendKeys in powershell scripts to perform hotkey functions. I am able to connect the two computers through PSSession and run my script, but nothing happens. I have the application focused. Even when I just open a text file and run the script, nothing comes up. I don't really think this should be that hard should it? Any help would be appreciated.
$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys(']')
Continuing from my comment...
Sendkeys is a thing but can be really finicky, focus, timing issues, etc. GUI automation is not really PowerShell's strong suit. Custom tools like AutoIT, Selenium, etc., are better options.
With Sendkeys, you often must set delays to ensure focus before calling keystrokes.
YOu can also avoid the use of ...
New-Object -ComObject wscript.shell
... and use this...
Add-Type -AssemblyName System.Windows.Forms
Here are a few examples you can try.
# pops the WinKey Start Menu
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait('^{ESC}')
Or this way...
# Initialize a variable with the .Net namespace, then use it.
$SendKeys = [System.Windows.Forms.SendKeys]
$SendKeys::SendWait('^{ESC}')
# SendKeys to hold down keys
$SendKeys::SendWait('q(+%) + (+)q')
# Send commnad results to notepad - Note the sleep to wait for notepad to open, paste the content then select the file menu
Get-NetIPConfiguration | clip | notepad
Sleep -Seconds 1
$SendKeys::SendWait('^V')
Sleep -Seconds 2
$SendKeys::SendWait('%F')
Update as per our comments below:
SendKeys requires a GUI up and running. A GUI requires a logged-on, interactive user.

How to check if NumLock is enabled

Recently I ran into an issue with a laptop that had NumLock disabled automatically at certain times (such as when coming out of sleep mode). This prompted me to look for ways to programmatically check if NumLock was off, and if so, turn it on.
I'm looking for the best way to accomplish this. I want to run the script when certain events occur, such as when logging on to the laptop. I plan to do this with a scheduled task, and I'd prefer to use PowerShell over VBScript, but I'd be happy to use whatever works.
In PowerShell, [console]::NumberLock is a Read Only property that will evaluate to true if NumLock is enabled.
The script I ended up writing is as follows:
if(-not [console]::NumberLock){
$w = New-Object -ComObject WScript.Shell;
$w.SendKeys('{NUMLOCK}');
}
Building on Thriggle's answer above, you can ensure NumLock never gets turned off by adding a loop. Note that this is pretty hard on CPU:
While($true){
if(-not [console]::NumberLock){
$w = New-Object -ComObject WScript.Shell;
$w.SendKeys('{NUMLOCK}');
}
}

PowerShell script to simulate "Enter" press [duplicate]

This question already has answers here:
How to perform keystroke inside powershell?
(4 answers)
Closed 7 years ago.
I have a PowerShell script that runs a program which requires a user to press "Enter" before the script can advance. Being that I'm trying to automate this process, I want to eliminate user involvement. Is there a way to simulate this "Enter" press within the PowerShell script? I have tried:
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('~')
and
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait('~');
but it still requires the user to press "Enter" and then it prints "False". It then adds a return at the very end of the program regardless of this code placement in the program.
I used this code at the beginning of my function:
$myshell = New-Object -com "Wscript.Shell"
$myshell.sendkeys("{ENTER}")

How to perform keystroke inside powershell?

I have ps1 script to grab some information from the vmware cluster environment.
In some place of ps1 script requires the ENTER button keystroke.
So, How to do that ?
-Thanks
If I understand correctly, you want PowerShell to send the ENTER keystroke to some interactive application?
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('~')
If that interactive application is a PowerShell script, just use whatever is in the title bar of the PowerShell window as the argument to AppActivate (by default, the path to powershell.exe). To avoid ambiguity, you can have your script retitle its own window by using the title 'new window title' command.
A few notes:
The tilde (~) represents the ENTER keystroke. You can also use {ENTER}, though they're not identical - that's the keypad's ENTER key. A complete list is available here: http://msdn.microsoft.com/en-us/library/office/aa202943%28v=office.10%29.aspx.
The reason for the Sleep 1 statement is to wait 1 second because it takes a moment for the window to activate, and if you invoke SendKeys immediately, it'll send the keys to the PowerShell window, or to nowhere.
Be aware that this can be tripped up, if you type anything or click the mouse during the second that it's waiting, preventing to window you activate with AppActivate from being active. You can experiment with reducing the amount of time to find the minimum that's reliably sufficient on your system (Sleep accepts decimals, so you could try .5 for half a second). I find that on my 2.6 GHz Core i7 Win7 laptop, anything less than .8 seconds has a significant failure rate. I use 1 second to be safe.
IMPORTANT WARNING: Be extra careful if you're using this method to send a password, because activating a different window between invoking AppActivate and invoking SendKeys will cause the password to be sent to that different window in plain text!
Sometimes wscript.shell's SendKeys method can be a little quirky, so if you run into problems, replace the fourth line above with this:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait('~');
function Do-SendKeys {
param (
$SENDKEYS,
$WINDOWTITLE
)
$wshell = New-Object -ComObject wscript.shell;
IF ($WINDOWTITLE) {$wshell.AppActivate($WINDOWTITLE)}
Sleep 1
IF ($SENDKEYS) {$wshell.SendKeys($SENDKEYS)}
}
Do-SendKeys -WINDOWTITLE Print -SENDKEYS '{TAB}{TAB}'
Do-SendKeys -WINDOWTITLE Print
Do-SendKeys -SENDKEYS '%{f4}'
Send "Enter" key to an App, for example for pressing "OK". Works great:
Add-Type -AssemblyName microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
# Get the desired process:
$ProcessName = Get-Process -Name Calculator
Start-Sleep -Seconds 1
# If the process is actually running, bring it to front:
If ($ProcessName)
{
(New-Object -ComObject.Wscript.Shell).AppActivate((Get-Process $ProcessName -ErrorAction SilentlyContinue).MainWindowTitle)
}
# Send "Enter" key to the app:
[Microsoft.VisualBasic.Interaction]::AppActivate($ProcessName.ProcessName)
[System.Windows.Forms.SendKeys]::SendWait({'~'})
Also the $wshell = New-Object -ComObject wscript.shell; helped a script that was running in the background, it worked fine with just but adding $wshell. fixed it from running as background! [Microsoft.VisualBasic.Interaction]::AppActivate("App Name")