powershellherestring

Task Scheduler Script with Auto-Delete


I am trying to get a script to self-delete after running, but I am having trouble figuring out the structure of the script. The script that I have works perfectly if I run it manually, but the issue is that I would then have to go back and manually remove the tasks that I've created.

I'm looking for some guidance on how to get this script to delete itself automatically after running (or +30 days).

Here is the current script in full:

$Trigger = New-ScheduledTaskTrigger -Once -At "01/11/2023 23:40:00"
$User = "domain\user"
$TaskName = $User,(Get-Date -Format "dd-MM-yyyy HH-mm-ss")
$command = @'
[System.Net.ServicePointManager]::SecurityProtocol = 
[System.Net.SecurityProtocolType]::Tls12
$userName = 'myemail@website.com'
$passwordText = Get-Content C:\Users\User\Secure.txt
$securePwd = $passwordText | ConvertTo-SecureString
$credObject = New-Object System.Management.Automation.PSCredential -ArgumentList 
$userName, $securePwd
connect-exchangeonline -Credential $credObject 
Remove-MailboxFolderPermission -Identity usersemail@website.com:\Calendar -User 
otherusersemail@website.com -Confirm:$false
$printConfig = (Get-ScheduledTask -TaskName Remove-Config).Triggers.StartBoundary
Write-Host Removed at $printConfig
'@
# Encode command to base-64
$commandBytes = [System.Text.Encoding]::Unicode.GetBytes( $command )
$commandBase64 = [Convert]::ToBase64String( $commandBytes )
$Action= New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-NoExit - 
EncodedCommand $commandBase64"
Register-ScheduledTask -TaskName "$TaskName" -Trigger $Trigger -User $User -Action 
$Action -RunLevel Highest –Force

If I could also have any advice on how to call a variable from outside the here-string. I cannot change the single quote to double quotes, as this creates an error with the authentication.


Solution

  • To remove the task upon completion of the script, just add Unregister-ScheduledTask as the last line of your $command = @' block.

    Unregister-ScheduledTask -TaskName 'Remove-Config' -Confirm:$false
    

    "or +30 days" - the only reliable way that comes to mind would be with a separate scheduled task that runs 30 days later that looks for/deletes the first task then itself.


    There are ways of passing arguments like Pass complex arguments to powershell script through encoded command but im not a fan - its unnecessarily complex IMO.

    A slight alternative is to use .ps1 files on the filesystem, its just easier. Include a Param block 1st line of the .ps1 file (possibly with default options, add validation rules etc) and then pass the script file and any other parameters as arguments to powershell.

    A simple demo - create a file c:\temp\argtest.ps1

    Param([String] $UserName = 'myemail@website.com')
    Start-Transcript -Path c:\temp\log-file.txt -Append
    write-Host "Logging in as $UserName";
    

    And then execute powershell and pass just the script file and it will use the default parameters in the param block:

    PS C:\Users\user> powershell.exe -file c:\temp\argtest.ps1
    
    Transcript started, output file is C:\temp\log-file.txt
    Logging in as myemail@website.com
    

    or overriding UserName variable from the command line:

    PS C:\temp> powershell.exe -file c:\temp\argtest.ps1 -UserName 'youremail@differentwebsite.com'
    
    Transcript started, output file is C:\temp\log-file.txt
    Logging in as youremail@differentwebsite.com
    

    You can apply this to New-ScheduledTaskAction so -Argument "-NoExit -EncodedCommand $commandBase64" would become -Argument "-file c:\temp\argtest.ps1 -UserName myuser@example.com


    Notes:

    Start-Transcript -Path C:\temp\log-file.txt inside the schedule task function is useful to catch the output of the script and write it to file.

    DONT put sensitive data like passwords as parameters to powershell - they will be visible in the process list until powershell exits.

    Have a read of this article about validation of parameters