How can I launch this PowerShell script in a new hidden window - powershell

I am working on a Reboot Scheduling application to be used on simple remote machines. It has to be user friendly though so I have to have multiple scripts and tasks in the background. my main GUI script needs to launch a Secondary Script in a NEW hidden window so that the Main GUI Script can close.
the Secondary Script (Reboot.ps1) will run until the machine restarts if the user has a scheduled reboot pending.
The code below starts the Secondary Script hidden but as a sort of "child job", since this script can run "forever" it wont end thus leaving the Main GUI script frozen open until killed in task manager (not very user friendly I know..)
$program = Powershell.exe -windowstyle hidden -file "C:\Reboot.ps1"
$scriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("Invoke-Command {$program}")
Invoke-Command -NoNewScope -Scriptblock $scriptblock
So what I'm asking is if anyone knows how to start the Secondary Script in a new PowerShell window, instance, environment, anything that allows the Main GUI Script to close. Preferably, less intensive if possible. :) thank you!

Use Start-Process's own -WindowStyle Hidden parameter to launch your script hidden and asynchronously (Start-Process's default):
Start-Process -WindowStyle Hidden powershell.exe -Args '-File', 'C:\Reboot.ps1'

Your code looks really complicated for what you're trying to achieve, use Start-Process
Start-Process powershell.exe -ArgumentList '-windowstyle hidden -file "C:\Reboot.ps1"'

Related

Is it possible in Powershell to enter a value to a program via script?

I'm quite new to powershell. I would like to create a powershell script that starts automatically and writes sth into the window. It should also work with task scheduler. It seems possible to start a program by using Start-Process. For example I start a program and would like to enter a text. How can I do it while it being executable using the task scheduler when a user is not logged in?
I found wshell.SendKeys but it only works when the user is logged in. Any other ideas?
Thanks!
In a file test.ps1 save this.
$wshell = New-Object -ComObject wscript.shell
Start-Process Notepad
Start-Sleep -Seconds 3
$wshell.AppActivate('Notepad')
$wshell.SendKeys('Hello World')
In the task scheduler configure to your needs.
Program: "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
Arguments: -ExecutionPolicy Bypass -File test.ps1
Paths must be adjusted, try with absolute paths first. Be aware that the scheduled task must be somehow user interactive.

Launch PowerShell script into new window while passing variables

I've been using the site for a while, searching through the questions and answers, trying to map them to my scenario, but I'm either missing something, or what I'm looking to do isn't possible (at least the way I'm trying to do it), hence I'm hoping for a push in the right direction. Thanks in advance for reading.
I've been working on a fairly sizeable automation project. My main script performs a number of tasks, and generally works well, and reliably. At one stage of the script, I execute another PowerShell script, which was written by another team. I call the script as follows:
.\DeployMySQLProvider.ps1 -AzCredential $asdkCreds `
-VMLocalCredential $vmLocalAdminCreds `
-CloudAdminCredential $cloudAdminCreds
-PrivilegedEndpoint $ERCSip `
-DefaultSSLCertificatePassword $secureVMpwd -AcceptLicense
When I call it this way, from my main script, it works fine, however, this script uses and registers a DLL file during it's deployment, and locks it until the PowerShell window and session is closed. At the end of my main script, I have a cleanup phase, which can't complete it's job because of this locked DLL.
My thoughts therefore, were to launch the 2nd script into a new PowerShell window and session, either using Start-Process or Invoke-Expression, but I just can't seem to get either right. Most of the variables I'm passing through to the 2nd script aren't just strings, which is probably where I'm falling over. They are a mix of usernames and passwords (secure strings) along with $ERCSip which is a string.
Should I be looking at Start-Process / Invoke-Expression, or something else entirely? When I was testing with Start-Process, I had the following defined, but couldn't get the ArgumentList side working correcly for me (blank below):
Start-Process "$pshome\powershell.exe" -PassThru -Wait `
-Verb RunAs -ErrorAction Stop -ArgumentList ""
Any pointers in the right direction would be much appreciated.
Thanks!
I've used something similar to this in my scripting:
$scriptpath="c:\pathto\deploysqlProvider"
$a = "$scriptpath\DeployMySQLProvider.ps1 -AzCredential $asdkCreds `
-VMLocalCredential $vmLocalAdminCreds `
-CloudAdminCredential $cloudAdminCreds
-PrivilegedEndpoint $ERCSip ` "
-DefaultSSLCertificatePassword $secureVMpwd -AcceptLicense
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList $a -wait -PassThru ;
Not sure if you need it to runas admin or not (-verb runas).
I'd suggest you then look for the Powershell process and path. So that if you have to kill this separate process you can.

Run a PowerShell method from cmd and don't wait for its return

In cmd I'm trying to run Method1 which is in a PowerShell script, script1.
Method1 is a method that takes a few hours, and I simply want to fire and forget.
The following is working for me:
c:\temp> powershell
PS c:\temp> . .\script1.ps1;Method1
When I do the lines above, everything is working fine as long as I keep the CMD of PS opened. once I close the PS window, it kills Method1.
So actually I want that from cmd, in one line, to somehow make Method1 work without the dependency of the PowerShell window, maybe create a new process.. I am not really sure.
I've tried:
c:\temp> cmd /c powershell . .\script1.ps1;Method1
It is running for a few seconds, but when the cmd gets closed, then Method1 also terminates.
I also tried
c:\temp>cmd /c powershell -noexit "& { . .\script.ps1;Method1 }"
Again, once I do this, it is working. However, a PowerShell window is opened and if I close it then it terminates Method1.
From you help, I've tried:
c:\temp> cmd /c powershell start-process cmd /c powershell . .\script1.ps1;Method1
But I get an exception:
Start-Process : A positional parameter cannot be found that accepts
argument 'powershell'.
But still, I am not able to make it work.
Alternatively if you want a pure PowerShell solution (note this needs to be running as Admin):
Invoke-Command LocalHost -Scriptblock $script -InDisconnectedSession
The InDisconnectedSession switch runs it in a separate PowerShell session that will not be terminated when you close the PowerShell window. You can also use Get-PSSession and pass the session to Enter-PSSession to interact with it during or after execution. Remember in this state if you close the window it -will- kill it, so you'll want to use Exit-PSSession to keep it alive.
There is however a problem - you can't do any remoting tasks, at least not easily. This incurs the wrath of the "double hop" where you remote to one computer (your own in this case), then to another, and for security PowerShell refuses to pass any credentials to the second remoting session so it can't connect, even if you put the credentials in manually. If you do need to do remoting I recommend sticking with launching a hidden PowerShell process.
You can use PowerShell jobs for that, so just:
Start-Job -FilePath somepath
And add a method call at the end of the script, or pass in a Scriptblock like:
Start-Job -ScriptBlock {. .\path_to_ps1; Method1}
Or perhaps use the hackish:
start-process cmd -WindowStyle Hidden -ArgumentList "'/c powershell . .\script1.ps1;Method1'"
Actually, you can just launch PowerShell, without CMD, and I am not sure why I was using a cmd approach:
start-process powershell -WindowStyle Hidden -ArgumentList ". .\script1.ps1;Method1"
Easy answer ya'll; Just paste "start" command into your PS window (whether in a remote session or not) and it works fine:
Start C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -file 'driverletter:\path\yourpowershellscript.ps1'

Kill a separate powershell script from the main script

I'm using a Powershell script to perform some automated testing on a web application.
Part of this script runs a small, separate script which basically monitors the web app for pop ups and closes them if they appear. It is called during the main script like so:
Start-Process Powershell.exe -Argumentlist "-file C:\Users\Documents\Monitor.ps1"
At some point though I would like to close the monitor script, perform some commands, and then start the monitor script again.
Is there a way for me to kill the monitor script from the main, without closing the main script as well in the process?
You would want to save it to a variable:
$a = start-process notepad.exe -PassThru
$a.Id
10536
So you could later kill it.

How do I run a PowerShell script when the computer starts?

I have a PowerShell script that monitors an image folder. I need to find a way to automatically run this script after the computer starts.
I already tried the following methods, but I couldn't get it working.
Use msconfig and add the PowerShell script to startup, but I cannot find the PowerShell script on that list.
Create a shortcut and drop it to startup folder. No luck.
%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -File "C:\Doc\Files\FileMonitor.ps1"
or
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -File "C:\Doc\Files\FileMonitor.ps1"
Here's my PowerShell script:
$folder = "C:\\Doc\\Files"
$dest = "C:\\Doc\\Files\\images"
$filter = "*.jpg"
$fsw = new-object System.IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubDirectories=$false
NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
Start-Sleep -s 10
Move-Item -Path C:\Doc\Files\*.jpg C:\Doc\Files\images
}
I also tried to add a basic task using taskschd.msc. It is still not working.
Here's what I found, and maybe that will help to debug it.
If I open up a PowerShell window and run the script there, it works. But if I run it in a command prompt,
powershell.exe -File "C:\Doc\Files\FileMonitor.ps1"
It will not work. I am not sure it's a permission problem or something else.
BTW, I have PowerShell 3.0 installed, and if I type $host.version, it will show 3 there. But my powershell.exe seems like it is still v1.0.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
I finally got my PowerShell script to run automatically on every startup. You will need to create two files: the first is the Powershell script (e.g. script.ps1) and the second is a .cmd file that will contain commands that will run on the command prompt (e.g. startup.cmd).
The second file is what needs to be executed when the computer starts up, and simply copy-pasting the .ps1 to the startup folder won't work, because that doesn't actually execute the script - it only opens the file with Notepad. You need to execute the .cmd which itself will execute the .ps1 using PowerShell. Ok, enough babbling and on to the steps:
Create your .ps1 script and place it in a folder. I put it on my desktop for simplicity. The path would look something like this:
%USERPROFILE%\Desktop\script.ps1
Create a .cmd file and place it in
%AppData%\Microsoft\Windows\Start Menu\Programs\Startup\startup.cmd
Doing this will execute the cmd file every time on startup. Here is a link of how to create a .cmd file if you need help.
Open the .cmd file with a text editor and enter the following lines:
PowerShell -Command "Set-ExecutionPolicy Unrestricted" >> "%TEMP%\StartupLog.txt" 2>&1
PowerShell %USERPROFILE%\Desktop\script.ps1 >> "%TEMP%\StartupLog.txt" 2>&1
This will do two things:
Set the Execution Policy of your PowerShell to Unrestricted. This is needed to run scripts or else PowerShell will not do it.
Use PowerShell to execute the .ps1 script found in the path specified.
This code is specifically for PowerShell v1.0. If you're running PowerShell v2.0 it might be a little different. In any case, check this source for the .cmd code.
Save the .cmd file
Now that you have your .ps1 and .cmd files in their respective paths and with the script for each, you are all set.
You could set it up as a Scheduled Task, and set the Task Trigger for "At Startup"
What I do is create a shortcut that I place in shell:startup.
The shortcut has the following:
Target: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "C:\scripts\script.ps1"
(replacing scripts\scripts.ps1 with what you need)
Start In: C:\scripts
(replacing scripts with folder which has your script)
You could create a Scheduler Task that runs automatically on the start, even when the user is not logged in:
schtasks /create /tn "FileMonitor" /sc onstart /delay 0000:30 /rl highest /ru system /tr "powershell.exe -file C:\Doc\Files\FileMonitor.ps1"
Run this command once from a PowerShell as Admin and it will create a schedule task for you. You can list the task like this:
schtasks /Query /TN "FileMonitor" /V /FO List
or delete it
schtasks /Delete /TN "FileMonitor"
This is really just an expansion on #mjolinor simple answer [Use Task Scheduler].
I knew "Task Scheduler" was the correct way, but it took a bit of effort to get it running the way I wanted and thought I'd post my finding for others.
Issues including:
Redirecting output to logs
Hiding the PowerShell window
Note: You must have permission to run script see ExecutionPolicy
Then in Task Scheduler, the most important/tricky part is the Action
It should be Start a Program
Program/Script:
powershell
Add arguments (optional) :
-windowstyle hidden -command full\path\script.ps1 >> "%TEMP%\StartupLog.txt" 2>&1
Note:
If you see -File on the internet, it will work, but understand nothing can be after -File except the File Path, IE: The redirect is taken to be part of the file path and it fails, you must use -command in conjunction with redirect, but you can prepend additional commands/arguments such as -windowstyle hidden to not show PowerShell window.
I had to adjust all Write-Host to Write-Output in my script as well.
Try this: create a shortcut in startup folder and input
PowerShell "& 'PathToFile\script.ps1'"
This is the easiest way.
Prerequisite:
1. Start powershell with the "Run as Administrator" option
2. Enable running unsigned scripts with:
set-executionpolicy remotesigned
3. prepare your powershell script and know its path:
$path = "C:\Users\myname\myscript.ps1"
Steps:
1. setup a trigger, see also New-JobTrigger (PSScheduledJob) - PowerShell | Microsoft Docs
$trigger = New-JobTrigger -AtStartup -RandomDelay 00:00:30
2. register a scheduled job, see also Register-ScheduledJob (PSScheduledJob) - PowerShell | Microsoft Docs
Register-ScheduledJob -Trigger $trigger -FilePath $path -Name MyScheduledJob
you can check it with Get-ScheduledJob -Name MyScheduledJob
3. Reboot Windows (restart /r) and check the result with:
Get-Job -name MyScheduledJob
see also Get-Job (Microsoft.PowerShell.Core) - PowerShell | Microsoft Docs
References:
How to enable execution of PowerShell scripts? - Super User
Use PowerShell to Create Job that Runs at Startup | Scripting Blog
Copy ps1 into this folder, and create it if necessary. It will run at every start-up (before user logon occurs).
C:\Windows\System32\GroupPolicy\Machine\Scripts\Startup
Also it can be done through GPEDIT.msc if available on your OS build (lower level OS maybe not).
Be sure, whenever you want PowerShell to run automatically / in the background / non-interactive, it’s a good idea to specify the parameters
-ExecutionPolicy Bypass to PowerShell.exe
PowerShell.exe -ExecutionPolicy Bypass
I have a script that starts a file system watcher as well, but once the script window is closed the watcher dies. It will run all day if I start it from a powershell window and leave it open, but the minute I close it the script stops doing what it is supposed to.
You need to start the script and have it keep powershell open.
I tried numerous ways to do this, but the one that actually worked was from http://www.methos-it.com/blogs/keep-your-powershell-script-open-when-executed
param ( $Show )
if ( !$Show )
{
PowerShell -NoExit -File $MyInvocation.MyCommand.Path 1
return
}
Pasting that to the top of the script is what made it work.
I start the script from command line with
powershell.exe -noexit -command "& \path\to\script.ps1"
A relatively short path to specifying a Powershell script to execute at startup in Windows could be:
Click the Windows-button (Windows-button + r)
Enter this:
shell:startup
Create a new shortcut by rightclick and in context menu choose menu item: New=>Shortcut
Create a shortcut to your script, e.g:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "C:\Users\someuser\Documents\WindowsPowerShell\Scripts\somesscript.ps1"
Note the use of -NoProfile
In case you put a lot of initializing in your $profile file, it is inefficient to load this up to just run a Powershell script. The -NoProfile will skip loading your profile file and is smart to specify, if it is not necessary to run it before the Powershell script is to be executed.
Here you see such a shortcut created (.lnk file with a Powershell icon with shortcut glyph):
This worked for me. Created a Scheduled task with below details:
Trigger : At startup
Actions:
Program/script : powershell.exe
Arguments : -file
You can see scripts and more scheduled for startup inside Task Manager in the Startup tab. Here is how to add a new item to the scheduled startup items.
First, open up explorer to shell:startup location via start-button => run:
explorer shell:startup
Right click in that folder and in the context menu select a new shortcut. Enter the following:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile
-Command "C:\myfolder\somescript.ps1"
This will startup a Powershell script without starting up your $profile scripts for faster execution. This will make sure that the powershell script is started up.
The shell:startup folder is in:
$env:APPDATA\Microsoft\Windows
And then into the folder:
Start Menu\Programs\Startup
As usual, Microsoft makes things a bit cumbersome for us when a path contains spaces, so you have to put quotes around the full path or just hit tab inside Powershell to autocomplete in this case.
If you do not want to worry about execution policy, you can use the following and put into a batch script. I use this a lot when having techs at sites run my scripts since half the time they say script didnt work but really it's cause execution policy was undefined our restricted. This will run script even if execution policy would normally block a script to run.
If you want it to run at startup. Then you can place in either shell:startup for a single user or shell:common startup for all users who log into the PC.
cmd.exe /c Powershell.exe -ExecutionPolicy ByPass -File "c:\path\to\script.ps1"
Obviously, making a GPO is your best method if you have a domain and place in Scripts (Startup/Shutdown); under either Computer or User Configurations\Windows Settings\Scripts (Startup/Shutdown).
If you go that way make a directory called Startup or something under **
\\yourdomain.com\netlogon\
and put it there to reference in the GPO. This way you know the DC has rights to execute it. When you browse for the script on the DC you will find it under
C:\Windows\SYSVOL\domain\scripts\Startup\
since this is the local path of netlogon.
Execute PowerShell command below to run the PowerShell script .ps1 through the task scheduler at user login.
Register-ScheduledTask -TaskName "SOME TASKNAME" -Trigger (New-ScheduledTaskTrigger -AtLogon) -Action (New-ScheduledTaskAction -Execute "${Env:WinDir}\System32\WindowsPowerShell\v1.0\powershell.exe" -Argument "-WindowStyle Hidden -Command `"& 'C:\PATH\TO\FILE.ps1'`"") -RunLevel Highest -Force;
-AtLogOn - indicates that a trigger starts a task when a user logs on.
-AtStartup - indicates that a trigger starts a task when the system is started.
-WindowStyle Hidden - don't show PowerShell window at startup. Remove if not required.
-RunLevel Highest - run PowerShell as administrator. Remove if not required.
P.S.
If necessary execute PowerShell command below to enable PowerShell scripts execution.
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Unrestricted -Force;
Bypass - nothing is blocked and there are no warnings or prompts.
Unrestricted - loads all configuration files and runs all scripts. If you run an unsigned script that was downloaded from the internet, you're prompted for permission before it runs.
I 'm aware that people around here don't need a tool like this. But I think it will be useful especially for novice users. Auto start tool It is a Portable freeware which designed to simplify the process to automatically launch an App or script when you login to Windows. It offers 3 different options for autostart
Task Scheduler
Startup folder
Registry run key
The best part of the tool is supports powershell scripts (.Ps1) . this means that you can run a Powershell script automatically at system startup with all 3 methods.
Download
https://disk.yandex.com.tr/d/dFzyB2Fu4lC-Ww
Source:
https://www.portablefreeware.com/forums/viewtopic.php?f=4&t=25761
One thing I found. if you are using Write-Host within your PowerShell scripts, and are also using Task Scheduler (as shown in the posts above), you don't get all the output from the command line.
powershell.exe -command C:\scripts\script.ps1 >> "C:\scripts\logfile.log"
In my case, I was only seeing output from commands that ran successfully from the PowerShell script.
My conclusion so far is PowerShell uses Out-File to output to another command or in this case a log file.
So if you use *> instead of >> you get all the output from the CLI for your PowerShell script, and you can keep using Write-Host within your script.
powershell.exe -command C:\scripts\script.ps1 *> "C:\scripts\logfile.log"
https://lazyadmin.nl/powershell/output-to-file/
You can also run the script in the background, regardless of user login.
Within your task in Task Scheduler set "Run whether user is logged on or not", and then in the password prompt type your hostname\username then your password (In my case an account with Admin permissions).
I used Set-ExecutionPolicy RemoteSigned -Scope CurrentUser to get around the script execution problem. I still would have preferred to run it on a per-process basis though. A problem for another time.