This example uses PowerShell Universal Dashboard.
This example can be used to create virtual machines on a Hyper-V host. This dashboard assumes it's being run on the host in question. You could adjust the dashboard script to run on a remote host.
Start-PSUServer -Port 8080 -Configuration {New-PSUDashboard -Name 'Hyper-V' -BaseUrl '/' -Framework 'UniversalDashboard:Latest' -Content {$HostRam = Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB *0.97),0)-1}$HostName=hostname$SwitchList = @()Get-VMSwitch | Select-Object -ExpandProperty name | ForEach-Object {$SwitchList += $_}function Run-Checks{$VMHostInfo= Get-VMHost$BootISOTextBoxText = (Get-UDElement -Id 'VMBootISO')['value']$VHDRootTextBoxText = (Get-UDElement -Id 'VMVHDRoot')['value']$VMNameTextBoxText = (Get-UDElement -Id 'VMName')['value']$Generation = (Get-UDElement -Id 'VMGeneration')['value']$SwitchNameComboBoxText = (Get-UDElement -Id 'VMSwitch')['value']$RAMinGBTextBoxText = (Get-UDElement -Id 'VMRam')['value']$CPUCountTextBoxText = (Get-UDElement -Id 'VMCPU')['value'][int64]$VLANIDTextBoxText = (Get-UDElement -Id 'VMVLan')['value']#Paths and Gen Setsif ($BootISOTextBoxText -and $BootISOTextBoxText -ne "") {$ISOFilePathValid = test-path $BootISOTextBoxText}if ($VHDRootTextBoxText -and $VHDRootTextBoxText -ne "") {$VHDBootPathValid = test-path $VHDRootTextBoxText}if ($Generation -eq 'Gen1') { $VMGeneration = 1 } else { $VMGeneration = 2 }if ($VMNameTextBoxText.Length -ne 0) { $VMExists = Get-VM -name $VMNameTextBoxText -ErrorAction SilentlyContinue }if (-not (Test-Path $VMHostInfo.VirtualMachinePath) ) {Show-UDToast -Message "Default Virtual Machine path is not valid in HyperV Host Settings"}elseif (-not (Test-Path $VMHostInfo.VirtualHardDiskPath) ) {Show-UDToast -Message "Default Virtual Harddisk path is not valid in HyperV Host Settings"}elseif ($VMExists) {Show-UDToast -Message "VM with that name already exists"}elseif ($VMNameTextBoxText.Length -eq 0) {Show-UDToast -Message "Please Enter VM Name"}elseif ($SwitchNameComboBoxText -eq "Switch Name") {Show-UDToast -Message "Please Select a Switch Name"}elseif ($ISOFilePathValid -eq $False) {Show-UDToast -Message "ISO File path in invaild"}elseif ($VHDRootTextBoxText -eq "") {Show-UDToast -Message "VHD Root path is blank. Please enter a valid path"}elseif ($VHDBootPathValid -eq $False) {Show-UDToast -Message "VHD Root path in invaild"}elseif ($RAMinGBTextBoxText.Length -eq 0) {Show-UDToast -Message "Please Enter Ram Amount in GB"}elseif ([int64]$RAMinGBTextBoxText -lt 1) {Show-UDToast -Message "Please Enter Ram Amount of at least 1GB"}elseif ([int64]$RAMinGBTextBoxText -gt $HostRam) {Show-UDToast -Message "Please Enter Ram Amount of "+ $HostRam + "GB or bellow"}elseif ($CPUCountTextBoxText.Length -eq 0) {Show-UDToast -Message "Please Enter a CPU Count"}elseif ([int64]$CPUCountTextBoxText.Length -eq 0) {Show-UDToast -Message "Please Enter a CPU Count"}elseif ([int64]$CPUCountTextBoxText -lt 1) {Show-UDToast -Message "Please Enter a CPU Count of at least 1"}elseif ([int64]$CPUCountTextBoxText -gt 64) {Show-UDToast -Message "Please Enter a CPU Count of 64 or below"}elseif ([int64]$VLANIDTextBoxText -gt 999 -or [int64]$VLANIDTextBoxText -lt 1) {Show-UDToast -Message "Please Enter VLAN ID between 1 and 999."}else{(65..90) | ForEach-Object {$DriveLetter = [char]$_[int64]$value = (Get-UDElement -Id "Drive$DriveLetter")['value']if ($value -gt 65536){Show-UDToast -Message "For $DriveLetter Drive please Enter a Disk Size of 65536 GB or below"return $false}}Show-UDToast -Message "Looking Good Man ;)"return $true}return $false}function Create-VMs{Run-Checks$BootISOTextBoxText = (Get-UDElement -Id 'VMBootISO')['value']$VHDRootTextBoxText = (Get-UDElement -Id 'VMVHDRoot')['value']$VMNameTextBoxText = (Get-UDElement -Id 'VMName')['value']$Generation = (Get-UDElement -Id 'VMGeneration')['value'][int]$SwitchNameComboBoxIndex = (Get-UDElement -Id 'VMSwitch')['value']$SwitchNameComboBoxText = $SwitchList[$SwitchNameComboBoxIndex]Show-UDToast -message ((Get-UDElement -Id 'VMSwitch') | ConvertTo-Json)$RAMinGBTextBoxText = (Get-UDElement -Id 'VMRam')['value']$CPUCountTextBoxText = (Get-UDElement -Id 'VMCPU')['value']$VLANIDTextBoxText = (Get-UDElement -Id 'VMVLan')['value']if ($Generation -eq 'Gen1') { $VMGeneration = 1 } else { $VMGeneration = 2 }#Create VMtry{New-VM -Name $VMNameTextBoxText -MemoryStartupBytes ([int]$RAMinGBTextBoxText*1073741824) -SwitchName $SwitchNameComboBoxText -Generation $VMGeneration -ErrorAction Stop}catch{$VMCrateFailed=$TrueShow-UDToast -Message ("VM " + $VMNameTextBoxText + " Failed to Create :( $($_.Exception.Message)")}if (-Not($VMCrateFailed -eq $True)){(65..90) | ForEach-Object {$DriveLetter = [char]$_[int64]$value = (Get-UDElement -Id "Drive$DriveLetter")['value']if ($value -gt 0){$Path = $VHDRootTextBoxText+"\"+$VMNameTextBoxText+"\"+$VMNameTextBoxText+"-"+$value+".vhdx"if (-not (test-path $Path)){New-VHD -Path $Path -SizeBytes (Invoke-Expression ("$($Value)GB")) -Dynamic}else{$VHDPathExisted = $true}}}Get-VM $VMNameTextBoxText | Set-VMProcessor -Count $CPUCountTextBoxTextGet-VM $VMNameTextBoxText | set-VMNetworkAdapterVlan -Access -vlanId $VLANIDTextBoxText(65..90) | ForEach-Object {$DriveLetter = [char]$_[int64]$value = (Get-UDElement -Id "Drive$DriveLetter")['value']$Path = $VHDRootTextBoxText+"\"+$VMNameTextBoxText+"\"+$VMNameTextBoxText+"-"+$value+".vhdx"if (Test-Path $Path){Add-VMHardDiskDrive -VMName $VMNameTextBoxText -Path $Path -ControllerType SCSI -ControllerNumber 0}}## REMOVING NETWORK FROM THE BOOT ORDER#Set New Boot orderif ($VMGeneration -eq "2"){$old_boot_order = Get-VMFirmware -VMName $VMNameTextBoxText -ComputerName $HostName | Select-Object -ExpandProperty BootOrder$new_boot_order = $old_boot_order | Where-Object { $_.BootType -ne "Network" }Set-VMFirmware -VMName $VMNameTextBoxText -ComputerName $HostName -BootOrder $new_boot_order}# ADD DVD Drive with ISO Attachedif ($BootISOTextBoxText -ne ""){Get-VM $VMNameTextBoxText | Add-VMDvdDrive -Path $BootISOTextBoxText}if ($VHDPathExisted) {Show-UDToast -Message ("VM " + $VMNameTextBoxText + " Created OK, but at least one VHD already existed and was just reattached")}else{Show-UDToast -Message ("VM " + $VMNameTextBoxText + " Created OK")}}}New-UDDashboard -Title "Hyper-V VM Creator" -Content {New-UDContainer -Children {New-UDTypography -Text "Hyper-V VM Creator" -Variant h3New-UDRow -Columns {New-UDColumn -LargeSize 6 -Content {New-UDRow -Columns {New-UDTextbox -Label 'VM Name' -Id 'VMName'}New-UDRow -Columns {New-UDTextbox -Id 'VMRam' -Label 'RAM in GB' -Value $HostRam}New-UDRow -Columns {New-UDTextbox -Id 'VMCPU' -Label 'CPU Count' -Value 2}New-UDRadioGroup -Label 'Generation' -Id 'VMGeneration' -Children {New-UDRadio -Label 'Gen 1' -Value 'Gen1'New-UDRadio -Label 'Gen 2' -Value 'Gen2'} -Value 'Gen1'}New-UDColumn -LargeSize 6 -Content {New-UDRow -Columns {New-UDSelect -Id 'VMSwitch' -Label 'Switch Name' -Option {$i = 0$SwitchList | ForEach-Object {New-UDSelectOption -Value $i -Name $_$i++}}}New-UDTextbox -Id 'VMVLan' -Label 'VLAN ID'}}New-UDRow -Columns {New-UDColumn -LargeSize 12 -Content {New-UDTextbox -Id 'VMBootISO' -Label 'Boot ISO'}}New-UDRow -Columns {New-UDColumn -LargeSize 12 -Content {New-UDTextbox -Id 'VMVHDRoot' -Label 'VHD Root'}}New-UDTypography -Text 'Drives' -Variant h4New-UDRow -Columns {New-UDColumn -LargeSize 6 -Content {New-UDRow -Columns {# Loop through each letter of the alphabet(65..90) | ForEach-Object {New-UDColumn -LargeSize 6 -Content {$DriveLetter = [char]$_New-UDTextbox -Id "Drive$DriveLetter" -Placeholder $DriveLetter}}}}New-UDColumn -LargeSize 6 -Content {New-UDButton -Text 'Do Some Checks' -OnClick { Run-Checks }New-UDButton -Text 'Im feeling lucky Create Vm' -OnClick { Create-VMs }}}}}}​}