Testing to see if a scheduled task exist in powershell - powershell

I can't figure out why the below code won't work:
Function createFirefoxTask() {
$schedule = new-object -com Schedule.Service
$schedule.connect()
$tasks = $schedule.getfolder("\").gettasks(0)
foreach ($task in ($tasks | select Name)) {
echo "TASK: $task.name"
if($task.equals("FirefoxMaint")) {
write-output "$task already exists"
break
}
}
}
createFirefoxTask
The output I get is this:
FirefoxMaint
TASK: #{Name=FirefoxMaint}.name
TASK: #{Name=Task1}.name
TASK: #{Name=Task2}.name
TASK: #{Name=Task3}.name
TASK: #{Name=Task4}.name
TASK: #{Name=Task5}.name
If I echo $task.name from the shell without going through the script, it properly displays the name.

In order to prevent errors with Get-ScheduledTask in case the task doesn't exist - you might want to consider doing :
$taskName = "FireFoxMaint"
$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }
if($taskExists) {
# Do whatever
} else {
# Do whatever
}

Try this one:
Get-ScheduledTask -TaskName "Task Name" -ErrorAction SilentlyContinue -OutVariable task
if (!$task) {
# task does not exist, otherwise $task contains the task object
}

When used in a double-quoted string, variable evaluation will stop at punctuation. You can use $() to denote a subexpression within a string, like this:
"TASK: $($task.name)"
PowerShell will then evaluate the expression inside the parentheses and expand the string with the outcome

If you are using v3.0, then you can do this using Get-ScheduledTask. Forexample,
$task = Get-ScheduledTask -TaskName "FirefoxMaint" -TaskPath \
Then, just need to check the value of $task.

You can use the following code to test to see if a scheduled task exists in PowerShell:
if(Get-ScheduledTask FirefoxMaint -ErrorAction Ignore) { #found } else { #not found}

Related

powershell if statements not giving predicted outcome

I'm new to coding trying to figure out powershell and confused at If statements.
Trying to get this code so it'll create the job scheduling to run on login but it won't create it on the initial first run. I want to add in an if statement at the end to run the command to check if it exists on a desktop as some end users I want to deploy this too will already have it. But I'm unsure where the error lies with the code and how to address or simplify the code?
Any help would be greatly appreciated
$PathTest = Test-Path -Path "C:\Users\public\desktop\Google.lnk"
$Google = {$ShortcutPath = "C:\users\public\desktop\Google.lnk"
$IconLocation = "C:\windows\System32\SHELL32.dll"
$IconArrayIndex = 150
$Shortcut = $Shell.CreateShortcut($ShortcutPath)
$Shortcut.TargetPath = "http://www.google.com"
$Shortcut.IconLocation = "$IconLocation, $IconArrayIndex"
$Shortcut.Save()
}
$Trigger = New-JobTrigger -AtLogOn -RandomDelay 00:00:30
Register-ScheduledJob -Trigger $Trigger -RunAs32 -ScriptBlock {$Google} -Name Google
If ($PathTest -is True) {
$PathTest
} Else {
$Google
}
You use a wrong if operator:
-is is used for checking types:
if ( $value -is [type] )
{
# do something
}
For a boolean check you can just use:
$condition = $true
if ( $condition ) # check for $true
{
Write-Output "The condition was true"
}
$condition = $false
if ( !$condition ) # check for $false
{
Write-Output "The condition was also true by inverting with not operator"
}
MS Docs PowerShell IF-Statement
The if statement is using wrong operator. -is is used to test object types, not logical equality which is -eq. In addition, the boolean true is $true

How to get results from Get-ScheduledTask into PowerShell variables

I have a PowerShell script that starts a task on a remote server. The task takes hours to run so I need to have a loop in my code to check the task every few minutes to see if it's still running before the script proceeds to the next step. I tried running the following:
$svc_cred = Get-Credential -Credential <DOMAIN>\<ServiceAccount>
$global:Remote_session = New-PSSession -ComputerName <Server> -Credential $svc_cred
Invoke-Command -Session $global:Remote_session -ScriptBlock {
$results = Get-ScheduledTask -TaskName "Export_users" -TaskPath "\"
Write-Output "Taskname: $results.TaskName"
Write-Output "State: $results.State"
}
But this produces the output:
Taskname: MSFT_ScheduledTask (TaskName = "Export_users", TaskPath = "\").TaskName
State: MSFT_ScheduledTask (TaskName = "Export_users", TaskPath = "\").State
My desired outpout is:
Taskname: Export_users
State: Running
How do I code this to allow access the script to check if State is equal to "Running"?
You can use the State property of a scheduled task on a while loop, like this:
Start-ScheduledTask -TaskName 'SomeTaskName'
while ((Get-ScheduledTask -TaskName 'SomeTaskName').State -ne 'Ready') {
##Wait a while
Start-Sleep -Seconds 10
}
The comment from Santiago Squarzon answered my question.
"Taskname: $($results.TaskName)" and "State: $($results.State)" or even simpler, $results | Select-Object TaskName, State –
Santiago Squarzon

PowerShell - Lambda Functions Not Executing

This lambda function executes as expected:
$WriteServerName = {
param($server)
Write-Host $server
}
$server = "servername"
$WriteServerName.invoke($server)
servername
However, using the same syntax, the following script prompts for credentials and then exits to the command line (running like this: .\ScriptName.ps1 -ConfigFile Chef.config), implying that the lambda functions aren't executing properly (for testing, each should just output the server name).
Why does the former lambda function return the server name, but the ones in the script don't?
Param(
$ConfigFile
)
Function Main {
#Pre-reqs: get credential, load config from file, and define lambda functions.
$jobs = #()
$Credential = Get-Credential
$Username = $Credential.username
$ConvertedPassword = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($ConvertedPassword)
$Config = Get-Content $ConfigFile -Raw | Out-String | Invoke-Expression
#Define lambda functions
$BootStrap = {
param($Server)
write-host $server
}
$RunChefClient = {
param($Server)
write-host $server
}
$SetEnvironment = {
param($Server)
write-host $server
}
#Create bootstrap job for each server and pass lambda functions to Scriptblock for execution.
if(($Username -ne $null) -and ($Password -ne $null))
{
ForEach($HashTable in $Config)
{
$Server = $HashTable.Server
$Roles = $HashTable.Roles
$Tags = $HashTable.Tags
$Environment = $HashTable.Environment
$ScriptBlock = {
param ($Server,$BootStrap,$RunChefClient,$SetEnvironment)
$BootStrap.invoke($Server)
$RunChefClient.invoke($Server)
$SetEnvironment.invoke($Server)
}
$Jobs += Start-Job -ScriptBlock $ScriptBlock -ArgumentList #($Server,$BootStrap,$RunChefClient,$SetEnvironment)
}
}
else {Write-Host "Username or password is missing, exiting..." -ForegroundColor Red; exit}
}
Main
Without testing, I am going to go ahead and say it's because you are putting your scriptblock executions in PowerShell Jobs and then not doing anything with them. When you start a job, it starts a new PowerShell instance and executes the code you give it along with the parameters you give it. Once it completes, the completed PSRemotingJob object sits there and does nothing until you actually do something with it.
In your code, all the jobs you start are assigned to the $Jobs variable. You can also get all your running jobs with Get-Job:
Get-Job -State Running
If you want to get any of the data returned from your jobs, you'll have to use Receive-Job
# Either
$Jobs | Receive-Job
# Or
Get-Job -State Running | Receive-Job

How to disable a clusted scheduled task using powershell

Need to disable a clusterschduled task in windows 2012, using following command
however it is not disabling clusterscheduled tasks.
get-ClusteredScheduledTask -disable
Disable-ScheduledTask -TaskName
The pipe | is causing the entire set of objects returned from get-ClusteredScheduledTasks to be passed to the Disable-ScheduledTask. The use of the -TaskName is causing an error in the Disable-ScheduledTask command, because the pipe tells it "apply this command to these objects," but you then immediately try to apply the command to a single task named "schTest 123". This article provides some deeper explanation on command piping.
A couple different ways to solve this, depending on what you're trying to do:
1) If your goal is to disable ALL tasks that are currently scheduled:
$tasks = get-ScheduledTasks | where { $_.State -eq "Ready" } # exclude any tasks that are already disabled so we don't accidentally re-enable them later
$tasks | Disable-ScheduledTask
# do your work
$tasks | Enable-ScheduledTask
OR
$tasks = get-ScheduledTasks | where { $_.State -eq "Ready" }
$tasks | foreach { Disable-ScheduledTask -TaskName $_.TaskName }
# do your work
$tasks | foreach { Enable-ScheduledTask -TaskName $_.TaskName }
These are functionally identical, but the first one is certainly semantically cleaner.
2) If your goal is to disable only a single task by name
Disable-ScheduledTask -TaskName $myTaskName
# do your work
Enable-ScheduledTask -TaskName $myTaskName
3) If you want to be certain a single task exists prior to disabling/enabling
$task = get-ClusteredScheduledTasks | where { $_.TaskName -eq $myTaskName }
if ( $task -eq $Null ) { throw ( "Could not find scheduled task " + $myTaskName ) }
Disable-ScheduledTask -TaskName $task.TaskName
# do work
Enable-ScheduledTask -TaskName $task.TaskName

Run parameters in a Powershell script from a batch file

I'm trying to specify parameters in a powershell script, from a batch file.
The script itself looks likes this:
Param(
[Parameter(Mandatory=$true,HelpMessage="Application switch")]
[string[]]$Apps,
[ValidateRange(3,9999)]
[int]$SwitchDelay = 30
$AppPids = #()
$Windows = Get-Process | ? { $_.MainWindowTitle -ne "" }
$Wsh = New-Object -COM Wscript.Shell
foreach ($App in $Apps) {
foreach ($Window in $Windows) {
if ($Window.MainWindowTitle -like $App) {
Write-Verbose "Vindusfilter ""$App"" found hit on ""$($Window.MainWindowTitle)"" med PID ""$($Window.Id)"""
$AppPids += $Window.Id
}
}
}
do {
foreach ($ID in $AppPIDS) {
# Hides text...
$Wsh.AppActivate($ID) | Out-Null
Start-Sleep -Seconds $SwitchDelay
Write-Verbose "Changed window to PID ""$ID"""
}
} while ($true)
And what I'm trying to do is to define in a batch file is something like:
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "C:\AppRotate.ps1" -Apps "*Chrome*", "Spotify*" -Switchdelay 5
pause
(Supposed to show error message here, need more reputation first...)
Error: "... PositionalParameterNotFound.Approtate.ps1"
I'm basically new to scripting, so any ideas?
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "C:\AppRotate.ps1" -Apps "*Chrome*","Spotify*" -Switchdelay 5
The problem was the space between the first, and second variable of parameter -Apps.
Should work now.