PowerShell: Toggle "Num Lock" on and off. - powershell

I would like to be able toggle on and off the "Num Lock" key on the keyboard. I have tried multiple examples around the web and here, with no success. This is the closest thing I've got to a solution:
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("{NUMLOCK}")
The above code looks like it might work and I see the "Num Lock" indicator on my keyboard flash for a second but it doesn't "stick".

I experienced the same on/off flicker you did.
This works fine for me though, give it a try:
$wsh = New-Object -ComObject WScript.Shell
$wsh.SendKeys('{NUMLOCK}')

For what it is worth, from the perspective of the keyboard, the OS sends a set and then a reset of the toggle key (caps, scroll lock, numlock) when using [System.Windows.Forms.SendKeys]::SendWait("{CAPSLOCK}"), but only sends a single event using WScript.Shell.

Stumbled here looking for a way to keep Num Lock ON eternally (apparently the word "lock" doesn't mean much 🤷‍♂️). This script checks Num Lock status every 2 seconds, and switches it back on if it's been turned off:
$wsh = New-Object -ComObject WScript.Shell
while($true){
if ([console]::NumberLock -eq $false) {
$wsh.SendKeys('{NUMLOCK}')
}
Start-Sleep 2
}
I think it would be a good candidate for converting into a standalone tiny .exe using PS2EXE.

intTime=0
strInputVal=InputBox("Enter the time","Enter Hours in Int")
intTime=strInputVal * 60 * 60
set WshShell = WScript.CreateObject("WScript.Shell")
For i = 1 to intTime
WScript.Sleep 500
WshShell.SendKeys "{NUMLOCK}"
WScript.Sleep 500
Next
WScript.Quit
Set WshShell = Nothing

Related

Ignore CTRL+C in delay - powershell

Whenever I set a delay in powershell using Start-Sleep, e.g:
Start-Sleep 10
then it does not ignore CTRLC. I mean when I hit that key stroke the delay quits. How can I ignore it in delays?
You can temporarily set [Console]::TreatControlCAsInput to $true:
[Console]::TreatControlCAsInput = $true
Start-Sleep 10 # Ctrl-C will now not abort this sleep.
[Console]::TreatControlCAsInput = $false
I have found a way to do this:
[System.Threading.Thread]::Sleep(milliseconds)
This ignores CTRL-C on delays.

sendkey code that will interrupt screen saver and not trigger help.txt in vi?

I have a powershell script running in the background to interrupt the screen saver. Unfortunately this has a very annoying side effect of triggering help.txt in vi when it has focus (e.g. via PuTTY).
Does anyone know of a sendkey code that will both interrupt the screen saver and not trigger help.txt in vi?
I have tried the following with no luck:
sendkeys("{NUMLOCK}{NUMLOCK}")
sendkeys("^")
sendkeys("{F15}")
sendkeys("{PRTSC}")
sendkeys("{SCROLLLOCK}{SCROLLLOCK}")
Any other suggestions are also welcome.
rather than send keys why not just move the mouse pointer like below
param($Minutes = 60)
for ($i = 0; $i -lt $Minutes; $i++) {
Start-Sleep -Seconds 60
$Pos = [System.Windows.Forms.Cursor]::Position
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point((($Pos.X) + 1) , $Pos.Y)
}
I was able to fix this in PuTTY by updating the session configuration under Terminal=>Keyboard
In the section marked: The Function keys and keypad
Select Xterm R6
This seems to prevent the sendkey code from triggering help text in vi

Start Internet Explorer, wait until the user closes it, then exit the script

I have a script that opened IE with no toolbar and to navigate to a url (below)
Dim IE, URL
URL = "website.com"
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate URL
IE.Visible = 1
IE.ToolBar = 0
IE.Left = 0
I need to have the window appear like this for reasons,
I cant use kiosk mode.
What I need to do is:
run the script (LaunchIE_noToolbar.vbs)
open IE, hide toolbar, go to url
wait in the background while the user does stuff which might be 10-15 minutes later
recognize it's closed and exit the script
It seems simple enough, but I can't work it out, the waiting part is driving me nuts.
If you can do this in PowerShell that would be great too, I don't mind.
I'm not in front of a computer right now, but as I recall...
You can start a process aka start-process I think. Grab the process ID which is returned. Then wait for the process to complete, might be wait-process? Do a "help process" at the PowerShell prompt for commands and syntax.
There may be a more elegant PowerShell solution, but this seems to work:
$url = "website.com"
$ie = New-Object -ComObject "InternetExplorer.Application"
$ie.Navigate($url)
$ie.Visible = 1
$ie.ToolBar = 0
$ie.Left = 0
# Wait for IE to exit.
while ($null -ne $ie.ReadyState) { # .ReadyState is only $null once the IE instance exits
Start-Sleep -Milliseconds 100
}

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}');
}
}

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")