Windows Forms SendKeys using Read-Host - powershell

Apologies if this question has already been answered on another thread, but I went looking for my specific query and I couldn't anything.
The issue I have is sending keystrokes to a Read-Host command. When I do this, nothing populates. Is this even possible?
$sendKeys = [System.Windows.Forms.SendKeys]
Sleep-Start -Seconds 1
$sendKeys::SendWait('serv01{ENTER}')
Read-Host -Prompt "Server Name"
Running this would only show the prompt and still waiting for input:
Server Name:
Please advise if this is possible.

Your code:
DOES work in regular console windows, in Windows Terminal, and - assuming the keyboard focus is on the integrated terminal when the code is run - in Visual Studio Code.
does NOT work in the Windows PowerShell ISE.
However, given that the ISE is obsolescent, consider migrating to Visual Studio Code with its PowerShell extension.
As a workaround, consider the technique shown in this answer, which uses a custom Read-Host function that returns predefined responses.
Note: The workaround suggested for use in the ISE may actually be the preferable solution overall, given that sending keystrokes is inherently brittle (not fully robust).

Related

PS1 script works normal in ISE but displays my -AsSecureString text when in Exe?

I'm writing a script right now but I can't figure out why this adding to the script makes my -AsSecureString echo in the finished result while compiled to an CMD/window (.*Exe) with ISEsteroids.
I am using Read-Host to use above and hide password written inside script. And while running the code in editor it works wonderful. But while compiled using ISEsteroids to executable my script runs and then at the end echos the password 3 times in plain text... like this(images)
im using this to add the "run again" boxes and script in between.
$choices = [System.Management.Automation.Host.ChoiceDescription[]] #("&Yes","&No")
while ( $true ) {
Script here:
$Host.UI.RawUI.WindowTitle = $PSScriptRoot
$choice = $Host.UI.PromptForChoice("Run again","",$choices,0)
if ( $choice -ne 0 ) {
break
}
}
ISE output:
Output from executable:
UPDATE - SOLVED got help from #mklement0! this solved the issue.
while ([Console]::KeyAvailable) { $null = [Console]::ReadKey($true) }
tl;dr
As a workaround for the unexpected behavior you see in your compiled application - characters typed in response to Read-Host also showing up in a later, unrelated prompt - clear the console keyboard buffer before calling $Host.UI.PromptForChoice(...) (taken from this answer):
# Clear any pending keystrokes.
while ([Console]::KeyAvailable) { $null = [Console]::ReadKey($true) }
The difference in behavior comes down to different PowerShell host implementations.
A PowerShell host is a .NET class derived from the abstract System.Management.Automation.Host.PSHost class, and its purpose is to provide input to and display output from the PowerShell runtime.
Different PowerShell environments have different host implementations whose behavior can differ substantially, and hosts are allowed to not implement certain features. $Host.Name reports a host's friendly name, such as ConsoleHost in regular console windows.[1]
An example of differing behavior is that the (obsolescent) ISE uses a GUI dialog for Read-Host -AsSecureString, whereas a regular console window prompts directly in the console.
I don't know what host implementation your compiled executable - created by wrapping a PowerShell script in a stand-alone executable - uses. In the simplest case, it uses the simple DefaultHost implementation that is used by default when you embed PowerShell in an application via the PowerShell SDK.
The behavior you experienced smells like a bug, but at least the workaround shown above seems to be effective.
[1] Note that there's seemingly no way to determine the full type name of the host-specific PSHost-derived class via the automatic $Host variable, whose own type is the non-public [System.Management.Automation.Internal.Host.InternalHost]` class. Similarly, the host-specific type may be non-public.

Do PowerShell ISE scripts produce system calls altering the entire OS down to the kernel?

I'm a complete rookie to programming. I will say so much off the bat: please go easy on me. I simply want to know what happens on a system-wide level when I run a script through the PowerShell ISE program. If I run something in an IDE, I have always assumed that no system calls are made, meaning the script isn't communicating with the kernel or making actual changes to the OS. To the contrary, the script is simply being run in a sandboxed environment, as a test run for lack of better terms. I use the term sandboxed loosely here.
If I am on the mark here regarding how an IDE works, does PowerShell also work the same way. If I am incorrect overall with all of my observations, please correct me. I'm just a tad bit beyond the phase of a script kiddie. I can write simple Bash scripts and execute PowerShell commands but I am miles behind the talent of a developer or full-time programmer. Looking for an answer from a veteran to a rookie here.
The PowerShell ISE is called an Integrated Scripting Environment. It can be thought of as a stripped down Visual Studio or maybe instead an enlightened Notepad with a paired PowerShell console.
In any case, and maybe someone will chime in with the true history of the ISE here, the PowerShell console is just as effective and powerful as the Linux Bash Shell, or the Windows Command Prompt.
Commands you run in PowerShell use underlying Windows APIs or dotnet namespaces which can absolutely change the system.
For instance, you can start and stop services or even disable them, if you've got the permissions and are running as an administrator. That's definitely changing the underlying system.
Set-Service -Name Spooler -StartupType Disabled
You can also change registry keys you definitely should not be touching.
#Disable Windows Update
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate -Name AU -Type DWord -Value "NoAutoUpdate"
Having permission to do these things depeneds on what your account can do. If you're running as a standard Windows user without admin rights, these calls will fail.
If you run the ISE or PowerShell without 'Run As Administrator', these calls will fail.
However, if you are an admin, and run PowerShell or the ISE as an Admin, you have effectively taken both safeties off and can now freely ventilate your foot.
Same goes for if you're running with a powerful Active Directory or Azure account. Only use those credentials when you need them, or your inevitable accidents will be truly remarkable, swift and terrible.

Question about ISE vs Console with SystemEvents

When I run the following in PowerShell ISE, it works perfectly, gives me the reason "AccountLock" or "AccountUnlock" exactly as it's supposed to. However, when I run this exact command in an elevated powershell console, it does not return the sessionswitch reason at all in console. It returns nothing after an unlock.
I checked Get-EventSubscriber as well as Get-Job and both look successfully created.
Screenshot of Subscriber & Job:
Register-ObjectEvent -InputObject $([microsoft.win32.systemevents]) -EventName "SessionSwitch" -Action {write-host $event.SourceEventArgs.Reason}
One thing I would like to do is have windows detect when the session is unlocked (after a user syncs their password with the domain) and open a program.
OS: Windows 10
Version: 5.1 Build 17134 R 590
After a lot of looking around, i couldn't find a good way to use [windows.win32.systemevents], so i reached out to Lee Holmes. He said it is because the powershell console host runs by default in the Single Thread Apartment (STA) model. If you run it in MTA, it works fine.
Simplest workaround is to use code similar to this at the beginning of your script to ensure you are in MTA mode, and if start a new powershell process if you are not and reload the script.
if ([System.Threading.Thread]::CurrentThread.ApartmentState -ne [System.Threading.ApartmentState]::MTA)
{
powershell.exe -MTA -File $MyInvocation.MyCommand.Path
return
}
Have a look to Microsoft documentation : SystemEvents.SessionSwitch Event, the explanation seems to be that this message is sent to message pump which is the part of code that process graphic messages. You perhaps can try to use an hidden form in your code to force creation of a message pump.
Note :
This event is only raised if the message pump is running. In a Windows service, unless a hidden form is used or the message pump has been started manually, this event will not be raised. For a code example that shows how to handle system events by using a hidden form in a Windows service, see the SystemEvents class.

Test-Path prints false even if the path exists in registry

While debugging a script in VS code's Powershell Integrated Console if I test for a registry path it's printing False even though the path exists.
If I execute the same instruction in PowerShell window or VS Code's Powershell Console it prints True.
I am running all instances with Admin privileges.
Check if Get-PSProvider shows Registry providers in both Integrated Console and Powershell Console. If it does not exist for some reason, test path simply won't understand Registry:: root. Environments may be different as explained here: https://powershell.org/2013/10/19/the-shell-vs-the-host/
You're using the wrong syntax argument (I'd suggest testing in the DBG console or the powershell.exe process as an FYI)... Also, don't post code as images, it's a bad practice that will not get your question answered.
The PowerShell way:
Test-Path -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GMS Software'
The issue was with VS code installation. A complete uninstall of VS code and reinstalling it resolved the problem.

Powershell Ambiguous Code Running on Windows Machine

Out of sudden, a colleague of mine found a script that runs during the startup of the Windows on his machine, which is found to be a powershell script.
The code is below, what I understood that it only minimizes all windows opened.
powershell -command "& { $x = New-Object -ComObject Shell.Application; $x.minimizeall() }"
I need to know if there is an impact from this code on his machine as to isolate from the network.
It doesn't seem to present a threat in and of itself. If someone is doing something unwanted, it would probably be that they're starting some other program that does something not nice, and this PowerShell command minimizes its window (possibly to the taskbar notification area where it can be hidden) so that you don't see what's going on. But the command itself appears harmless.
It only minimizes all the windows. Except that nothing else. I don't think it is harmful. If someone has kept it in the startup, I believe the reason being some other App is opening window in the startup , so it is trying to avoid that.