functions/New-PSRemoteOperationForm.ps1
Function New-PSRemoteOperationForm { [cmdletbinding()] [OutputType("None", [system.io.fileinfo])] [Alias('nrof')] Param( [ValidateScript({Test-Path -Path $_ })] [Parameter(HelpMessage = "The folder where the remote operation file will be created.")] [string]$Path = $PSRemoteOpPath, [Parameter(HelpMessage = "Specify which version of PowerShell to use for the remote operation.")] [ValidateSet("Desktop", "Core")] [string]$PSVersion = "Desktop" ) if ($isWindows -or ($PSedition -eq 'Desktop' )) { Try { Add-Type -AssemblyName PresentationFramework -ErrorAction stop } Catch { Write-Warning "Failed to load required WPF assemblies." Throw $_ #bail out return } [xml]$xaml = @" <Window x:Name="form" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="PS Remote Operations v$PSVersion" Height="500" Width="425"> <Grid Margin="0,4,0.4,-3.6"> <Grid.ColumnDefinitions> <ColumnDefinition Width="311*"/> <ColumnDefinition Width="106*"/> </Grid.ColumnDefinitions> <Label x:Name="label" Content="Computername" HorizontalAlignment="Left" Margin="20,16,0,0" VerticalAlignment="Top" Width="112" Height="30"/> <ComboBox x:Name="comboComputername" HorizontalAlignment="Left" Margin="120,17,0,0" VerticalAlignment="Top" Width="180" ToolTip="Select a computer from the list or enter a new one" Height="22" IsEditable="True" TabIndex="0"/> <CheckBox x:Name="chkWhatIf" TabIndex = "8" Content="WhatIf" HorizontalAlignment="Left" Margin="23.8,17,0,0" VerticalAlignment="Top" RenderTransformOrigin="1.387,-14.475" Grid.Column="1" Height="15" Width="55"/> <Button x:Name="btnCreate" TabIndex = "10" Content="_Create" HorizontalAlignment="Left" Margin="104,410,0,0" VerticalAlignment="Top" Width="75" AutomationProperties.AcceleratorKey="C" Height="20"/> <Button x:Name="btnCancel" TabIndex = "11" Content="C_ancel" HorizontalAlignment="Left" Margin="230,410,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.547,0.994" Height="19" AutomationProperties.AcceleratorKey="A"/> <RadioButton x:Name="radioScriptblock" Content="Scriptblock" HorizontalAlignment="Left" Margin="20,48,0,0" VerticalAlignment="Top" Height="15" Width="78" TabIndex="1"/> <RadioButton x:Name="radioScriptfile" TabIndex="3" Content="Script File" HorizontalAlignment="Left" Margin="20,194,0,0" VerticalAlignment="Top" Height="15" Width="70"/> <TextBox x:Name="txtFile" TabIndex = "4" HorizontalAlignment="Left" Height="23" Margin="99,192,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="259" ToolTip="Enter the path to a ps1 file on the REMOTE computer" Grid.ColumnSpan="2"/> <TextBox x:Name="txtScriptBlock" TabIndex="2" AcceptsReturn="True" HorizontalAlignment="Left" Margin="44,73,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="319" Height="106" FontFamily="Consolas" ScrollViewer.VerticalScrollBarVisibility="Auto" ToolTip="Enter a scriptblock to run on the remote computer. Enter the contents only without the {}." Text="scriptblock here" BorderThickness="2" Grid.ColumnSpan="2"/> <TextBox x:Name="txtInitialization" TabIndex = "5" AcceptsReturn="True" HorizontalAlignment="Left" Margin="44,245,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="319" Height="41" FontFamily="Consolas" ScrollViewer.VerticalScrollBarVisibility="Auto" ToolTip="Enter initialization command such as dot sourcing scripts or importing modules" BorderThickness="2" Grid.ColumnSpan="2"/> <TextBox x:Name="txtArguments" TabIndex = "6" AcceptsReturn="True" HorizontalAlignment="Left" Margin="44,323,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="319" Height="41" FontFamily="Consolas" ScrollViewer.VerticalScrollBarVisibility="Auto" ToolTip="enter a set of parameters like Name = foo one per line. You don't need to include quotes. Enable a switch as $True." BorderThickness="2" Grid.ColumnSpan="2"/> <Label x:Name="label1" Content="Initialization" HorizontalAlignment="Left" Margin="20,218,0,0" VerticalAlignment="Top" Height="25" Width="74"/> <Label x:Name="label2" Content="Arguments" HorizontalAlignment="Left" Margin="20,296,0,0" VerticalAlignment="Top" Height="26" Width="69"/> <Label x:Name="label3" Content="To:" HorizontalAlignment="Left" Margin="20,378,0,0" VerticalAlignment="Top" Height="26" Width="22"/> <ComboBox x:Name="ComboTo" TabIndex = "7" IsEditable = "True" HorizontalAlignment="Left" Height="23" Margin="44,378,0,0" VerticalAlignment="Top" Width="316" ToolTip="Enter CMS To: recipient" Grid.ColumnSpan="2"/> <CheckBox x:Name="chkPassthru" TabIndex = "9" Content="Passthru" HorizontalAlignment="Left" Margin="23.8,37,0,0" VerticalAlignment="Top" RenderTransformOrigin="1.387,-14.475" Grid.Column="1" Height="15" Width="67"/> <TextBox x:Name="statusbar" HorizontalAlignment="Stretch" Width="auto" Padding = "10,0,0,10" Margin="0,433,0,0" Text="Loading" VerticalAlignment = "Center" Height="30" Grid.ColumnSpan="3"/> </Grid> </Window> "@ $reader = New-Object System.Xml.XmlNodeReader $xaml $form = [Windows.Markup.XamlReader]::Load($reader) $form.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen $form.background = "#dce4de" #connect to controls $btnCancel = $form.findname("btnCancel") $btnCancel.Add_click( { $script:nroParams = $null $form.close() }) $btnOK = $form.findname("btnCreate") $btnOK.Add_Click( { if ($cmbComputername.text -notmatch "\w+") { $status.text = "You must select a computername." #bail out and go back to the form return } else { $script:nroParams = @{ Computername = $cmbComputername.Text Path = $Path } } if ($chkWhatIf.IsChecked) { $script:nroParams.Add("WhatIf", $True) } if ($chkPassthru.IsChecked) { $script:nroParams.Add("Passthru", $True) } if ($comboTo.text -match "\w") { $script:nroParams.Add("To", $ComboTo.Text) } if ($txtInit.text) { $script:nroParams.Add("Initialization", [scriptblock]::Create($txtInit.Text)) } if ($txtArgs.text) { if ($txtArgs.text -match "\w+(\s+)?=(\s+)?\w+") { $txtArgs.text.Split("`n") | ForEach-Object -Begin { $h = [ordered]@{ } } -Process { $items = $_.split("=") $h.add($items[0].trim(), $items[1].trim()) } -End { $script:nroParams.Add("ArgumentList", $h) } } #if argument text matches x = y else { $status.text = "Arguments must follow the form parameter = value each on a new line" $script:nroParams.remove("ArgumentList") return } } if ($radioSB.IsChecked) { if ($txtSB.text -match "\w+") { $script:nroParams.Add("Scriptblock", [scriptblock]::Create($txtSB.text)) } else { $status.text = "You must enter code for the scriptblock." #bail out return } } else { #$radioFile must be checked instead if ($txtfile.text -match "\w+") { $script:nroParams.Add("Scriptpath", $txtFile.Text) } else { $status.text = "You must enter path to the .ps1 file on the REMOTE computer." #bail out return } } $form.Close() }) $cmbComputername = $form.findname("comboComputername") (Get-ChildItem -Path $PSRemoteOpArchive -File).foreach( { ($_.name).split("_", 2)[0] }) | Select-Object -Unique | Sort-Object | ForEach-Object { [void]$cmbComputername.items.add($_) } $radioSB = $form.FindName("radioScriptblock") $radioSB.Add_Click( { $txtSB.IsEnabled = $True $txtFile.IsEnabled = $False }) $txtSB = $form.Findname("txtScriptBlock") $txtSB.Text = $Null $radioSB.IsChecked = $True $txtSB.IsEnabled = $True $radioFile = $form.FindName("radioScriptfile") $radioFile.Add_Click( { $txtSB.IsEnabled = $False $txtFile.IsEnabled = $True }) $txtFile = $form.findname("txtFile") $radiofile.IsChecked = $False $txtFile.IsEnabled = $False $chkWhatif = $form.FindName("chkWhatIf") $chkPassthru = $form.FindName("chkPassthru") $txtInit = $form.FindName("txtInitialization") $txtArgs = $form.FindName("txtArguments") $status = $form.findname("statusbar") $ComboTo = $form.findname("ComboTo") $certs = Get-ChildItem -Path Cert:\CurrentUser\my -DocumentEncryptionCert if ($certs) { foreach ($cert in $certs) { [void]$comboTo.items.Add($cert.subject.trim()) } } $form.Add_Loaded( { $cmbComputername.focus() $status.text = "Ready" }) [void]$form.showDialog() if ($script:nroParams) { if ($chkWhatif.IsChecked) { $msg = "PSRemoteOperation WhatIf Values `n $($script:nroParams | Out-String )" Write-Host $msg -ForegroundColor green } $script:nroParams.Add("PSVersion",$PSVersion) New-PSRemoteOperation @script:nroParams } } #if Windows else { Write-Warning "This requires a Windows platform that supports WPF." } } #close New-PSRemoteOperationForm |