Powershell from batch file not working as expected - powershell

Let me start with some background. I work in a school district with about 300 laptops using win 10 pro. We are getting ready for our annual standardized testing which uses a lockdown browser. For whatever reason, the company created a new lockdown browser that does not close MSEdge that is running in the background. If you start the lockdown browser as soon as you log in, MSEdge is not an issue.
The provided solution by the software company is to change the registry entries for the test then change it back after the test. That seems like way too much work to me.
My first choice was to use kiosk mode, but it seems it does not work on win 10 pro. The solution I am working on now is to create a user specifically for the testing and use scheduled task at logon with a command to log off at exit. The basic concept seems to work for this situation, as long as the Laptops are plugged in. I can not seem to get the
New-ScheduledTaskSettingsSet –AllowStartIfOnBatteries –DontStopIfGoingOnBatteries
to take effect. I suspect it has to do with the a missing argument, but I can not find any leads with Google searches.
I am using a batch file to call PowerShell and run the .PS1 file
.bat file
:: this Batch file which is run by double clicking in SMACS_IT account. calls powershell to
start the task_kiosk.ps1. Which starts the proccess of creating the scheduled task for the
user STAAR TEST to run TXSecureBrowser.
Powershell.exe -Command "& {Start-Process Powershell.exe -ArgumentList '-ExecutionPolicy
Bypass -File C:\1kiosk\task_kiosk_ps1.ps1' -Verb RunAs}"
.PS1 file
$User = "STAAR TEST"
$Description = "A task created to launch the txsecurebrowser using the kiosk_bat.bat file when
the user STAAR TEST logs in"
$taskName = "Launch TXSecureBrowser"
$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }
$action = New-ScheduledTaskAction -Execute 'C:\1kiosk\kiosk_bat.bat'
$trigger = New-ScheduledTaskTrigger -AtLogOn -User "STAAR TEST"
$settings = New-ScheduledTaskSettingsSet –AllowStartIfOnBatteries –DontStopIfGoingOnBatteries
if($taskExists) {
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
}
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName $taskName -Description
$Description -User $User
Set-ScheduledTask -TaskName $taskName -Settings $settings
Using this code I can log in as the test account and the task starts the staar test as long as the laptop is plugged in. The task does not work if laptop is not plugged in. However, If I enter the command manually in PowerShell running as administrator the task will work if the laptop is not plugged in. Which is what leads me to believe that the .bat file needs another argument.

It's been too many years since I worked with Task Scheduler, so I can't help you directly. But, I still have my working script from the time. We needed a webpage updated with a gate counter every couple of minutes and the script below is how I automated the configuring of the scheduled task.
Strip out everything you don't want, insert a few things you do want, and you should pretty much have it.
.CMD file
<# : BATCH Bootstrap for PowerShell
#ECHO OFF
SETLOCAL
PowerShell -executionpolicy remotesigned -Command "Invoke-Command -ScriptBlock ([scriptblock]::Create($([System.IO.File]::ReadAllText('%~f0')))) -ArgumentList ([string]'%*').split()"
ENDLOCAL
GOTO :EOF
#>
# https://blog.netnerds.net/2015/01/create-scheduled-task-or-scheduled-job-to-indefinitely-run-a-powershell-script-every-5-minutes/
# Change these three variables to whatever you want
$jobname = "Gate Count Web Updater"
$script = "C:\Users\Public\GateCountWebUpdater.cmd"
$repeat = (New-TimeSpan -Minutes 2)
# The script below will run as the specified user (you will be prompted for credentials)
# and is set to be elevated to use the highest privileges.
# In addition, the task will run every 5 minutes or however long specified in $repeat.
$action = New-ScheduledTaskAction –Execute $script
$duration = (New-TimeSpan -Days (365 * 20))
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval $repeat -RepetitionDuration $duration
$msg = "Enter the username and password that will run the task";
$credential = $Host.UI.PromptForCredential("Task username and password",$msg,"$env:userdomain\$env:username",$env:userdomain)
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd
Register-ScheduledTask -TaskName $jobname -Action $action -Trigger $trigger -RunLevel Highest -User $username -Password $password -Settings $settings

Related

Unable to create 2 machine environment variables and execute another command via a Scheduled Task

I would like to create 2 "machine" environment variables and also execute a command via a single Scheduled Task. The scheduled task should immediately run and delete itself. The scheduled task should be executing as the current logged-in desktop user.
Below are the 3 items I need to execute:
[Environment]::SetEnvironmentVariable('AppA', (Get-StartApps -Name 'PowerShell (Tools1)').AppID, 'Machine')
[Environment]::SetEnvironmentVariable('AppB', (Get-StartApps -Name 'PowerShell (Tools2)').AppID, 'Machine')
Export-StartLayout -path 'C:\temp\Orig.xml'
Note: I do NOT want to depend on an external script; which is why I have such a long line of code for $action
When I run the code below, almost always, none of the commands are executed. Very rarely, a single environment variable get's created. If it's impossible to do this reliably in a single task, I'm hoping someone could show me how to do this reliably in 3 separate tasks. It seems even if I do 3 separate tasks, the results are still inconsistent/unreliable.
Code:
$AppA = (Get-StartApps -Name 'Windows PowerShell ISE (x86)').AppID
$AppB = (Get-StartApps -Name 'Outlook').AppID
$action = New-ScheduledTaskAction -Execute "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -Argument "-noprofile -windowstyle hidden -command ( [Environment]::SetEnvironmentVariable('AppA', $AppA, 'Machine') ; [Environment]::SetEnvironmentVariable('AppB', $AppB, 'Machine') ; Export-StartLayout -path 'C:\temp\Orig.xml' )"
$trigger = New-ScheduledTaskTrigger -Once -At (get-date).AddSeconds(4); $trigger.EndBoundary = (get-date).AddSeconds(8).ToString('s')
$principal = New-ScheduledTaskPrincipal -UserId (Get-WmiObject -Class win32_computersystem).UserName -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DeleteExpiredTaskAfter 00:00:12
Register-ScheduledTask -TaskName "2 envvars and Export-StartLayout" -Action $action -Trigger $trigger -Principal $principal -Settings $settings

Powershell script scheduled task output to log file

I have Powershell script with some Write-Host but I want to use it as scheduled task.
I added it as scheduled task with this:
$action = New-ScheduledTaskAction -Execute "$pshome\powershell.exe -WindowStyle Hidden" -Argument "-File $FilePath"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval $repeat
Register-ScheduledTask -TaskName $Name -Trigger $trigger -RunLevel Highest -Action $action
Can I make it write to log file? Is it possible to make it write to file at the same location as the Powershell script?
There were 2 problems with the script and the 1st was my main problem:
if it is not signed default behavior is to be sckipped by the Task Scheduler (or at least I didn't saw an error in the Event Viewer).
I had to use Write-Output
Check if the script is signed with Get-AuthenticodeSignature. Here you are going to receive SignatureStatus as string:
$isSigned = Get-AuthenticodeSignature -FilePath $FilePath | select -ExpandProperty Status
If it is not signed, you can enable the execution of it by adding -ExecutionPolicy Bypass like it is described in this spiceworks how-to. Do this for your own scripts, because of security !
For the writing part I used Write-Output and Out-File:
(
...
Write-Output "some text here"
...
) | Out-File -FilePath "C:\somepath\log.log

PowerShell scheduled task: opens PowerShell and script to be run but doesn't execute script

$Trigger = New-ScheduledTaskTrigger -AtLogOn
$User = "Administrator"
$Action = New-ScheduledTask -Execute "PowerShell_ISE.exe" -Argument "C:\Payload\XML_Read.ps1"
Register-ScheduledTask -TaskName "StartupScript_PS" -Trigger $Trigger -User $User -Action $Action -RunLevel Highest -Force
This is my code which creates a scheduled task and runs fine upon logon. the problem is when it logs on it opens PowerShell and the XML_Read file but I have to manually click run for the XML file to be read etc. Is there a way I can modify my code to do this for me? thanks in anticipation.
You can't execute scripts automatically with the ISE. Instead of PowerShell_ISE.exe, use PowerShell.exe.

Register scheduled task with New-ScheduledTaskTrigger to trigger on event ID

Register-ScheduledTask with New-ScheduledTaskTrigger on a Windows event ID
Hello Stack-overflow users. Neither MSDN nor Google yields results...
I configured a couple of scheduled tasks via a Powershell script. The scheduled tasks are set to run at certain times.
This all works fine. But I need to configure another scheduled task which run when a certain event ID is logged in the Windows event logger.
I can set this up manually of course but I want it as part of my automated script.
this is the code I have so far for the scheduled tasks, I need to replace the $Trigger= New-ScheduledTaskTrigger -At 4:00am -Daily section:
Copy-Item "\\networkDrive\Backups\scripts\Reset-Sessions.ps1" "c:\scripts\Reset-Sessions.ps1"
$Trigger= New-ScheduledTaskTrigger -At 4:00am -Daily
$User= 'Nt Authority\System'
$Action= New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "-executionpolicy bypass -File c:\scripts\Reset-Sessions.ps1"
Register-ScheduledTask -TaskName "Reset-Sessions" -Trigger $Trigger -User $User -Action $Action -RunLevel Highest -Force
I have changed some of the directory and file names for online purposes.
I would appreciate it if somebody could steer me into the right direction or assist with an example.
I would prefer to only change the $Trigger portion and not re-write the whole script but I would understand if it is not possible.
I use Powershell version 5.1.
With this answer as a base and some additional help I was able to construct this script
$taskname="Reset-Sessions"
# delete existing task if it exists
Get-ScheduledTask -TaskName $taskname -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false
# get target script based on current script root
$scriptPath=[System.IO.Path]::Combine($PSScriptRoot, "Reset-Sessions.ps1")
# create list of triggers, and add logon trigger
$triggers = #()
$triggers += New-ScheduledTaskTrigger -AtLogOn
# create TaskEventTrigger, use your own value in Subscription
$CIMTriggerClass = Get-CimClass -ClassName MSFT_TaskEventTrigger -Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskEventTrigger
$trigger = New-CimInstance -CimClass $CIMTriggerClass -ClientOnly
$trigger.Subscription =
#"
<QueryList><Query Id="0" Path="Microsoft-Windows-NetworkProfile/Operational"><Select Path="Microsoft-Windows-NetworkProfile/Operational">*[System[(EventID=4004)]]</Select></Query></QueryList>
"#
$trigger.Enabled = $True
$triggers += $trigger
# create task
$User='Nt Authority\System'
$Action=New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "-ExecutionPolicy bypass -File $scriptPath"
Register-ScheduledTask -TaskName $taskname -Trigger $triggers -User $User -Action $Action -RunLevel Highest -Force
The main magic is to use Get-CimClass to get the correct instance, and then populate Subscription from Get-ScheduledTask "Tmp" | Select -ExpandProperty Triggers
Step1:
Go to eventvwr, then create a new scheduled task based on an eventid.
Step2:
Open powershell, then show the scheduled task and see the the way how to was written.
Step3:
Attached and test it in your scrip.
I created a temporary Get-ScheduledTask and run the below line : all what you have to do is to replace the Subscription to meet your requirement.
$A = (Get-ScheduledTask "Tmp" | select -ExpandProperty Triggers)
Here is another method I used in the end to solve the problem:
If you are trying to do this on a Windows Server prior to Server 2012 then you probably don't have the Get-ScheduledTask and New-ScheduledTaskTrigger and the Register-ScheduledTask modules on your Windows system. That means the script in my original question and the accepted answer won't work.
A workaround is to create the desired scheduled task manually and then export it to a xml file. You can edit this file if you like, it is normal plain text xml.
Then have your script and the xml file in the same directory.
Change your script to be compatible with the older version of Powershell to import the xml file.
schtasks /create /tn "Reset-Sessions" /xml "c:\scripts\Reset-Sessions.xml"
Your new scheduled task should now be registered and active.

New-ScheduledTaskSettingsSet Expire task

I'm currently attempting to create a Powershell script that the overall goal will create a scheduled task on my VM which will reboot remote computers at certain times. The issue I'm currently having is trying to set the task to expire, and delete once it has been completed.
One point of confusion is there seems to be a disparity between the type of variable the cmdlet wants, and how an existing one is shown in the system. So as an example I have a dummy task that:
-Runs once at 11:00PM on 3/16/2017 and expires at 11:30PM on 3/16/2017 in the Triggers tab
-Has the setting "If the task is not scheduled to run again, delete it after: Immediately" under settings.
If I look at the existing task using Get-ScheduledTask this is what the values come across as:
(Get-ScheduledTask -TaskName Test).Settings
If I do a Get-Member these values are strings
(Get-ScheduledTask -TaskName Test).Settings | Get-Member
Now part of my issue may entirely be that I'm using the wrong cmdlets to go about this (just started messing around with this yesterday).The basic script I'm using while testing this out is:
function Create-Task ($Computer,$Time)
{
$Task = New-ScheduledTaskAction -Execute 'cmd.exe'`
-Argument "/c `"Shutdown /m \\$Computer /r /t 0`""
$Trigger = New-ScheduledTaskTrigger -Once -At $Time
$Settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 'PT72H' -DeleteExpiredTaskAfter 'PT0S'
Register-ScheduledTask -Action $Task -Trigger $Trigger -TaskName "Test" -Description "Testing this out" -Settings $Settings
}
$Comp = "WIN7-0031B"
[datetime]$TriggerTime = '3/16/2017 11:00PM'
Create-Task -Computer $Comp -Time $TriggerTime
When I look at Get-Member for New-ScheduledTaskSettingsSet cmdlet it again says those values are strings
However, if I attempt to run the script as is it complains about them not being datetime variables:
"New-ScheduledTaskSettingsSet : Cannot process argument transformation on parameter 'ExecutionTimeLimit'. Cannot convert value "PT72H" to type "System.TimeSpan". Error: "String was not recognized as a valid TimeSpan.""
(I would post a screenshot but I just joined StackOverflow so don't have the reputation).
What I've so far attempted has been changing the $Settings variable to things such as:
$Settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 30).Minutes -DeleteExpiredTaskAfter (New-TimeSpan -Seconds 0).Seconds
and
$Settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 30).Minutes.ToString() -DeleteExpiredTaskAfter (New-TimeSpan -Seconds 0).Seconds.ToString()
In both scenarios it does not generate any error messages, but the setting just doesn't get created. I'm wondering if doing something like this requires creating the task without the setting, and then doing something like a
Get-ScheduledTask -TaskName 'Test' | Set-ScheduledTask <Some other code here>
type of method, but wasn't 100% sure about how to do this. I'm somewhat new to powershell and completely new to trying to create scheduled tasks through Powershell, and any help would be greatly appreciated! The version of Powershell is Version 5
Edit Comment: It looks like when I pasted my script to StackOverflow it is showing most of it as being within quotations and not sure why, but in my ISE it shows things properly.
Eventually was able to get this working. I found an additional StackOverflow post and an article that helped get me in the right direction:
Powershell v4. Create remote task scheduler task set to expire and delete
https://blogs.technet.microsoft.com/platformspfe/2015/10/26/configuring-advanced-scheduled-task-parameters-using-powershell/
The working script (at least as far as getting this specific aspect working) is:
function Create-Task ($Computer,$Time)
{
$ActionArgs = "/c `"Shutdown /m \\$Computer /r /t 0`""
$TaskAction = New-ScheduledTaskAction -Execute 'cmd.exe' -Argument $ActionArgs
$TaskUserName = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount
$TaskSettings = New-ScheduledTaskSettingsSet -Compatibility V1 -ExecutionTimeLimit (New-TimeSpan -Minutes 30) -DeleteExpiredTaskAfter (New-TimeSpan -Seconds 0)
$TaskTrigger = New-ScheduledTaskTrigger -Once -At $Time
$Task = New-ScheduledTask -Action $TaskAction -Trigger $TaskTrigger -Principal $TaskUserName -Settings $TaskSettings
Register-ScheduledTask -TaskName "Test" -InputObject $Task -Force
$RegisteredTask = Get-ScheduledTask -TaskName "Test"
$RegisteredTask.Triggers[0].EndBoundary = $Time.AddMinutes(30).ToString('s')
$RegisteredTask.Settings.DeleteExpiredTaskAfter = 'PT0S'
$RegisteredTask | Set-ScheduledTask -User "NT AUTHORITY\SYSTEM"
}
$Comp = "WIN7-0031B"
[datetime]$TriggerTime = '3/17/2017 11:00PM'
Create-Task -Computer $Comp -Time $TriggerTime
One thing I also noticed I was doing wrong from the onset is I was confusing ExecutionTimeLimit with the EndBoundary property.
Also for reference, if you try running this in ISE without running ISE as admin you will most likely get an Access Denied issue. I'm planning to basically have this script as a scheduled task that looks for a CSV file to create the other tasks and will be running it as system so it shouldn't be a problem. But just in case someone happens across this thread and runs into the issue