Hi,
We are currently looking for something like this, but I can´t get this worklet to run.
Through Powershell, on my machine, it works, but through Automox it´s not working, and we can´t debug why.
Thanks
Sometimes I will drop in this line at the top of the script to get an idea of what is happening when the worklet runs. After the worklet runs I review output of C:\windows\temp\worklet.txt
Start-Transcript C:\Windows\Temp\worklet.txt
Another option is try and see what is not happening by evaluating the various parts the script accomplishes
- Does it create the directory C:\ProgramData\ToastNotify
- Does it create a file C:\ProgramData\ToastNotify\RunToastHidden.cmd
- Did these files “config-toast.xml, Hidden.vbs, New-ToastNotification.ps1, ToastHeroImageDefault.jpg, ToastLogoImageDefault.jpg” get copied under C:\ProgramData\ToastNotify
- Does a schedule task called ToastNotify exist
- Is there a history of the Scheduled Task running
- If the scheduled task is running, did any output get generated here C:\Users\%username%\AppData\Roaming\ToastNotficationScript\ for the currently logged in user...
Thanks for the ideas!
We’ll keep debugging and update here with our final output.
Hi Jack, after suggesting using this for reboots on another thread, I’ve been pondering what else to use it for.
The obvious one seems to be when you need a user to close an application before running an update. Looking at the Toast script, you can add functionality to invoke an install from SCCM, but would there be a way to trigger an Automox policy to run? Do you know if the locally installed agent for example could be triggered to run a particular policy?
Thanks!
Danny
I’d like to think it would be possible. To run an Automox policy one would need to know the Client ID and the Policy ID.
Here is sample code that would let you run a policy from Automox remotely. Assumes a few things:
- assets.csv is a payload containing every asset under columns: hostname,id (otherwise during runtime you would have to query all assets just to filter on the asset or have the id pre-staged on each client)
- PolicyID which you is in the URL of any policy you find in the console.
$assetid = (Import-Csv assets.csv | where-object hostname -eq $env:COMPUTERNAME).id
$policy = '123456'
$orgID = '12345'
$headers = @{ "Authorization" = "Bearer $apiKey" } # $apiKey being stored as secret in Automox
$url = "https://console.automox.com/api/policies/$policy/action?o=$orgID&action=remediateServer&serverId=$AssetId"
Invoke-WebRequest -Method POST -Uri $url -Headers $headers -UseBasicParsing
The next part, I’m going to assume will require a lot of trial and error to get just right.
In the script “New-ToastNotification.ps1” around line 1998, you might be able to just replace the code under the section “Running RunApplicationID function” with the code block above instead of having it call that function “Write-ApplicationIDRegistry”. I’m about 90% sure that would work. I’ve not tried it, but would think it possible.
Ultimately to solution this it requires time and a deep understanding of how this XML configuration file and “New-ToastNotification.ps1” script runs. Paying close attention to those action buttons and how that flow works.
On second thought… perhaps just code in the remediation necessary over trying to figure out Policy and Agent IDs. I mean, at this point a script is running to display all the content to the end user.
Hi Jack, thanks for this, I’ll see what I can do and will report back.
So just put the remediation script in “New-ToastNotification.ps1” rather than calling back to Automox (which I guess will report on success insomuch as the application will show as installed?)?
Of course, any third or fourth thoughts you have along the way would be greatly received as I’m flying by the seat of my pants!
The actions run during the New-ToastNotification.ps1 script runtime would not reflect in the Automox worklet activity log. Only exit codes from the code dropped in the remediation section of the worklet reflect in the activity log. Which makes a feedback loop for anything executed beyond that a bit harder.
To get a desired feedback I’d focus on the evaluation code in the worklet itself, which in a way can help us see successful or not in the console. Given you may be waiting for user input, the immediate evaluation run post remediation code is not likely to yield anything great. Will have to rely on the scan cadence (default is 24 hours) or manually do a re-scan of the agent.
You definitely have a pretty cool use case here. re-purposing this tool to act in a similar way as it already does with SCCM would likely close a lot of gaps I think all of us Automox customers would love to have. Complex workflows with on-demand end user interactions.
So, here’s my plan… it’ll end up with multiple policies but I’m ok with that!
Policy 1. - Uses your script to create the schedule task (I have it set to trigger 15 mins after it’s installed)
Policy 2. - Installs the relevant software
So Policy 1 kicks off the toast notification, which in turn runs the code you posted 4 posts above to run Policy 2 which does the standard eval and remediation - this way it all reports correctly, but the user has been able to close down their apps before installing.
Last thing standing in my way… Getting Toast to run a custom protocol and script to kick off Policy 2… anyone played with this and got it to do something bespoke?
Dig the strategy play here @IamDannyOConnor.
I’m thinking outload here without looking. I’m almost wondering is there a way to take advantage of the do while loop in PowerShell to achieve that desired outcome.
For example, a do-while loop that just waits for a file to show up with a built in timeout. That way you can say wait for this file to show up that indicates a user has interacted with the prompt, to now execute the code. Which could build a way between the Automox worklet and balloon tip pop-up, the script now 5 posts above , to play well together and avoid having two policies.
Oooooo, like your thinking!
K, the do-while loop works perfectly, as soon as I (manually) drop the test text file in it does it’s thang!
Just to get the Toast ‘Action’ button to instigate the file creation now, it’s being a bit stubborn for some reason.
Think I’ve cracked it. As soon as I’ve tided up the code I’ll start a new thread as I think it deserves it
when testing (or in general), modify the first line of the Schedule-ToastNotify function to set the time to just a few minutes from now…. If you leave it as suggested (12pm today), that may have passed resulting in never running the script or may be far off making testing tricky. Changing to the line below would run the task 2 minutes from when the worklet is doing its thing, which should be plenty of time… keep in mind that it will take an additional minute or so after this 2 minute delay til it pops up.
$TaskStartTime = iDateTime]::Now.AddMinutes(2)
Does anyone know if there is a way to set the maximum number of deferrals? it seems like its infinity to me.
Anyone?? Could really use some help.
I ended up modifying the powershell script. it is hard coded for 3 days.
function Get-DynamicDeadline() { Write-Log -Message "Running Get-DynamicDeadline function. Checking existing deadline in registry."
$RegistryPath = "HKCU:\Software\MyScript" $DeadlineName = "Deadline"
# Check if the registry path exists if (Test-Path $RegistryPath) { $ExistingDeadline = Get-ItemProperty -Path $RegistryPath -Name $DeadlineName -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $DeadlineName -ErrorAction SilentlyContinue }
# If the existing deadline is in the future, return it if ($ExistingDeadline -and $DateTime]::Parse($ExistingDeadline) -gt (Get-Date)) { Write-Log -Message "Existing deadline in registry is in the future: $ExistingDeadline" return nDateTime]::Parse($ExistingDeadline) }
# Calculate the new deadline date $Deadline = (Get-Date).AddDays(3) Write-Log -Message "Calculated new deadline date is: $Deadline"
# Convert deadline to universal time $DeadlineUTC = $Deadline.ToUniversalTime() Write-Log -Message "New deadline in UTC is: $DeadlineUTC"
# Save the new deadline to the registry if (-not (Test-Path $RegistryPath)) { New-Item -Path $RegistryPath -Force | Out-Null } Set-ItemProperty -Path $RegistryPath -Name $DeadlineName -Value $DeadlineUTC Write-Log -Message "New deadline date and time saved to registry at path: $RegistryPath"
# Return the new deadline return $DeadlineUTC }