PowerShell script problem, cause of lacking knowledge - powershell

I have kinda 0 expirience of coding but wanted to get myself a script which would take some work of me.'
Started this yesterday and just googled myself everything together.
What I want to do is open a vnc viewer(remote desktop app for our raspberrys), copy paste a link there, log into the website, fullscreen it and leave the session of vnc viwer, go into the next pi (we have 6 different where we need to do this every 3 hours) and do exactly the same.
I get everything together just with simple phrases like:
$wshell.SendKeys("{TAB}")
$wshell.SendKeys("{Enter}")
etc. but the only problem I have no is to close the session of vncviewer without killing the overview console(both have different tasks in task manager but named the same, only different is the ProcessID but this is changing for every start.
I figured out myself 3 different solutions but couldn't find a working answer on this in different forums or tech discords.
LF a command like" (New-Object -ComObject WScript.Shell).AppActivate((Kill-Process vncviewer).MainWindowTitle) " which would kill only the vncviewer which is the main window atm (normaly this command is exactly the same only swap "Kill-Process" for "get-process" but I just wrote kill process to better descripe what Im looking for) and would leave the overview console open.
Get a command like .SendKeys for MouseClicks so I could work with fix "Set mouse coordinate" commands in PowerShell and then just simulate a mouseclick to close the window.
Do a "Get-Process | Out-File" and a "Get-Content" in the next line to write and read the processes which are running atm, to terminate the ProcessID of the session of nvcviewer to kill it via "Stop-Process "ProcessID"".
But couldnt find a command for "Get-Content | Where-Object_Name = "nvcviewer"" or smth like this to know what ProcessID its running atm, problem would be I would get 2 process IDs without knowing which one to kill.
Would be great to get some help on this, sorry for my bad english/grammar its not my native language and I'm rly new to coding etc so if you have a answer for me would be great to get this explained for an 5year old ^^ + I'm not allowed to install 3rd party software so all needs to be in PowerShell.

Related

Powershell won't pass keystroke to cli window

I first need to offer the disclaimer that I am barely a novice when it comes to scripting or coding, so I might be doing this all wrong in the first place. I'm running into an issue with a script I had written in powershell a while ago that is used on several hundred computers in my company daily to automate starting a certain app that everyone uses. So far everyone else hasn't had an issue except one machine.
Normally when I run the script, it starts the services and cli for the program which opens in a new window. Then the script, still open behind that, sends all of the key commands to that cli window, pauses for a brief line of user input after which it closes that cli window, does a few other clean up tasks and closes out itself.
The only difference on this one machine that's not working is the script won't pass the keystrokes to the cli window. If I put them in manually including the normal user input, it finishes the rest of the script just fine, but the cli window is just not receiving the keystroke input from the main script.
The only part of the script that send the keystrokes to the cli window is a few lines of this:
[System.Windows.Forms.SendKeys]::SendWait("Text{Enter}")
I have tried using the sleep command before and in between the key commands to make sure it's not going through the keystrokes to early. I've checked and windows had gone through an Update two days ago, but we would've heard about this issue right then if that was it. I'm at a loss for what the issue could be and would apreciate and help, tips, or direction to help figure this one out.
Is the console window the active window when the keys are sent? The documentation for the class you are calling indicates that it sends the keys to the active window. Not only that, but the documentation also seems to indicate that there are some issues that developers have run into when using that class to sends keys. I would try using the autoit powershell module instead. Autoit is its own scripting language which specializes in automating windows processes and being capable of automating interactions with windows forms, but also comes bundled with its own powershell module that I think is exactly what you need, so I would download the portable "zip" package, extract the powershell module from "Autoitx", and that should help you accomplish what you need
PowerShell automation especially when using SendKeys can / is glitchy due to many varying reasons. Can you use SendKeys sure, but you have to know the environment it will be run in and the needed performance details. Hence your futzing/guessing with Sleep.
There are purpose-built tools to help.
Auto HotKey
'PowerShell auto hotkey'
or the UIAutomation tool
'PowerShell automating other applications'

How to automate UI keyboard input? pywin32 PostMessage vs Powershell SendKeys

Motivation: I'm using a software that doesn't have an API to interface with ... I have no alternative and have to open the software, send simple key sequence, then close ... Again and again, so I want to automate this process.
Goal: Send combinations of keyboard inputs to an inactive window.
Progress: I wrote a powershell script that open, send keys, wait, then end the process, but it only works on active window. A part of the powershell code is as follows.
$appProcess = Start-Process -FilePath $path -PassThru
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate($appProcess.Id)
$wshell.SendKeys('%(E)E')
Stop-Process $appProcess -Force
It works, but only on active window (windows comes to the top). What I want is to run automate the window in the background. I found an article that point me to using PostMessage in Win32 API. Since the majority of my code uses python, I decided to move from powershell to pywin32.
Issue: I cannot get the PostMessage to send key to the right handler. I saw in this article that I may need to find the exact window, but I still don't really understand how. In powershell, I can directly send keys via $wshell.AppActivate($appProcess.Id).
hwndMain = win32gui.FindWindow(None, winname)
hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD)
temp = win32api.PostMessage(hwndChild, win32con.WM_KEYDOWN, 0x45, 0)
# temp came out as None
Question: Is there a way to do this in pywin32 / Win32 API?
Edit: (May 8, 2020) Yes, I have heard that using SendKeys are not reliable, but since there is no alternative offered to questions like this one on SO, how should anyone learn the "right way"? If you think there is alternative, everyone will appreciate to see a solution in action. Please suggest edits to my post to improve the quality of the question instead of shooting it down.
Time ago I developed SendMessage utility that allows to post messages to other processes or Windows via the WIN32 API. I discovered that I can't send a message to an inactive window, so I searched for a method to activate a Window. After several tests, I found a trick that allows me to "reactivate" a Window:
The development of this program presented a problem: the items in the
Notepad topmost menu can not be selected if the window was not active.
I did some tests and discovered that this point depends on the
relation that the cmd.exe window have (has?) with the other window and
the particular program in the other window. For example, in the case
of Calculator Windows accessory, its menu items can be selected when
the window is not active, and even when the window is minimized! I
tried to develop a method to activate other window from the cmd.exe
one using just System-Defined messages. I did several tests using
diverse combinations of WM_ACTIVATE, WM_CANCELMODE, WM_ENABLE,
WM_ACTIVATEAPP, WM_SETFOCUS and WM_KILLFOCUS messages, with no
success. Fortunately, the items in the system menu of any window can
be selected from another window, and after a SC_RESTORE the restored
window remains active; this behavior makes possible to activate
Notepad and other windows from the cmd.exe one via a Minimize/Restore
procedure.
I think that using my SendMessage.exe utility you may test if you may send keys to your inactive window process or to activate it, so you may then translate such a method to your phyton code. For complete details on this matter, see this link.

Script runs fine in ISE, but not in Powershell Console

I wrote an extremely lengthy script that creates a form. The main purpose of it it to connect to vCenter servers, total up hosts/vms within different datacenters and also identify ESXi host versions. Running the script in ISE the form loads fine and when I click the Button to start the many various functions to update the fields, it runs. I have Foreach() fields throughout and added in a little StatusLabel to the bottom of the form to show me where in the script it is currently scanning.
Once all was done and working, I saved the PS1 file and moved it to a shared server to be run. When I run the Powershell console (as Admin) and point to the file, the Form loads ok. Once I click the button to begin generating the info, It just changes to (Not Responding) and grays out. I know it's working and if left there long enough it will return the info.
Why does the console window not function like the ISE? I want to be able to see the information and Status Label update/change as it goes through the script (just like I do in the ISE).
Appreciate the feedback. The script is several thousand lines long and would need to be scrubbed before I upload. Was hoping to just get some general info before doing that.
I updated to v4 and verified that my command window was running as STA using the command from Jan Chrbolka. Script runs properly now.
I was also facing the same issue.(Btw, I cannot upgrade Powershell to V4 right now since it is my company owned one.)
The Browse button that I incorporated in my form was not working when I am lauching it from Powershell command line. It went to Not Responding state when I click the browse button.
I took the advise from Jan ChrbolkaMay about the STA and MTA.
I checked for the threads related to that and changed the script execution format to the below one which fixed my issue.(adding the word -STA)
powershell -STA -File D:\PS\GUI.ps1
For checking the current state. Use the below query in Commandshell as well as ISE.

Interactive Perl programming in Sublime 3 (Ubuntu)

Practically all of the exercises in my introductory Perl book have so far required taking input, which is causing me some challenges with Sublime Text 3. I set up the custom build file from this post to run scripts directly and I've also installed REPL on top of that, but I'm still unable to provide input through the bottom console.
Is there a way to enable input for scripts built via Ctrl+B, preferably with the console messages getting a little less in the way? I'm currently stuck with having to fire up the terminal every time, which doesn't make for a particularly smooth learning experience.
This doesn't really help you with your Sublime issue, but you mention firing up a terminal every time isn't helping you learn - here's the way I do it when I'm either learning or rapidly prototyping: Simply setup a folder on your local machine, called sync or something. Create a similar folder on your terminal server.
Now use an app (I use WinSCP and use Keep Remote Directory Up To Date setting) to sync. Every time you press save in your text editor, the new script is automatically uploaded to your terminal server, you can now just alt+tab to your terminal and run the script. Works very well for me and enabled really easy rapid prototyping.

Making and Interfacing with Custom Services

I've been searching for this for awhile now, and I am not sure if I am just not using the correct search terms or if the answer is really that hard to find.
What I am trying to do is to create a new Windows service for a game server from a batch file, and then have a task run another batch file every 30 minutes or more that would run two commands on the game server's command line and do some file work.
Specifically, I am running a Minecraft server using Bukkit for a gaming community I help run, and I want to make sure that the thing is always up unless I specifically tell it to stop (like a service). Bukkit is run directly from a batch file and has it's own command line thing running on it.
I am told that you CAN run this type of thing as a service, but the command line will be hidden from view and/or interaction. This is the second part of my query. I have a handy little backup.bat file that copies all the world files and userdata files into a backup directory, 7zips it, and deletes the directory. The only thing is, is that Minecraft likes to always have the worlds' region files open and writing at all times, meaning that it could cause map corruption if I just run it straight off. To compensate, I need to run the command "save-off" on the server to disable the file hooks temporarily, run the backup, and as soon as it finishes, run "save-on" so that the game can continue without lost data.
What I would like to know about this second one is, is it possible to interface with the game service through a batch file, or do I need to create an application to do that? If the latter, how exactly does one go about doing that? I have moderate C++ knowledge (up through my second OO-C++ course in college), and can possibly learn another language if absolutely necessary.
So, in short, two questions:
1. Is it possible to, and how to run a BAT file as a Windows Service?
2. How to interface with said service via BAT files, and if not possible, what kind of application do I need to write (redirection to or writing a tutorial works for me).
Thank you in advance for any and all help!
Old question, user account doesn't seem active on SO anymore, but hey, if you stumble upon this because you have a similar problem:
Since we are speaking about a Bukkit Minecraft server, turn to the "Essentials" plugin for Bukkit.
It now includes a Backup function that does exactly what the OP asks for, namely stop the save so the files can be manipulated without corruption, launch a script, then starts again.
The script can be a backup one (examples provided in the linked page) but can be used to run any operation on the world's files.