Invoke-Expression to Launch .ps1 scripts - powershell

I am trying to make a service that scans a folder. When it detects certain files it renames them and then creates variables for the rest of the script. This all works fine, but I am trying to find a way to run this script so that the subsequent windows that it launches are minimized. I've tried the below, but the 2 scripts still launch a window each that flashes on the screen.
I have tried converting the file into an EXE and a service but then it refuses to work. Hoping for a quick one-liner if anyone can help?
Set-Location -Path C:\scripts\ICVT
while ($true) {
invoke-expression 'cmd /c start powershell -WindowStyle Minimized -Command {.\file_checker.ps1}';
Start-Sleep 5
invoke-expression 'cmd /c start powershell -WindowStyle Minimized -Command {.\kill_checker.ps1}';
Start-Sleep 5
}

Sounds like you need to use Start-Job to run the script in the background. Simply replace the Invoke-Expression with Start-Job:
Set-Location -Path C:\scripts\ICVT
while ($true) {
Start-Job -FilePath '.\file_checker.ps1}';
Start-Sleep 5
Start-Job -FilePath '.\kill_checker.ps1}';
Start-Sleep 5
}
It will also accept script blocks as well. See about_jobs for more information on running and managing background jobs.

Related

Is there a way for powershell to get the output from a console app and save it in a text file? [duplicate]

I have a Java program which I would like to launch as a background process from a PowerShell script, similar to the way a daemon runs on Linux. The PowerShell script needs to do a couple of things:
Run the program as a separate and detached process in the background, meaning the parent window can be closed and the process keeps running.
Redirect the program's standard output and standard error to files.
Save the PID of the background process to a file so it can be terminated later by another script.
I have a shell script on Linux which starts the program like so:
$ java -jar MyProgram.jar >console.out 2>console.err &
I'm hoping to replicate the same behavior on Windows using a PowerShell script. I have tried using Start-Process with various combinations of options, as well as creating System.Diagnostics.ProcessStartInfo and System.Diagnostics.Process objects, but so far I am not having any luck. PowerShell starts the program as a background process, but the program abruptly terminates when the DOS window which started the PowerShell session is closed. I would like it to start in the background and be independent of the command window which started it.
The output redirection has also been troublesome, as it seems that the output and error streams can only be redirected in the process is being run in the same window (e.g., using -NoNewWindow).
Is this sort of thing possible in PowerShell?
Use jobs for this:
Start-Job -ScriptBlock {
& java -jar MyProgram.jar >console.out 2>console.err
}
Another option would be Start-Process:
Start-Process java -ArgumentList '-jar', 'MyProgram.jar' `
-RedirectStandardOutput '.\console.out' -RedirectStandardError '.\console.err'
Consider using the task scheduler for this. Define a task and set it without any triggers. That will allow you to simply "Run" (manually trigger) the task.
You can set up and/or trigger scheduled tasks using the ScheduledTasks powershell module, or you can use the GUI.
This is an old post but since I have it working fine thought it might help to share. Its the call to 'java' instead of 'javaw' that is likely your issue. Ran it out myself using my JEdit java program through powershell to launch it.
#Requires -Version 3.0
$MyDriveRoot = (Get-Location).Drive.Root
$JEditDir = $($mydriveroot + "jEdit") ;# Should be C:\jEdit or wherever you want. JEdit is a sub-directory.
$jEdit = $($JEditDir + "\jedit.jar" )
$jEditSettings = $($JEditDir + "\settings")
$JEditLogs = $($JEditDir + "\logs")
Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$JEditSettings"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
Which you can turn into a little function and then an alias to make it easy to launch in Powershell.
If ( ( Test-Path $jedit) ) {
Function Start-JEdit() {
Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$($mydriveroot + "jEdit\settings")"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
}
New-Alias -Name jedit -Force Start-JEdit -Description "Start JEdit programmers text editor"
}
Try this with PowerShell:
Start-Process cmd -Args /c,"java -jar MyProgram.jar" `
-WindowStyle Hidden -RSI console.out -RSE console.err
OR
Start-Process cmd -Args /c,"java -jar MyProgram.jar >console.out 2>console.err" `
-WindowStyle Hidden
This will start a detached cmd window that is hidden, and will redirect the std streams accordingly.
Old question, but since I had the same goal, I used answer from #use to acheive it.
So here is my code :)
$NAME_TASK = "myTask"
$NAME_TASKPATH = "\myPath\"
if ($args[0] -eq "-task") {
# Code to be run "detached" here...
Unregister-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Confirm:$False
Exit
}
$Task = (Get-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -ErrorAction 'SilentlyContinue')
if ($Task) {
Write-Host "ERR: Task already in progress"
Exit 1
}
$A = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy bypass -NoProfile -Command ""$PSCommandPath -task $args"""
Register-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Action $A | Start-ScheduledTask
The solution is to combine Start-Process with nohup:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-7.3#example-9-create-a-detached-process-on-linux
(Note: This is NOT for Windows.)

powershell script loop that runs two python files

I would like to use powershell script in windows 10 that calls a python file, waits for completion, then calls another, waits for completion and loops this forever.
I know how to run one in a loop but know nothing of powershell scripts.
I am however fimaliar with Dos batch files and loops.
something like this:
while ($true)
{
start-Process -wait .\python1.py
start-Process -wait .\python2.py
}
This command does what I want with one file from powershell prompt
while ($true) {start-Process -wait .\python1.py}
while ($true) { start-Process -wait .\python1.py ; start-Process -wait .\python2.py }
Thanks Bill!

How can I run powershell in the background if I want execution policy Bypass?

I have this batch file which runs the powershell script.
I want to run it the background but if I run with "windowstyle hidden" still visible.
powershell -ExecutionPolicy ByPass -windowstyle hidden -File "C:\script.ps1"
You can run, e.g. long running scripts, as a jobs.
To start it you run
$job = Start-Job -ScriptBlock {Get-Process}
this will start the Get-Process cmdlet in the background. The script can be also some custom made script or a longer script, it doesn't need to be a one-liner.
You can check its status by running
$job | Get-Job
and to receive the output you run
$job | Receive-Job
just note that once the data is received, it's lost. You can only receive it once, after that it's up to you to save it in a variable or later processing.
Finally to remove the job from the queue you run
$job | Remove-Job
I use the following function:
function bg() {
Start-Process `
-WorkingDirectory (Get-Location) `
-NoNewWindow `
-FilePath "powershell" `
-ArgumentList "-NoProfile -command `"$args`" "
}
It starts a new powershell instance which is executed in background and allows the usage of cmdlets.
You call it like:
bg "Start-Sleep 2; get-location; write 'done' "

Calling a powershell script from InstallShield project

I'm having a weird problem.
I have an InstallShield project (which creates setup.exe) that contains a custom action item - calling a powershell script.
All the script does is to install 3 adobe reader updates (1 exe file and 2 msp files) on top of the already installed Adobe Reader 11.0.0.
When I'm calling the script my self - it works fine.
However, after the setup.exe finishes, it seems like only one update (the exe file) was really installed (the adobe reader version after the install is 11.00.10 which is the result of running only the exe file..).
All 3 adobe updates sit in the same folder and the powershell script first sets it location to this folder.
When running the updates manually after the installation - it also works fine and updates it to 10.00.22 (what it should be).
Any ideas why is this happening?
Here's my powershell script:
Set-Location "C:\myProject\adobeUpdates"
Start-Process .\AdbeRdr11010_en_US.exe -ArgumentList '/q /norestart /sPB /rs /msi' -WindowStyle hidden -Wait
ping 1.1.1.1 -n 1 -w 10000 # Tried to add a delay but wasn't helpful
Start-Process -FilePath “AdbeRdrUpd11021.msp” -ArgumentList '/qn' -Wait
Start-Process -FilePath “AdbeRdrUpd11022_incr.msp” -ArgumentList '/qn' -Wait
Thank you very much
Solved it, this is the working script:
Set-Location "C:\myProject\adobeUpdates"
Start-Process .\AdbeRdr11010_en_US.exe -ArgumentList '/q /norestart /sPB /rs /msi' -WindowStyle hidden -Wait
ping 1.1.1.1 -n 1 -w 10000
Start-Process .\AdbeRdrUpd11021.msp -ArgumentList '/qn' -Wait
Start-Process .\AdbeRdrUpd11022_incr.msp -ArgumentList '/qn' -Wait
I'm not sure what is the different and would love someone to explain but anyway it works just fine now.

Invoke-Expression Not Running Command

I am pulling in a text file that was previously created that simply lists the KB numbers for all currently installed Windows Updates. I am trying to pull this file in and call wusa.exe and pass it the KB number to perform an uninstallation.
$a = Get-Content c:\hotfixid.txt
foreach ($kb in $a) {
$command = 'cmd /c wusa.exe /uninstall /kb:' + $kb.Trim().Substring(2) + ' /quiet /norestart'
#Write-Host $command
Write-Host "Currently uninstalling $kb"
Invoke-Expression -Command:$command
}
If I use
Write-Host $command
and copy that directly to a run dialog box in Windows, it completes successfully.
What happens when I run it in a PowerShell script is that it only outputs the Write-Host portions one after the other in about 2 seconds. I do not see any command windows opening and I don't see it actually DOING anything. I am running the PowerShell script 'As Administrator' with an unrestricted execution policy. I have also tried adding 'runas' to the $command to call the CMD window each time with administrative privileges and it made no difference. Calling it via Invoke-Command as well makes no difference.
PowerShell can run most commands directly w/o too much trouble.
Using Invoke-Expression just complicates matters, as does Invoke-Command or Start-Process, because you need to get the quoting right, and pass the arguments in a slightly unnatural way.
You can even skip running cmd.exe most of the time.
Try the following:
wusa.exe /uninstall "/kb:$($kb.Trim().Substring(2))" /quiet /norestart