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