0

I saw some code on an older Stack Overflow on how to accomplish a GUI based input box found below which works great. But I am wondering if there is a way to restrict this to just int's as I am requesting a UPC. And if I can add a simple dropdown list. Not sure if this is possible or not or it I need to use read-line which is quite a bit of code for some simple inputs.

#Ask for UPC
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')

$title = 'Enter UPC'
$msg   = 'Enter the UPC of the Item:'

$upc = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
1
  • Be sure to check the new edit, the previous answer actually blocked INTs instead of allowing only INTs. Fixed! Commented Aug 27, 2021 at 16:00

1 Answer 1

4

If you run this command, you'll see the options we have available for configuring a VisualBasic Input box.

[Microsoft.VisualBasic.Interaction]::InputBox

OverloadDefinitions                                                                              
-------------------                                                                              
string InputBox(string Prompt, string Title, string DefaultResponse, int XPos, int YPos)  
                                                                                                 

So as you can see, we can only configure the prompt, title, default value in the text box and where on the screen it should appear.

However, if instead of using Visual Basic in PowerShell, you were to make your own GUI using WPF which also works in PowerShell, you can restrict the input.

How to do it in WPF

Here's a working form that displays a textbox in WPF.

$inputXML = @"
<Window x:Class="FoxDeploy.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:Azure" 
    mc:Ignorable="d" 
    Title="FoxDeploy Awesome GUI" Height="350" Width="600">    
    <Grid Margin="0,0,45,0">        
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Height="100" Margin="174,28,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="282" FontSize="16"><Run Text="Use this tool to find out all sorts of useful disk information, and also to get rich input from your scripts and tools"/><InlineUIContainer>
                <TextBlock x:Name="textBlock1" TextWrapping="Wrap" Text="TextBlock"/>
            </InlineUIContainer></TextBlock>
        <Button x:Name="button" Content="OK" HorizontalAlignment="Left" Height="55" Margin="370,235,0,0" VerticalAlignment="Top" Width="102" FontSize="18.667"/>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="35" Margin="221,166,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="168" FontSize="16"/>
        <Label x:Name="label" Content="UPC" HorizontalAlignment="Left" Height="46" Margin="56,162,0,0" VerticalAlignment="Top" Width="138" FontSize="16"/>
</Grid>
</Window>
"@

$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML
 
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{
    $Form=[Windows.Markup.XamlReader]::Load( $reader )
}
catch{
    Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged or TextChanged properties in your textboxes (PowerShell cannot process them)"
    throw
}
 
#===========================================================================
# Load XAML Objects In PowerShell
#===========================================================================
  
$xaml.SelectNodes("//*[@Name]") | %{"trying item $($_.Name)";
    try {Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop}
    catch{throw}
    }

$Form.ShowDialog()

Then, you can add a simple event handler to remove any integers as soon as someone types or pastes them, which looks like this.


$WPFtextBox.add_TextChanged({
    #rPrevious, would prohibit INTs
    #$WPFtextBox.Text = $WPFtextBox.Text -replace '[^0-9a-zA-Z-]',''

    #new, only allows ints
     $WPFtextBox.Text = $WPFtextBox.Text -replace '[^0-9-]',''
})

enter image description here

Accessing the value

Afterwards, when the user closes the window, you can retrieve the last value of the text box in the same way we setup the event handler, by using the $WpfTextbox.Text property.

PS> $WPFtextBox.Text
232123455212

If you want to learn more about these kinds of tools, you can check the guides I wrote or google for 'PowerShell WPF GUI tutorial'

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.