Powershell in a batch file running as a service issue - windows

disclosure
I'm a PHP/Linux developer that is having to get use to working in a Windows environment, so I very well my be missing something fundamental in the question. I've researched the heck out of this and can't seem to pinpoint a solution. Thanks for your help in advanced.
I have a batch file that calls a powershell script that doesn't work correctly when it is started by the window's task scheduler, but works perfectly when it is launched by hand.
Below is the Powershell script that the batch file is launching...
$WatchFolder = '\\networkshare\foldername'
$Filter = '*.csv'
$fsw = New-Object IO.FileSystemWatcher $WatchFolder, $Filter -Property #{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters] 'LastWrite'}
Register-ObjectEvent $fsw Changed -SourceIdentifier SAS_Poll_FileChanged -Action {
$WatchFolder = '\\networkshare\foldername'
$OutputFolder_one = '\\networkshare\outputFolder_One'
$OutputFolder_two = '\\networkshare\outputFolder_Two'
$name = $Event.SourceEventArgs.Name
$lock_file = $WatchFolder + '\.' + $name + '.lock'
$test = (Test-Path "$lock_file")
if ( $test ){
return
} else {
Set-ExecutionPolicy -Scope CurrentUser Bypass
Out-File -FilePath "$lock_file"
Start-Process powershell -ArgumentList ".\General\PollingProcess-alone.ps1 $WatchFolder $MainFrameFolder $SASFolder $name $lock_file" -NoNewWindow
}
}
I know the issue occurs at the following line...
Start-Process powershell -ArgumentList ".\General\PollingProcess-alone.ps1 $WatchFolder $MainFrameFolder $SASFolder $name $lock_file" -NoNewWindow
I know this b/c when the event is triggered ( when the script is launched via the task scheduler ), the lock file is created and then the process hangs.
I therefore think that the issue has something to do with path of second powershell script I'm calling, but I don't know how to fix it. I've tried using the full path of the second script, but haven't been able to make it work.
Just to give you some more context of the script, it is sort of important the the event process spins up a new powershell script b/c I need these scripts to run concurrently.

Pretty sure the problem is with your argument list, right now you are passing a single string with everything contained within it, change that to an array and things should work properly.
so convert
".\General\PollingProcess-alone.ps1 $WatchFolder $MainFrameFolder $SASFolder $name $lock_file"
to
".\General\PollingProcess-alone.ps1",$WatchFolder,$WatchFolder,etc..
give that a shot and let us know if it works for you, also want to say that your code is impressive for being relatively new to PowerShell so kudos lol.

Related

Scheduled Task succesfully completes but doesn't get past import-csv

I'm trying to run below code in an automated scheduled task.
Whether I run this task manually or automated it is not working. When the option 'Run only when user is logged in' is set I at least see a PowerShell window opening, and I do see the jobs getting started. However, when the PS window closes the jobs are not visible (not completed, failed, nothing).
The logging shows the script runs till the import-csv command. I have put the CSV in the C: map, and I run the automated task as the logged in user and on highest privilege.
Why doesn't it get past import-csv? When I run this script in i.e Powershell ISE it works like a charm.
Running program
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Arguments:
–NoProfile -ExecutionPolicy Unrestricted -File "C:\Users\usr\Desktop\Scripts\script.ps1"
Start-in:
C:\Users\usr\Desktop\Scripts
Write-Host "Starting script"
$maxItems = 8
$iplist = import-csv "C:\Create.csv.txt"
Write-Host "Opened $($iplist[0])"
For ($i=0; $i -le $maxItems; $i++) {
Write-Host $iplist[$i].DisplayName
Start-Job -ScriptBlock {
Param($displayName)
try{
Start-Transcript
Write-Host "Found and started a job for $($displayName)"
Stop-Transcript
}
Catch{
Write-Host "Something went wrong "
Stop-Transcript
}
} -ArgumentList $iplist[$i].DisplayName
}
UPDATE:
The PS window closed before it got to do anything. The answer in this page send me in the right direction. The full fix I used to get this working:
Task Scheduling and Powershell's Start-Job
First, to prevent the powershell window from closing, run add the following line to the bottom of the script:
Read-Host 'Press Any Key to exit'
Second, if you run into issues with params, try explicitly naming the param with a flag:
$iplist = Import-csv -LiteralPath "C:\Create.csv.txt"
Third, make sure that you explicitly declare the delimiter being used if different than a comma.

Running powershell script to perform automated webpage login from task schedular behaves differently from running the script manually

My university requires all computers to perform a web-based login in order to get-access to the internet, and claims that all users will log-off automatically in the mid-night (sounds strange, but it is true), so I am trying to write a powershell script (in Windows 10) to perform automatic login at mid-night.
My script is list here. It opens an IE process in the background (in a nonvisible way), fill in the username and password, login, and kills the IE process.
# If there are existing Internet Explorer processes, close it
$IE_Process = Get-Process iexplore -ErrorAction Ignore
if ($IE_Process) {
$IE_Close = Foreach-Object { $IE_Process.CloseMainWindow() }
}
Stop-Process -Name "iexplore" -ErrorAction Ignore
# Login Information
$url = "http://xxx.xxx.xxx.xxx/"
$username = "xxxxxxxx"
$password = "xxxxxxxx"
# Open an IE process
$ie = New-Object -com internetexplorer.application;
$ie.silent = $true
$ie.navigate($url);
while ($ie.Busy -eq $true)
{
Start-Sleep -s 1;
}
# The stupid webpage needs to submit twice
$ie.Document.getElementById("loginname").value = $username
$ie.Document.getElementByID("password").value = $password
$ie.Document.getElementById("button").Click()
Start-Sleep -s 1;
$ie.Document.getElementById("loginname").value = $username
$ie.Document.getElementByID("password").value = $password
$ie.Document.getElementById("button").Click()
# Close the IE process
$IE_Process = Get-Process iexplore -ErrorAction Ignore
if ($IE_Process) {
$IE_Close = Foreach-Object { $IE_Process.CloseMainWindow() }
}
Stop-Process -Name "iexplore" -ErrorAction Ignore
Remove-Variable -Name ie,username,password,url,IE_Process -ErrorAction Ignore
The script is saved as "login_IE.ps1". It may be poorly written as I am new to powershell, but it works. If I open an cmd window and execute the following command, I am logged in.
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -File C:\Users\MyName\Documents\Powershell\login_IE.ps1
However, if I create a scheduled task in windows task scheduler executing this script, it doesn't work. I fill the "Program/script:" as:
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe
and fill the "Add arguments (optional):" as:
-ExecutionPolicy RemoteSigned -File C:\Users\MyName\Documents\Powershell\login_IE.ps1
The scheduled task is run under my account (I am the only user of this computer).
If I run the scheduled task manually, in the task manager I can see two IE process opened in the "Background process", communicate with the internet, and then get killed, so I am pretty sure that the script has actually been executed. But I found I am not logged in since I don't have internet access, where could the problem be?
Any advice is really appreciated. Thanks in advance.
Similar type of issue I had, when trying to run the script directly from Powershell window it works as expected, but from the task scheduler or command line both not getting the desired results.
Commenting and adding lines like below in my script, help me to run the script from command line and task scheduler as well
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[Net.ServicePointManager]::SecurityProtocol =
[Net.SecurityProtocolType]::Tls12
Hope this helps anyone else.

Powershell Crash after couple of hours

I'm experiencing with weird case with my Powershell script.
I have written a script that's execute an .exe file
this exe runtime is about 3 hours but constantly crashing after 2 hors (1-2 minutes more or less)
I have break my head try to figure out why the process crashing
eventually I found that the .exe crashing because the powershell crashing.
Here is the process execution command:
$Proc = Start-Process -FilePath $ExePath -ArgumentList $Arguments -NoNewWindow -PassThru
$Proc | Wait-Process -Timeout 28800 -ea 0 -ev timeouted
After I realized this issue cased by the Powershell I have enabled windows powershell logging and find an error message "the pipeline has been stopped"
The script need perform more actions after the process ends and get its exit code, that's why I used the -PassThru flag.
I have tried to run it without using the PassThru flag or the Process-Wait command, the result stayed the same (the process crashed after 2 hours but there wasn't log with the message "The pipeline has been stopped")
Important points:
the .exe file is soured with try;catch blocks with logger but did not logged any thing when crashing- this is not a runtime error in the .exe file
When running the .exe independently from the command line its finish successfully after ~3 hours
The Powershell script run with Administrator privileges
The exe is not casing the crashing due to high CPU/Memory/Disk usage
I will follow up once I will have more updates.
Thanks for all the helpers.
Your help is much appreciated!
In my opinion the Start-Process cmdlet is good for quick things. But, it leaves a lot to be desired when trying to debug why an exe isn't behaving.
To work around this in your case it might be useful to use .Net objects to redirect and change certain things about your instantiation. I put an example function below that I've used when having trouble debugging exe runs.
function Start-Exe
{
param
( [string]$exePath, [string]$args1 )
$returnVal = $false
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $exePath
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $args1
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
$exitCode = $p.ExitCode
#OutputFile can be some log file, or just use write-host to pump to console
#$stdout | Add-Content $global:OutputFile
#$stderr | Add-Content $global:OutputFile
return $exitCode
}
You can try it without using Wait-Process and see if it is reproducible.
Start-Process with -Wait parameter .
or Create it in a Job without -Wait and wait for the Job using Wait-.Job cmdlet
I had the same symptom when trying to execute an 8 hour process, it would always die after 2 hours, you need to clear the powershell IdleTimeout.
This answer helped me

Powershell output doesn't log properly when called from Task Scheduler

I need to log my powershell output. My ps file is something like this:
#Set-ExecutionPolicy Unrestricted
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"
$date = (Get-Date).tostring("MMddyy HHmmss")
$filename = 'C:\apierror\logs\' + $date + '.txt'
Start-Transcript -path $filename -append
$python = "C:\Python34\python.exe"
$python_path = "C:\script.py"
cd (split-path $python_path)
& $python $python_path
Stop-Transcript
Now, when I run this file directly from powershell, the output is logged correctly. But when I try to run it from taskscheduler - only some portion of the console output is stored in the file.
Any ideas why that might be?
Using transcript only stored partial output for some reason. I ended up using logs directly into the python file as opposed to powershell. Seems to be working correctly.

Start a detached background process in PowerShell

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

Resources