PowerShell embedded in a batch script, AKA Polyglot script

Copper Contributor

Hey folks,

I've been tasked with migrating user profiles on workstations using the ForensIT utility.
This works wonderfully, however, I want to also run clean-up actions such as un-mapping network drives and deleting any shared printers for each user once they log in next.
Those actions need to be performed from the user context from my understanding, and we would want them performed only after the profile migration has occurred for that device, and only once per user.

My solution:

I've written a powershell script that will be called by the profile migration utility.
It will create a batch file in each user's startup directory.
That batch file then calls powershell and runs a base64 encoded scriptblock (encoded bc the PS script is multi-line and syntax was no fun) to create an immediately run scheduled task, which performs those actions and then deletes the batch file as well.
(much too complicated really)

I was able to successfully get the batch script to deploy to all user's start up folders. Where I've found trouble is the batch script does not work when I double click it, however, if I simply copy the contents into a CMD shell it runs flawlessly.

I'm open to other solutions that meet the requirements (run per user, post migration, can be called by the migration utility, deletes itself once finished) but I'm also curious why I cant get the resulting batch file to work but the code works in CMD shell.

Thanks folks!


$scriptblock = {
$taskAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument 'remove-item %appdata%\Microsoft\Windows\Start` Menu\Programs\Startup\RunOnce.bat';
$taskAction2 = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument 'Get-service > $home\desktop\file.txt';
$taskTrigger = New-ScheduledTaskTrigger -Once -At (get-date).AddSeconds(10);
$taskTrigger.EndBoundary = (get-date).AddSeconds(60).ToString('s');
$taskSetting = New-ScheduledTaskSettingsSet -StartWhenAvailable -DeleteExpiredTaskAfter 00:00:30;
$taskName = 'Profile Migration Cleanup';
$description = 'Deletes all mapped drives as well as any printers';
Register-ScheduledTask -TaskName $taskName -Action $taskAction,$taskAction2 -Trigger $taskTrigger -Settings $taskSetting -Description $description

$encoded = [convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($scriptblock))

$script = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand $encoded -executionpolicy bypass"

$profiles = get-childitem C:\Users | where name -notlike Public | select Name
Foreach ($profile in $profiles) {
$profile = $profile.name
$path = "C:\Users\$profile\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\RunOnce.bat"
$script > $path

0 Replies