Good afternoon,
I am very new to Powershell and am trying to achieve the following:
Loop through a folder directory
Set the folder name as a variable
Create a Task
Pass the variable (declared in Step 2) as the required parameter for the -File being called in the Task Action
Get-ChildItem -Path C:\Users\Paul\Documents\RSYNC -Directory -Recurse |ForEach-Object {
$FolderName = $_.name
$taskName = 'My Powershell Task_' + $FolderName
# Create Action
$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-File "C:\Users\Paul\Documents\RSYNC\Get-LatestAppLog.ps1" -name "$FolderName"'
# Create Trigger
$Trigger = New-ScheduledTaskTrigger -Daily -At 12:35am
# Create Settings
$Settings = New-ScheduledTaskSettingsSet
# Create Task
$Task = New-ScheduledTask -Action $Action -Trigger $Trigger -Settings $Settings
# Register Task
Register-ScheduledTask -TaskName $taskName -InputObject $Task -User 'username' -Password 'password'
}
The tasks are created as desired, however, the problem is that inside the $Action step, instead of passing the folder name inside the $FolderName variable, it is simply passing $FolderName as a string (I hope that makes sense).
How can I correctly pass the folder name to the PowerShell script being called?
Your immediate problem was to expect the reference to variable $FolderName to be expanded (interpolated) inside a verbatim PowerShell string literal, '...':
Only "..." strings (double-quoted) perform string interpolation in PowerShell: see this answer for an overview of PowerShell's expandable strings (interpolating strings) and this answer for an overview of PowerShell string literals in general.
While swapping the use of quotation marks - using "..." for the outer quoting and '...' for the embedded quoting in order to get interpolation may situationally work - depending on the target program or API - it does not work in the context of Task Scheduler.
For command lines in Task Scheduler - and generally on Windows from outside PowerShell - you must use "..." quoting for the embedded strings too, which therefore requires escaping " as `" ("" would work too).
The reason is that PowerShell doesn't treat ' characters as having syntactic function when its CLI is called from the outside, such as from Task Scheduler, cmd.exe, or the Windows Run dialog (WinKey-R). For instance, if the path passed to -File were 'C:\Users\Paul\Documents\RSYNC\Get-LatestAppLog.ps1', the ' chars. would be interpreted as part of the path.
Specifically:
$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument `
"-File `"C:\Users\Paul\Documents\RSYNC\Get-LatestAppLog.ps1`" -name `"$FolderName`""
Note that you could simplify the quoting with the use of an expandable here-string; the embedded " then do not require escaping:
$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument #"
-File "C:\Users\Paul\Documents\RSYNC\Get-LatestAppLog.ps1" -name "$FolderName"
"#
Thank you Theo and Abraham Zinala. Both suggested to swap the double and single quotes and that worked perfectly.
Related
I have a short Powershell script which backup desktop items to D drive
$now = [datetime]::now.ToString('yyyy-MM-dd')
$trigger=new-scheduledtasktrigger -daily -at("08:00am")
$action = new-scheduledtaskaction 'copy "C:\USERS\ADMIN\DESKTOP" "D:\$now" -recurse'
Register-scheduledtask -Action $action -Trigger $trigger -Taskname "dailybackup" -Description "Daily backup"
The code seems valid and scheduled is registered well in scheduler
Get-scheduledtask "dailybackup"
But the task havent executed once but dont know why
anyone knows the solution?
New-ScheduledTaskAction executes commands in the old CMD shell by default. The command you're running doesn't error out because COPY is an ancient CMD built-in. It doesn't actually have the ability to recurse though, so it's not what you want.
To run powershell commands, the task action should execute PowerShell.exe, then have the powershell commands themselves added as arguments like below.
It looks like you want to use the run time date as the folder name $now, so you'll need to re-calculate the date every time it runs,
I also suggest adding -Force to create the target directory as needed,
I'm using here-string formatting #' '# to make quotes and things simpler to handle:
$Action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument #'
-Command Copy-Item -Recurse -Force -Path 'C:\USERS\ADMIN\DESKTOP' -Destination "D:\$([datetime]::Now.ToString('yyyy-MM-dd'))"
'#
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
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
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.
I am trying to create a scheduled task using powershell.
able to create and execute the task properly
```
$servername ="myservername"
# Issue with the version, unable to pass. Splitting in the scheduler argument.
$version="sql server 2016"
$edition="enterprise"
$action = New-ScheduledTaskAction -Execute Powershell.exe -Argument "-File G:\ForAPI\MainFunctions_All.ps1 -Servername $servername -Version $version -Edition $edition"
$trigger = New-ScheduledTaskTrigger -Once -At 12:00PM
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "MSSQL" -Description "SQL Deployment"
```
I should get -version as "sql server 2016" instead of "sql"
You need to change the parameters as positional and make it in order like 1st servername ,then version followed by edition in the function where you are using it.
You should use single quotes for the parameters inside while the value is being held by them else you will observe partial record(exactly what you are getting now); Change the quotation like this below:
$action = New-ScheduledTaskAction -Execute "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -Argument "-ExecutionPolicy ByPass -File G:\ForAPI\MainFunctions_All.ps1 '$servername' '$version' '$edition'"
If the parameters are all positional then you can completely avoid the -Servername , -Version and -Edition unnecessarily.
This will do the trick for you. Hope it helps.