Initializing, Formatting and Assigning Drive Letters remotely, no WinRM

I am working with a company on a larger script to automate the build and deploy of Windows Servers in a VMWare environment. The script is working, and now I am working on enhancements. One of the biggest asks is for the script to automatically configure any additional drives added during the build, to cut down on the need for more than a single template per OS. The base build has a C drive the requester cannot modify, as well as a D drive that is 10GB but can be increased as needed. The D drive is where all applications are installed. Additionally, depending on the server function, the requester can add up to 3 additional drives (webserver or sql logs, etc.). They would like all of this configured automatically. As an additional caveat, due to the company doing government work, they have disabled powershell remoting altogether (nothing like tying my hands and then telling me to make shadow puppets).

The basic workflow for a SQL server would be something like this (pseudo):

    foreach($a in 2..5) {
       Initialize-Disk -Number $a -PartitionStyle GPT
       $sDrive = New-Partition -DiskNumber $a -AssignDriveLetter -UseMaximumSize
       Format-Volume -DriveLetter $sDrive.DriveLetter -FileSystem NTFS
       Set-Volume -DriveLetter $sDrive.DriveLetter -NewFileSystemLabel $description
       Set-Partition -DriveLetter $sDrive.DriveLetter -NewDriveLetter $newLetter
    }

This works well inside the guest OS, although I have to run PS as Admin. I found, to my surprise, I can to everything except changing the drive letter in the last line without prompting UAC. I first tried through VMWare’s Invoke-VMScript, but get errors that it cannot create a CIM session; basically the same thing, it is trying to launch UAC.

In the end, I hit upon Invoke-WMIMethod Which is not blocked. It won’t allow me to do a For loop, but I can do something like this:

$sText = @"
Initialize-Disk -Number 2 -PartitionStyle GPT
New-Partition -DiskNumber 2 -UseMaximumSize
Get-Partition -DiskNumber 2 | Format-Volume -FileSystem NTFS -NewFileSystemLabel "SQL"
Get-Partition -DiskNumber 2 | Set-Partition -NewDriveLetter K

Initialize-Disk -Number 3 -PartitionStyle GPT
New-Partition -DiskNumber 3 -UseMaximumSize
Get-Partition -DiskNumber 3 | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Logs"
Get-Partition -DiskNumber 3 | Set-Partition -NewDriveLetter J

Initialize-Disk -Number 4 -PartitionStyle GPT
New-Partition -DiskNumber 4 -UseMaximumSize
Get-Partition -DiskNumber 4 | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Backup"
Get-Partition -DiskNumber 4 | Set-Partition -NewDriveLetter M

Initialize-Disk -Number 5 -PartitionStyle GPT
New-Partition -DiskNumber 5 -UseMaximumSize
Get-Partition -DiskNumber 5 | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Scratch"
Get-Partition -DiskNumber 5 | Set-Partition -NewDriveLetter T
"@

$creds = Get-Credential

Invoke-wmiMethod -computername $VM `
                 -class win32_process `
                 -name create `
                 -argumentlist “powershell.exe -command $($sText)” `
                 -credential $creds

while ((Get-Process -Name "powershell" -ComputerName $VM -ErrorAction SilentlyContinue).Count -gt 0) {
   Start-Sleep 1
}

I found that if I specify -AssignDriveLetter when creating the partition, whether I specified the drive letter or not, would cause a similar error. But if I did not assign a letter, and then assign it in the last line, it works. Unfortunately, it only assigns the drive letter ~50% of the time. The initialization works every time, as well as the formats. Only the drive letters fail; sometimes the first two, sometimes 1 and 3, sometimes all, sometimes none. I have tried every way I can think of: adding sleeps between each drive configuration, sleeps between each step, doing all the initializations first, then sleep, then format, sleep, then drive letters, doing one drive then disconnecting and reconnecting for the next drive, etc. I am just at a loss on how to get any consistency, or even what is causing it to fail - I get no errors, no event viewer logs, nothing I can track down. Just wondering if anyone has experience with this method, and how I might go about troubleshooting, or what I might try.

In the end, I resolved by setting the drive letter assignment block into a 3x loop. It gets two of the four drives the first loop, then one of the two left on the second, and the last one on the last. Not elegant, but it works.