Part II – Deploying PowerShell GUIs in Minutes using Visual Studio

series_PowerShellGUI

This post is part of the Learning GUI Toolmaking Series, here on FoxDeploy. Click the banner to return to the series jump page!


I got a lot of feedback last time, everyone wants the rest of the series, and you guys want it now! So I’m skipping my normal 1,000 word limit for this post and making this bad-boy LONG! There will still be a part three where I’ll show you how to use some of the trickier form elements. Some of them are absolute hacks to make them work in PowerShell, so if you’re the god of XAML and WPF, please have mercy on us mere-mortals and add some comments to let us know how I ought to be doing it.

Let’s jump back in and take our finished XAMl from last time and put it into PowerShell.

Whoa whoa, what’s XAML

I don’t know if you noticed this window. This whole time we’ve been adding elements, dropping boxes and text and things like that, it’s been updating in real time!

ZAMMLE_pic0

The language here is XAML, (Extensible Application Markup Language) which is a Microsoft language built on XML to make very small but effective applications easily. We’ll copy this code, but first, we need to make some changes to it before it will ‘just work’.

If you want to use my example as the base for your GUI, you can copy this right into Visual Studio:

Basically, we need to remove some properties from the window declaration, and also remove the x: before each name. But don’t do all of that by hand, just copy and paste it into this little blob I’ve made for you 🙂

Importing this into PowerShell

Updated January 2018 with better error catching!

If you’ve taken a look at the blog article on the MS site which I linked last week, some of the above might look very familiar. In fact, I’ve added a bit of extra output to help us in troubleshooting (by dumping a list of all of the variables relating to objects on our form) and made this into a snippet, which you can download and embed in your own ISE.

That’s a lot of code, but you only need to copy and paste your XAML from VisualStudio to PowerShell in between the here-string.

What’s a here-string?

If you’ve never heard of a here-string, it’s a programming term for a multi-line variable that maintains spacing and allows for variable expansion. Long-story short, it’s the @” “@ above.

When you’ve copied and pasted your XAML into the here-string above and hit F5 in the PowerShell ISE (or wherever you edit scripts), you’ll see the following:

Running Convert tool

Our tool has scanned through the GUI and created hooks associated with every interactable element on the screen. We can now make changes to these things with code, just by changing their objects. This little display here is actually a function embedded in the code. You can run it again later if you forget the variable names by running Get-FormVariables.

As you see above, if we want to run the GUI, we just type in

>$Form.ShowDialog() | Out-Null

That was SO EASY!
That was SO EASY!

Changing values on the GUI is easy!

Now, what if we wanted to do something a bit more complex, like change the value of the Text where it says ‘TextBox’.

We need to hook into the properties that the tool displayed to us earlier. In this case, the name is $WPFTextBox. This is an object which this refers to the object on our form. That means we can change the text just by looking for a .text property on this object.

$WPFtextBox.Text
>TextBox

If we change this with a simple equals statement…

$WPFtextbox.Text = 'Hello World'

Hello World

This is the basic flow we’ll take to interact with all of our GUIs hence-forth. Draw something cool in Visual Studio, copy and paste it into the snippet, then run Get-FormVariables and see what the name is for our new cool GUI features (they’re called ‘Form controls’ if we want to be specific). Then look at the new object and see what it’s properties and methods are.

But it doesn’t work…

One last thing before we fully upgrade this into an awesome tool, let’s try clicking the OK Button.

Nothing happens! Here’s why: by default, we need to give our button an action to run when we click it. You do this using the Add_Click() method, which lets us put a {script-block} into the () overload, which will be executed when the user clicks a button. This makes our buttons a great place to setup hooks if we want to grab the values from a box.

For instance, if we want our OK button to just close our form, we run this little number

$WPFbutton.Add_Click({$form.Close()})

After the form has closed, the value of all of these objects in the form still persist, so if the user made typed something like ‘YoDawg’ into our textbox, we can get it once the form is gone by running:

$WPFtextBox.Text

YoDawg

Alright, let’s make this into a WMI info gathering tool.

Building a better WMI tool

I’ve got a tool that I walk people through making in my Learning PowerShell bootcamp course (if you want me to come deliver one at your company, send me a message!), in which we learn how to query WMI/CIM and then expand from there and make it do cool fancy stuffs. The output of the tool at the end of the day looks like this.
Driveinfo

We can make a GUI version of this by adding a ListView, which is pretty much embedding something like an Excel datasheet into this GUI. To do this, click ListView in the ToolBox and drag it to your form and size appropriately. You’ll notice that I also made a few tweaks to the layout to better fit what we want this tool to do.

Layout pregridview

You can just barely make it out, but there is a grid there now, waiting to receive our beautiful rows and columns. Let’s add some stuff, just a warning, this can be a bit tricky at first.

In Visual Studio, in the XAML, click the GridView Tag.

Layout Click Gridview

In properties on the right, click ‘Columns’

Layout AddColumns
This will bring up the Column collection editor

Column editor

Now, in this area, you’ll want to click the ‘Add’ button and change the width to about 100 for each, and specify the column name in the Header Box. I’ll add one each for each of the fields my tool returns:

• Drive Letter
• Drive Label
• Size(MB)
• FreeSpace%

As before, you can change the font by clicking on the area with text, then go to Properties>Text on the right side of the screen. When finished you should have something like this:

Columns

If we want to make our buttons and form actually work though, we’ll need to hook into the form again, as we did previously.

Making all of the new stuff work

If you want to catch up with where we are now in the walkthrough, get this stuff:

If you scroll to the bottom, just below Get-FormVariables, you’ll see an example of how to add data to a field. This part of our script is where the XAML has been parsed, and objects have been created to hook into them. This is where we’ll need to put our magic sauce to make the buttons and fields work and do cool things.

Where-To-make-changes

So, scroll down to the ‘Make the Objects Actually Work’ area.

First things first, take this snippet of code which accepts a computer name and returns the disk information:

Function Get-DiskInfo {
param($computername =$env:COMPUTERNAME)

Get-WMIObject Win32_logicaldisk -ComputerName $computername | Select-Object @{Name='ComputerName';Ex={$computername}},`
                                                                    @{Name=‘Drive Letter‘;Expression={$_.DeviceID}},`
                                                                    @{Name=‘Drive Label’;Expression={$_.VolumeName}},`
                                                                    @{Name=‘Size(MB)’;Expression={[int]($_.Size / 1MB)}},`
                                                                    @{Name=‘FreeSpace%’;Expression={[math]::Round($_.FreeSpace / $_.Size,2)*100}}
                                                                 }

Here is what to do next.

  • I want my textbox to default to displaying my computer name
  • I want to add a trigger that when I click the Get-DiskInfo button, it should run the Get-DiskInfo function, using the computer name specified in the textbox
  • Finally, I want to take the objects I get from that and for each of them, add a new row to my ListView area

Change your code to the following, beginning on line 61 (or just below Get-FormVariables)

Function Get-DiskInfo {
param($computername =$env:COMPUTERNAME)

Get-WMIObject Win32_logicaldisk -ComputerName $computername | Select-Object @{Name='ComputerName';Ex={$computername}},`
                                                                    @{Name=‘Drive Letter‘;Expression={$_.DeviceID}},`
                                                                    @{Name=‘Drive Label’;Expression={$_.VolumeName}},`
                                                                    @{Name=‘Size(MB)’;Expression={[int]($_.Size / 1MB)}},`
                                                                    @{Name=‘FreeSpace%’;Expression={[math]::Round($_.FreeSpace / $_.Size,2)*100}}
                                                                 }

$WPFtextBox.Text = $env:COMPUTERNAME

$WPFbutton.Add_Click({
Get-DiskInfo -computername $WPFtextBox.Text | % {$WPFlistView.AddChild($_)}
})

Let’s run it and see what happen’s when you click the button.

If it breaks in a new way, I call that progress

Layout almost there

Well, crap. Adding new rows worked, but now every column has the output for every property. This is happening because, very similar to when you work with the pipeline in PowerShell or make a function, you have to tell PowerShell how to bind to values.

To fix this, go up to your XAML for your GridView Columns and add a DisplayMemberBinding Property like this. Make sure if you’re deviating from the walkthrough and doing your own thing to pick names that make sense. If your name has a space in it, use single quotes around it.

And the finished product:

done

Whats up next?

Alright guys, I want to thank you for sticking with me to the end of this VERY long blog post. I hope you enjoy it and will use this technique to make some awesome GUIs of your own.

Join me for my post next time on this topic, part III in the GUI series, in which we dig into how to add some of the cooler and more difficult features to our GUI, like a tabbed interface (to get other WMI values) and how to use checkboxes and radio buttons, dropdown boxes and more!

Part III – Using Advanced GUI Elements in PowerShell

Final XAML Code here

Full PowerShell Code here

$inputXML = @"
COPY Xaml from above 🙂
"@        

$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 properties (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}
    }
Function Get-FormVariables{
if ($global:ReadmeDisplay -ne $true){Write-host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow;$global:ReadmeDisplay=$true}
write-host "Found the following interactable elements from our form" -ForegroundColor Cyan
get-variable WPF*
}

Get-FormVariables

#===========================================================================
# Actually make the objects work
#===========================================================================

Function Get-DiskInfo {
param($computername =$env:COMPUTERNAME)

Get-WMIObject Win32_logicaldisk -ComputerName $computername | Select-Object @{Name='ComputerName';Ex={$computername}},`
                                                                    @{Name=‘Drive Letter‘;Expression={$_.DeviceID}},`
                                                                    @{Name=‘Drive Label’;Expression={$_.VolumeName}},`
                                                                    @{Name=‘Size(MB)’;Expression={[int]($_.Size / 1MB)}},`
                                                                    @{Name=‘FreeSpace%’;Expression={[math]::Round($_.FreeSpace / $_.Size,2)*100}}
                                                                 }

$WPFtextBox.Text = $env:COMPUTERNAME

$WPFbutton.Add_Click({
$WPFlistView.Items.Clear()
start-sleep -Milliseconds 840
Get-DiskInfo -computername $WPFtextBox.Text | % {$WPFlistView.AddChild($_)}
})
#Sample entry of how to add data to a field

#$vmpicklistView.items.Add([pscustomobject]@{'VMName'=($_).Name;Status=$_.Status;Other="Yes"})

#===========================================================================
# Shows the form
#===========================================================================
write-host "To show the form, run the following" -ForegroundColor Cyan
$Form.ShowDialog() | out-null

Link to the ISE Snippet

Advertisements

227 thoughts on “Part II – Deploying PowerShell GUIs in Minutes using Visual Studio

  1. Zachary Loeber (@zloeber) April 16, 2015 / 7:08 pm

    Good stuff. Might I add that replacing the x: from all the form element names is not required. Using some xpath trickery you can pull all the named variables out and define them. If $xamlMain is your xaml form it would look something like this:

    # Read XAML
    $reader=(New-Object System.Xml.XmlNodeReader $xamlMain)
    $window=[Windows.Markup.XamlReader]::Load( $reader )

    $namespace = @{ x = ‘http://schemas.microsoft.com/winfx/2006/xaml’ }
    $xpath_formobjects = “//*[@*[contains(translate(name(.),’n’,’N’),’Name’)]]”

    # Create a variable for every named xaml element
    Select-Xml $xamlMain -Namespace $namespace -xpath $xpath_formobjects | Foreach {
    $_.Node | Foreach {
    Set-Variable -Name ($_.Name) -Value $window.FindName($_.Name)
    }
    }

    Like

    • FoxDeploy April 16, 2015 / 7:15 pm

      I totally super suck at xpath, so I tried to do this for about an hour before I gave up and found the xpath used here in another blog. Thanks for posting this, I’m eager to try it out!

      Like

      • Jarko April 21, 2015 / 4:02 pm

        Ok Zloeber, tried your approach together with FoxDeploys goodies, worked just fine, thanks, both of you!

        Like

    • T September 15, 2015 / 8:46 am

      For me, the xpath fails:
      select-xml : ‘//*[@*[contains(translate(name(.),’n’,’N’),’Name’)]]’ has an invalid token.

      Like

      • FoxDeploy September 15, 2015 / 8:49 am

        Try to copy it from github instead.

        Like

  2. BeauD April 20, 2015 / 7:05 pm

    Great posts, really enjoying it! Everything worked perfectly for me until I added the DisplayMemberBinding in the gridview tags. I changed the names to match the columns I’m returning. When running the Form, it now does nothing on button click.

    Liked by 1 person

    • FoxDeploy April 20, 2015 / 7:11 pm

      Hi Beau! Make sure that your objects and your property name in the binding match, otherwise you’ll get blank columns! If you are having trouble, put your code on pasteBin and link it here!

      Like

  3. BeauD April 21, 2015 / 1:10 pm

    Ah, silly me. The objects I’m returning in Powershell didn’t have spaces in the names like the columns in my ListView. Thanks for your help!

    Like

  4. Mattis May 11, 2015 / 6:02 pm

    how do you hide buttons when a submenu has been selected?

    example: menu has 4 categories [1 – FIX PC] [2 – TOOLS] [3 – OPTIONS] [4 – ADMIN LOGIN]

    when you press [1 – FIX PC] , various buttons appear in subsection below.
    when you press [2 – TOOLS] the respective buttons appear but the FIX PC buttons will become hidden.

    is there a visibilty syntax or do you move them at an x,y coordinate out of the form range?

    Like

    • FoxDeploy May 11, 2015 / 6:16 pm

      Pretty much everything has a .visible property. Set visible to false when you need to hide something

      Like

      • Mattis May 14, 2015 / 5:10 pm

        in XAML or PS?

        Like

        • FoxDeploy May 14, 2015 / 5:12 pm

          Check out part III , I added examples of just this thing for you!

          Like

  5. Mattis May 14, 2015 / 5:21 pm

    ignore my last reply…just read your GUI Blog pt.3 🙂

    Liked by 1 person

  6. MATTIS May 15, 2015 / 3:08 am

    Stephen, you are a PS god. thanks! 🙂

    Liked by 1 person

    • FoxDeploy May 15, 2015 / 6:16 am

      Aw, thanks for saying that 🙂

      I need some ideas for part 4 and beyond, so let me know if there is anything you’d like to see!

      Like

      • MATTIS May 15, 2015 / 8:55 am

        3 things:

        1. When you launch a button, the midsection of your GUI will show a new set of buttons

        and

        2. when you press one of these new buttons in the midsection (example: ping workstation or show ADD/REMOVE programs in grid view, it will run a progress bar in the lower section (a rich text area perhaps?). When the PS script stops running the results are also displayed in the lower section showing the ping results or the grid view of the ADD/REMOVE programs.

        see my ascii pic here:

        —————————————————————-
        | FoxDeploy Toolkit [x] |
        |————————————————————–|
        | [1 – PC TOOLS] [2 – INFO] | <- TOP SECTION
        |————————————————————–|
        | |
        | [PING PC] [Show ADD/REMOVE] | <- MID SECTION
        |————————————————————–|
        | |
        | |
        | [======= ] 10% done | <- LOWER SECTION
        | |
        |_____________________________________|

        3. Back in XAML, how to make the buttons rollover with a different colour or image.

        Nuff stuff for you, mate? 🙂

        Liked by 1 person

        • FoxDeploy May 12, 2016 / 9:43 pm

          Check my site on Tuesday next week… Didn’t use all of these ideas but I used some of them… 🙂

          Like

      • Mattski June 17, 2015 / 6:55 am

        Did you manage to find some time to do the below ideas? 🙂

        Like

  7. MATTIS May 15, 2015 / 8:56 am

    I should have drawn a pic – probably confused you now, best to copy the above pic text and plonk it in Notepad! 😉

    Like

  8. Daryl June 12, 2015 / 7:32 pm

    Why would I not be able to show the form a second time after running the snippet? It works fine the first time. I close out the form and make the change to the text to ‘Hello World’. When I try to open the form again by running $Form.ShowDialog() out-null I get an exception.

    PS C:\windows\system32> $Form.ShowDialog() | Out-Null
    Exception calling “ShowDialog” with “0” argument(s): “Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a
    Window has closed.”
    At line:1 char:1
    + $Form.ShowDialog() | Out-Null
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : InvalidOperationException

    Like

    • FoxDeploy June 12, 2015 / 8:23 pm

      Ah, the variables persist but the form is consumed when it Is displayed then closed. You have to run the whole thing again to display the form again.

      For this reason, I like to store my forms in functions, called something like Show-UserEntryForm or the like.

      Does this make sense?

      Like

      • Daryl June 14, 2015 / 8:13 pm

        Not exactly. Could you expand please?

        Like

        • FoxDeploy June 14, 2015 / 9:16 pm

          You need to rerun the xaml and everything prior to the $form.Show command whenever you want to display a form

          Like

      • Dudki July 6, 2015 / 10:14 am

        Thanks for a hint, this works 🙂

        Like

        • Espo October 17, 2016 / 2:58 pm

          I fee dumb now not being able to figure out where to put this function and when it needs to be called. basically once i close my form (either through the button or forcing close) I need to re-run script and call it again with $Form.ShowDialog() | out-null, but then any “changes” made via PS are wiped, as the form goes back to square 1

          Like

        • FoxDeploy October 17, 2016 / 7:06 pm

          Could you share your code? I’m having a hard time picturing it.

          Like

        • Espo October 17, 2016 / 8:13 pm

          This behavior is the same even if I use the exact code from your example. Pasted into powershell and run it. Then call the form, then close the form, then run ps command to alter the text box then call the form again and I get that same error as mentioned above. You suggested using the function before calling the form.

          Like

        • Espo October 18, 2016 / 10:17 am

          Ignore my questions… clearly it was a long day and I was thinking inside the box!

          Like

  9. Daryl June 14, 2015 / 10:43 pm

    I can see where a change is taking place but when I re-run the xaml it resets the changes (ie. ‘Hello World’) so the form doesn’t show them but instead shows ‘Textbox’.

    Like

  10. Kirk July 7, 2015 / 1:11 pm

    This is all new to me, I’m getting stuck at the point where I paste my XAML in the here-string. I get the catch message “Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed.” Then when I try to run $form.ShowDialog() | Out-Null I get that message about not being able to call a method on a null valued expression.

    Please advise

    Like

  11. Mark August 13, 2015 / 10:23 am

    This is great! Is there a way to save/compile it so I could give what I build to other users?

    Like

  12. DITG August 20, 2015 / 6:52 am

    This is an awesome and very usefull blogpost! I’ve always wanted to create GUI’s around my powershell scripts, but found the manual adding and finetuning of powershell code to do this to be tiresome. this makes it so much easier!

    Thank-you!

    Like

  13. Ron Aricha September 4, 2015 / 10:49 am

    Hi
    I have learned a lot from your script.
    I want to know if is a way to refer to the image in the current directory instead of the full path

    Thank you.

    Like

    • Mike September 8, 2015 / 7:15 pm

      Ron,

      Try this in the script:
      $WPFimage.Source = (Join-Path $(Split-Path -Parent $MyInvocation.MyCommand.Path) “my_logo.png”)

      Add this underneath the “Actually make the objects work” section of the example, and of course, give it a valid image name instead of “my_logo.png”. This sets the image source to that file name in the directory where your script lives.

      Like

  14. Ben October 15, 2015 / 4:00 pm

    Hi,

    i have an idea.

    create a small windows with one button and 2 text fields.

    1. username
    2. password
    3. button: join domain!

    user will input these values and when he clicks join domain, the app will try to join the computer into AD domain 😀

    Like

    • Ben October 15, 2015 / 4:02 pm

      Ow,

      and when app launches, it should check if the PC is already member of a domain, and if it is, it should exit immediatly without any popups, but if its not, it should launch normally.

      this could be good for client VPN connection, to run this script “OnConnect”, so that any remote PC will have simple means of joining the domain :d

      Like

  15. Ram Iyer November 14, 2015 / 8:53 am

    Hey Stephen! Your post is super-detailed and got me intrigued big time. 🙂
    I created the form. However, when I put in the XAML in the script that you’ve given to extract the variables and stuff, it gave me errors at the line:

    $xaml.SelectNodes(“//*[@Name]”) | %{Set-Variable -Name “WPF$($_.Name)” -Value $Form.FindName($_.Name)}.

    Not sure if I can post the error here. Would look like a big load of spam. I can email you the XAML and the error… or something. Could you help, please?

    Like

    • FoxDeploy November 14, 2015 / 9:04 am

      Put your code on paste bin and send me the link, and I’ll try to help you!

      Liked by 1 person

        • FoxDeploy November 16, 2015 / 1:27 pm

          Just remove these ‘TextChanged=”textBox_TextChanged”‘ and your script will load. I’m not sure what you were trying to do with that, but let me know and I’ll show you how it works in PowerShell.

          Like

        • Ram Iyer November 20, 2015 / 12:00 am

          Wow… I have no idea what that is. Must have set some wrong property and then copied the controls.
          Removed all the occurrences of ‘TextChanged=”textBox_TextChanged”
          It works now. Thank you!

          Like

        • Kyle Sparrow June 2, 2016 / 8:27 am

          I had the same issue and resolution, Ram.

          I added another replace method to block that out, since I figure it will probably happen again in the future, and there’s no guarantee at all that I’ll remember what I did to fix it! 🙂

          Thanks, Fox!

          -Kyle

          Liked by 1 person

        • Ram Iyer June 13, 2016 / 12:49 pm

          🙂 haha, good thinking!

          Like

  16. Florian December 22, 2015 / 5:34 am

    Hi, after opening the form with $Form.ShowDialog() the script is waiting until the form is closed. Is it possible to call the form and the close it automatically after a given time?

    Like

  17. JMAD February 2, 2016 / 4:15 am

    Hey Stephen,

    Everything works fine, until I paste my XAML-Code into your script. For some reason he can’t compilate most of the textboxes and labels. I noticed some differences between a single label-declaration by your example-code and my code.

    For example your code declared a label like this :

    but my xaml-code from visual basic 2010 says:

    Theres is a different syntax and theres no “x:” before the name.

    Can you give me any advices or even better check my code and figure out, whats wrong

    Kind Regards,

    Tom

    Like

    • FoxDeploy February 2, 2016 / 4:56 am

      Ahh, this is a difference between 2010 and 2013. Look for the line that says something like -replace x:name etc etc and edit it accordingly!

      Like

  18. Dries Willems February 16, 2016 / 10:10 am

    Wow, I’m impressed!
    This works great.
    Thanks for sharing this with us!

    Btw: I used Visual Studio 2015 Professional

    Like

    • FoxDeploy February 16, 2016 / 10:30 am

      I’m on the hunt for a lightweight substitute for visual Studio too! So far, I’ve tried xamlpad and kaxaml, both show promise but I think have their own learning curves.

      I’ve also considered doing this in blender instead, but the different approach to code behind there makes it less desirable.

      I’m happy you liked it! Feel free to send me your GUIs and I can cover them here!

      Like

  19. Dries Willems February 16, 2016 / 12:03 pm

    So this worked fine until I added a Button, Checkbox or Textbox.
    If I remove each, it still doesn’t work.
    When I remove all.
    It starts to work again

    Found the following interactable elements from our form

    Name Value
    —- —–
    WPFbtnSearchUser
    WPFcbxUserDomain
    WPFchkAdminYes
    WPFimgLogo System.Windows.Controls.Image
    WPFlblAdmin System.Windows.Controls.TextBlock
    WPFlblMACAddress System.Windows.Controls.TextBlock
    WPFlblManufacturer System.Windows.Controls.TextBlock
    WPFlblModel System.Windows.Controls.TextBlock
    WPFlblSerial System.Windows.Controls.TextBlock
    WPFlblUser System.Windows.Controls.TextBlock
    WPFlblUserConfirmed System.Windows.Controls.TextBlock
    WPFlblUserDomain System.Windows.Controls.TextBlock
    WPFtxtMACAddress System.Windows.Controls.TextBlock
    WPFtxtManufacturer System.Windows.Controls.TextBlock
    WPFtxtModel System.Windows.Controls.TextBlock
    WPFtxtSerial System.Windows.Controls.TextBlock
    WPFtxtUser
    WPFtxtUserConfirmed System.Windows.Controls.TextBlock

    PS C:\Users\.\Documents> $Form.ShowDialog() | out-null
    Exception calling “ShowDialog” with “0” argument(s): “Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle a
    fter a Window has closed.”
    At line:1 char:1
    + $Form.ShowDialog() | out-null
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : InvalidOperationException

    Like

    • FoxDeploy February 16, 2016 / 12:10 pm

      Post your whole code on GitHub or pastebin and then send us the link

      Like

      • Dries Willems February 16, 2016 / 12:35 pm

        http://pastebin.com/zgpzGWDn

        It looks like it doesnt recognize the other objects one way or another.
        Thx for looking up the problem!

        Like

  20. Dries Willems February 17, 2016 / 9:03 am

    So when I add just a textbox to the form, everything is ok.
    If I add other components to the form it is not ok.
    If I remove just the textbox and let the other components in the form,it is working again.
    This is so weird.

    ———————————————————————-

    ———————————————————————-

    Like

    • FoxDeploy February 19, 2016 / 9:38 am

      Sorry for my slow turnaround here, just had a new baby in the family :).

      To fix this issue, remove the TextChanged=”…” from your text box. When you’re using PowerShell w/ XAML, you can’t use the TextChanged prop of a text box. Instead, we create an event like this,

      $WPFtxtADUser.add_TextChanged({
      #stuff to do when the textbox changes
      })

      Like

  21. Nate Ferrell February 19, 2016 / 3:36 pm

    First: THANK YOU!!!

    Second: Not sure if this has already been brought up and I missed it, but having any events defined in the XAML will cause the import to fail (these are defined for this purpose in the Powershell script below). Due to the script still trying to run the rest and the catch for that failure invoking a Write-Host only, it created a lot of on screen errors when trying to build the variables and form and didn’t actually show the error that was causing it to fail.

    To catch these, I adjusted the Catch statement like so:

    BEFORE:
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
    try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
    catch{Write-Host “Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed.”}

    AFTER:
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
    try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
    catch{return $Error[0]}

    This allows the script to stop and display the error found in the XAML build.

    Sample events that were created automatically in Visual Studio were buttonClick, listViewSelectedItem, etc.

    Like

    • FoxDeploy February 19, 2016 / 5:05 pm

      Good catch! I get weekly requests from people to help with their guis and there is almost always an automatic click option causing the issue. I should strip those out when I get a chance…

      Thanks for the kind words too 🙂 I’m working on post 5 right now

      Like

      • Nate Ferrell February 23, 2016 / 12:35 am

        Awesome!! If you need any content, I’d love to lend what I’m currently building =]… Creating a tabbed GUI to manage Google Apps domain, specifically user deprovisioning, on the first one =]… Items to be included are comboboxes, textboxes, labels that alter depending on authenticated user, and validation functions to activate / deactivate buttons depending on whether logic is met or not

        Either way, looking forward to part 5! 😀

        Like

        • FoxDeploy May 12, 2016 / 9:48 pm

          Did you ever post this? Sounds fascinating!

          Like

    • FoxDeploy May 12, 2016 / 10:01 pm

      Finally tried your code and I love it. I’ll edit the samples here to use it instead. It makes finding the actual error much, much easier.

      Like

  22. wim March 7, 2016 / 7:58 am

    Can you explain, while this didn’t work when you add an Combobox in the form?

    Like

  23. Lucas March 10, 2016 / 10:18 am

    Hi! I am testing this awesome thing and wanted to try our the following xaml code:

    But when I want to use one of the buttons for validate the date with the get-date command it keeps showing me weird things and not the date in the format I want, it seems to be a problem with the click method somehow, these are the codes I tried for the Validation button:

    $WPFValidate_Stg.Add_Click({
    $WPFStage_Date.Clear()
    $Day = $WPFSTG_DAY.Text
    $Month = $WPFSTG_MONTH.Text
    $Year = $WPFSTG_YEAR.Text
    Get-Date -date $Month/$Day/$Year -DisplayHint date | % $WPFStage_Date.AddText($_)
    })

    or

    $WPFValidate_Stg.Add_Click({
    $WPFStage_Date.Clear()
    $Day = $WPFSTG_DAY.Text
    $Month = $WPFSTG_MONTH.Text
    $Year = $WPFSTG_YEAR.Text
    $DATESTG = Get-Date -date $Month/$Day/$Year -DisplayHint date
    $WPFStage_Date.AddText($DATESTG)
    })

    This second one returns the date as I enter it instead of what I want which is something like this:

    PS C:\Users\> Get-Date -date 01/01/2016 -DisplayHint date

    Friday, January 01, 2016

    Can you spot what is wrong with the button? Thank you!

    Like

    • FoxDeploy March 13, 2016 / 8:36 am

      When you run get-date, you get back not only the Date, but a full rich object with lots of properties. Powershell in the Shell itself knows to pick only certain properties, move even just one and to display it to you.

      What you should do is run your get date command and pipe it into format-list and see all of the variations you’re getting, under the covers. Find the property that corresponds (probably datetime or simply date) and then run get-date ¦select -expand Date, which will select just that property.

      Now when you add it, it should render as expected.

      Like

  24. Lanabhat March 13, 2016 / 8:06 am

    Hi Stephen,
    I would appreciate if you take up a combo box manipulation example, which would benefit me.
    I was using autoIt to create a GUI and I was calling powershell script using it. This method of WPF is easier and the GUI is easy to build.

    Like

    • Lanabhat March 13, 2016 / 9:13 am

      this is already there in the next post… 🙂 Thanks for reading my mind 😉

      Like

  25. Jose Enriquez March 16, 2016 / 11:05 pm

    Hello Stephen,

    Thank you for your post. I have been having similar issues when pasting different XAML code. I am not sure if I am missing something, but I keep getting: You cannot call a method on a null-valued expression.
    At H:\PowerShell Scripts\stgmenu.ps1:45 char:62
    + … electNodes(“//*[@Name]”) | %{Set-Variable -Name “WPF$($_.Name)” -Valu …
    + ~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    I loaded the code on: http://pastebin.com/3P37x5Y5

    Your help would greatly be appreciated.

    Like

    • FoxDeploy May 12, 2016 / 10:04 pm

      Hi Jose! I missed this message from you two months ago! Don’t know if you moved on from this task but I found and fixed the error. It was in the Window Class name, your’s was set to stgWindow instead of Window for some reason. That caused the error. Neat concept for a tool I hope you finish it and share with the rest of us.

      Like

  26. john March 23, 2016 / 12:56 pm

    I’m kind of lost when you’re trying to import it to powershell. As I compare the xaml to the powershell script you posted, I can see from Windows X all the way to but the buttons and textbox is not there…

    I need to know what you did to this portion?

    You did mention that remove the x before the name, but on the powershell script below the sample you provide; doesn’t show those textbox or button property.

    Like

    • Morry May 6, 2016 / 6:16 pm

      I too am getting this same error is this code compatible with Win 7 powershell 2?

      Like

      • FoxDeploy May 6, 2016 / 6:32 pm

        Paste your code? It should work on v2, but I primarily design for v3 and up

        Like

  27. Morry May 7, 2016 / 1:31 pm

    Displays variables but never show form

    Like

  28. Morry May 7, 2016 / 1:34 pm

    $inputXML = @”

    “@
    $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-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."}

    #===========================================================================
    # Load XAML Objects In PowerShell
    #===========================================================================

    $xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name "WPF$($_.Name)" -Value "$Form.FindName($_.Name)"}

    Function Get-FormVariables{
    if ($global:ReadmeDisplay -ne $true){Write-host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow;$global:ReadmeDisplay=$true}
    write-host "Found the following interactable elements from our form" -ForegroundColor Cyan
    get-variable WPF*
    }

    Get-FormVariables

    #===========================================================================
    # Actually make the objects work
    #===========================================================================

    #Sample entry of how to add data to a field

    #$vmpicklistView.items.Add([pscustomobject]@{'VMName'=($_).Name;Status=$_.Status;Other="Yes"})

    #===========================================================================
    # Shows the form
    #===========================================================================
    #write-host "To show the form, run the following" -ForegroundColor Cyan
    #'$Form.ShowDialog() | out-null'
    $Form."ShowDialog()" | out-Null

    Like

    • FoxDeploy May 10, 2016 / 11:42 am

      There is no form? I don’t see anything under $inputXML. The UI you design needs to go here.

      Like

  29. Dave May 10, 2016 / 9:58 am

    Getting the following error when trying to run $Form.ShowDialog() | out-null

    You cannot call a method on a null-valued expression.
    At line:1 char:1
    + $Form.ShowDialog() | out-null
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Like

  30. Dave May 10, 2016 / 1:25 pm

    Still getting an error, below is sequence of what I am trying to run. Appreciate the help, im new to the whole XAML with powershell.

    Found the following interactable elements from our form

    Name Value
    —- —–
    WPFbutton System.Windows.Controls.Button: OK
    WPFlabel System.Windows.Controls.Label: UserName
    WPFtextBlock System.Windows.Controls.TextBlock
    WPFtextBox System.Windows.Controls.TextBox: Enter UserName
    To show the form, run the following
    $Form.ShowDialog() | out-null

    PS C:\WINDOWS\system32> $Form.ShowDialog()
    You cannot call a method on a null-valued expression.
    At line:1 char:1
    + $Form.ShowDialog()
    + ~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Like

    • FoxDeploy May 10, 2016 / 1:28 pm

      When I run the code from the gist, it works. Are you doing this in the ISE or PowerShell console? Do you have skype/hangouts/Lync etc?

      Like

  31. Chris German May 12, 2016 / 10:37 am

    Code and everything works, created my own and it works, but the only problem I have is the PowerShell CLI and the PowerShell GUI both opens up. Any way to prevent the CLI opening up?

    Like

    • FoxDeploy May 12, 2016 / 12:53 pm

      You want to run powershell with a hidden window. If you google that, you should find what you want. I think it’s powershell.exe – file your script.ps1 – showwindow hidden or something close to that!

      Like

      • mattsky May 12, 2016 / 1:30 pm

        Make a shortcut of your executable and add to the target this line: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden -file

        Like

  32. Adam E.Adam Eaddy May 12, 2016 / 2:41 pm

    Hello. Excellent posts and thank you for sharing. I am getting an error on the following line: (34 in your example above.)

    $xaml.SelectNodes(“//*[@Name]”) | %{Set-Variable -Name “WPF$($_.Name)” -Value $Form.FindName($_.Name)}

    I have posted my code on GitHub –

    The error I get is as follows:

    You cannot call a method on a null-valued expression.
    At C:\Users\106226\Desktop\Scripts\Create GUI PowerShell.ps1:51 char:62
    + … electNodes(“//*[@Name]”) | %{Set-Variable -Name “WPF$($_.Name)” -Valu …
    + ~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    If you need to reference this display again, run Get-FormVariables
    Found the following interactable elements from our form
    To show the form, run the following
    $Form.ShowDialog() | out-null

    Any help would be greatly appreciated.

    Like

    • FoxDeploy May 12, 2016 / 4:03 pm

      Here you go. GistRevision Link
      Sometimes when you double click or drag an item in Visual Studio, it adds a property called ‘TextChanged’ or something similar to the XAML. PowerShell doesn’t know how to parse this and throws an error. Deleted that and removed an unneeded class reference from the window declaration and it’s good now.

      Like

      • Adam E. May 12, 2016 / 8:14 pm

        Thank you very much. I will try this out soon. (Sorry again for the double post.)

        Like

      • Adam E. May 12, 2016 / 8:42 pm

        This worked perfectly. Thank you very much.

        Like

  33. Adam E. May 12, 2016 / 2:47 pm

    First off, thank you for sharing this.

    I am getting an error on line 32 in your example.

    $xaml.SelectNodes(“//*[@Name]”) | %{Set-Variable -Name “WPF$($_.Name)” -Value $Form.FindName($_.Name)}

    I have posted my code on GitHub –

    I get the following error:

    You cannot call a method on a null-valued expression.
    At C:\Users\106226\Desktop\Scripts\Create GUI PowerShell.ps1:51 char:62
    + … electNodes(“//*[@Name]”) | %{Set-Variable -Name “WPF$($_.Name)” -Valu …
    + ~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    If you need to reference this display again, run Get-FormVariables
    Found the following interactable elements from our form
    To show the form, run the following
    $Form.ShowDialog() | out-null

    Any assistance you could offer would be great.
    Apologies if this posts twice.

    Like

  34. Bo May 16, 2016 / 3:21 pm

    Hi Stephen,

    First, thanks for this series. I found it right at a great time when I’m developing a small tool for my team to use to monitor processes to find out if they’ve died or malfunctioned. I walked through the first post with no problems. I love using VS for the graphical side! Very helpful.

    However, when I started working with the XAML things went a little sideways on me. If I copy/paste the first code snippet you posted on this article, here’s what I get:

    Cannot convert value “…*all of the XAML code here*…” to type “System.Xml.XmlDocument”. Error: “‘<', hexadecimal value 0x3C, is an invalid attribute character. Line 2, position 16."

    This then returns the catch statement, and throws a bunch of "cannot call a method on a null-valued expression" errors, presumably because it can't load.

    To complicate things a little further, I would swear the first example was working before I went to lunch! I could use Get-FormVariables successfully, but now it won't play ball…

    Any insight you might be able to offer here?

    Like

    • FoxDeploy May 16, 2016 / 3:30 pm

      Can you put your code in a github gist or on pastebin and send us the link? Be sure to sanitize it first (Remove your company names).

      Like

        • FoxDeploy May 16, 2016 / 9:49 pm

          Dunno how that happened, but the XAML namespace declarations at the top were in the form of HTML Links! This breaks the XAML. I fixed that bug. Here you go 🙂 http://pastebin.com/U67CwzPT

          Like

        • Bo May 17, 2016 / 9:38 am

          I’m not sure how that happened either…wonder if it was a copy/paste clipboard “helpful feature” issue. In any event, your fix did the trick, so thanks!

          Also, man, for such an old post, your responsiveness and response times are freaking amazing! Thanks for all of this! I’ll be continuing on to the third part of this series today.

          Like

        • FoxDeploy May 17, 2016 / 9:56 am

          Part V for the series just dropped today too! If yo have ideas for future posts, drop me a line. Always happy to help.

          🙂

          Like

        • Bo May 17, 2016 / 9:58 am

          Sweet! I’ll power through (…ahar har) all of them.

          Also, to keep some of your follow-along PS newbies like me, you might add this to your $inputXML assignment:

          -replace ” SelectionChanged=””listView_SelectionChanged”””, ”

          That takes care of that pesky SelectionChanged thing I’ve seen you bring up a couple times. Thanks again!

          Like

        • FoxDeploy May 17, 2016 / 10:32 am

          …Why did I never think of this?! This is a great idea.

          Like

        • Bo May 17, 2016 / 9:59 am

          The last two ” is two single quotes with nothing between them. Looks weird in this font. 🙂

          Like

  35. Bo May 20, 2016 / 9:53 am

    One last thing…You can set the DisplayMemberBinding property in Visual Studio in the properties window. Click the little box beside “DisplayMemb…” (see here: http://imgur.com/fFt9DWR) and enter: “{Binding }” without the quotes. And you also don’t need to include quotes inside the binding even if the column heading includes spaces. This way, if you update the XAML and re-copy to your script, you don’t have to remember to manually add the DisplayMemberBinding attributes.

    Like

    • Bo May 20, 2016 / 9:54 am

      Oops…the post killed some of my formatting. You should enter “{Binding ..column header..}” without quotes

      Like

      • Bo May 20, 2016 / 9:55 am

        Urgh…no “.”‘s. If the column is named Alert Name just enter, {Binding Alert Name} for the Custom Expression.

        Like

        • FoxDeploy May 20, 2016 / 11:16 am

          can you make a gist on github and paste that, I’m not sure I’m following.

          Like

        • Bo May 20, 2016 / 11:37 am

          Going to reply in a fresh box….I had the step by step and it looks like it was eaten.. 😦

          Like

  36. Bo May 20, 2016 / 11:44 am

    Here’s a way to add DisplayMemberBinding to your XAML in VS2015 so you don’t have to manually edit each time you update the form.

    Like

    • Bo May 20, 2016 / 11:48 am

      Crap…sorry to bomb your blog, man! The image for #3 should be this: http://imgur.com/XxAhnKf Sorry, I’ve never used Gist before, so I’m not sure if I can edit as an anonymous post.

      Like

    • Bo May 20, 2016 / 11:49 am

      Oh for the love of…..last post, honestly. My other comment STILL has the wrong damn image. #3 should use THIS image: http://imgur.com/wOdnbl5

      Like

  37. Michel June 27, 2016 / 1:13 pm

    From the running GUI, how could I run an external powershell script. For example if I click on the OK button I would like to trigger another .ps1 file and pass it some parameters values comming from the fields in the GUI.

    Like

  38. billhoover June 27, 2016 / 1:36 pm

    I’m wondering if it could be possible to call en external powershell script from the GUI. For example, if I click on a OK button, would it be possible to execute another powershell (.ps1) and pass it some parameter values comming from TextBox fields in my GUI ?

    Like

    • FoxDeploy June 27, 2016 / 3:53 pm

      Sure, you definitely could do that. Just use the invocation character (Which is the ampersand, this thing: &)

      Button.Add_Click({
      & c:\Scripts\Script.ps1 -Param1 $WPFTextBox.Text
      })

      Like

  39. jarofrant July 4, 2016 / 1:59 am

    Im sure at least 100 of the page visits here are me refusing to let this page drop off my chrome “open tabs” list on reboots etc because ive been building a nicr script using the material within. Thanks!

    Liked by 1 person

  40. christoph July 14, 2016 / 5:15 am

    How can I click the button by hitting ENTER ?

    Like

    • FoxDeploy July 14, 2016 / 7:33 am

      You want to add a key down listener. Check out what we do to close the form when we hit escape, ans you can use this same logic.

      Like

      • christoph July 14, 2016 / 9:38 am

        thanks for your quick reply. exactly, unfortunately I dont get it working. in the example above nothing happens when you hit escape and I can not find any code for it here. I tried some other codesnippets from google, but nothing works. any help would be appreciated.

        Like

        • Bo July 14, 2016 / 9:55 am

          You should be able to set the isDefault attribute of the button to true in the XAML. When you load the form, hitting Enter should activate the button.

          Like

        • christoph July 14, 2016 / 10:13 am

          Works! Thank you very much!

          Like

  41. Jim Moyle July 22, 2016 / 5:39 am

    I found I needed to replace the line `[void][System.Reflection.Assembly]::LoadWithPartialName(‘presentationframework’)` with `Add-Type -AssemblyName presentationframework` for this to work on PoSH v5

    Like

  42. Mike September 16, 2016 / 1:42 pm

    I’ve used your page here for several tools at my previous employer, and always got them working simply following your examples and incredible instructions (brown nosing complete now to ask for the help 🙂 ). Now I’m somewhere new…trying to do something that should be very simple and cannot get it to work. If you are able to help determine what I’m doing wrong it would be appreciated.
    Here’s the git link *I think* https://github.com/ArmedGeek/XAMLAHIS/blob/Powerhsell-XAML-Help/HelpPlease.ps1

    Like

    • FoxDeploy September 16, 2016 / 3:29 pm

      I’m happy you like it! I send you a PR with my changes. 🙂

      Like

      • Mike September 20, 2016 / 8:28 am

        Hi, I found the issue. The machine I was issued @ my new company had PS 2.0 only. I’ve upgraded and registered the new version in my ISE (PrimalScript) and the script works like it should. Thanks again for the blog and all the help that it’s provided the community!
        Mike

        Like

  43. Daniel Petcher October 5, 2016 / 1:50 pm

    I love how you’ve brought Data Binding into the discussion so early. Is there any chance you’ll cover Validation in a tutorial soon? All the examples I’ve found online are in C-something, and I just have never grasped that language family’s ways of handling objects, even after reading June Blender’s citation of Keith Hill’s blog.

    Like

    • FoxDeploy October 6, 2016 / 10:20 am

      I’m planning on a series of transitioning to c# from Powershell, but that will be something for early next year.

      Like

  44. Rafael Acurcio October 8, 2016 / 11:14 pm

    Hey Foxdeploy

    What an awesome blog do you have!!! The way you write the posts it’s just so reader-friendly that makes it awesome!

    Following your tutorial I have been trying to make my own GUI however I got stuck with an error. It’s like the xaml generated by my visual studio is somewhat inappropriate. For ex:

    My textblock generated by visual studio:

    Your textblock:

    using my textblock generates an error and my windows doesn’t show up.

    Like

    • FoxDeploy October 8, 2016 / 11:28 pm

      First off, thanks for taking the time to write me. I always wantes to learn the things I cover in this blog, but couldn’t understand the guides that other people wrote. Since I learn by explaining things, I decided to start this blog.

      Can you put your full code on github as a gist or on pastebin and I’ll help you with this issue? Thanks!

      Like

      • rafaelacurcio October 8, 2016 / 11:58 pm

        Wow…what a fast repply! Back in Brazil it’s 2am… I was thinking that it would take until monday for you to you see this comment xD

        For some reason the code that I posted didn’t appear.
        but it was:

        My textblock generated by visual studio:

        **openTextBox tag** x:Name=”textBox” HorizontalAlignment=”Left” Height=”20″ Margin=”135,174,0,0″ TextWrapping=”Wrap” Text=”12313123123120938#01928301928.pdf” VerticalAlignment=”Top” Width=”358″ TextChanged=”textBox_TextChanged” **closeTextBox tag**

        Your textblock:

        **openTextBox tag** x:Name=”textBox” HorizontalAlignment=”Left” Height=”35″ Margin=”186,144,0,0″ TextWrapping=”Wrap” Text=”TextBox” VerticalAlignment=”Top” Width=”168″ FontSize=”16″ **closeTextBox tag**

        Here is my full XAML: http://pastebin.com/FiqHi3TP

        I could solve my problem by removing:

        TextChanged=”textBox_TextChanged”

        from my textbox element.

        Again, congrats for the awesome blog (and the fast repply!). keep it up! \o/

        Like

        • FoxDeploy October 9, 2016 / 10:33 am

          Remove the textchanged values. Sometimes when you double click an item in visual studio, it adds a text changed property. This works fine for a c# GUI but doesn’t work with the method we use here in PowerShell. I’m working to strip that property with the next version of the template, but haven’t done /gotten it done yet.

          Like

  45. Berry Miltenburg October 11, 2016 / 9:10 am

    Hi FoxDeploy

    i hope you could help me with my problem. Take a look at my code on http://pastebin.com/SK41xhNy
    Its just suppose to show localadmins on remote computers deppending on OU,Group or single computer. It works good in powershell but i needed to make a GUI for it just so other users could use it. The problem is that the column “Members” is showing as “System.Management.Automation.PSMemberInfoIntegratingCollection’1[System.management.automation.PsMemberInfo]”
    When resolving $arr in powershell it looks good but im not getting it to work with the GUI.

    Like

    • FoxDeploy October 12, 2016 / 9:25 am

      Change line 167 to this

      $WPFlistView.AddChild([pscustomobject]@{‘Computer’=$ComputerName;’Groupname’=$groupname;’Members’=$arr -join ‘;’})

      This issue came up because $arr might contain more than one item. PowerShell knows how to handle this, but our dumb GUI doesn’t know what to do. In this case, we used the -join operator to join all the separate items into a semicolon separated list.

      You may need to make similar changes elsewhere in your code.

      Like

      • Caleb Kroggmann October 12, 2016 / 12:11 pm

        I am trying to do something similar to this but have it pop up to an information box. I have everything working but the values are all in a one line string (just like they are in the above example). Is there a way to have each value on its own line so it looks like a list?

        Thanks in advance!

        Like

        • FoxDeploy October 13, 2016 / 10:22 am

          If you put each on it’s own line, you should just break them out into their own entries with .AddChild() for each. Pseudo code-

          $arr | ForEach {$listbox.AddChild($_)}

          Otherwise your end user might be confused by a multi-line listbox. If you REALLY wanna go that way, replace -join ‘;’ with -join ‘`n’ to try adding a new line. Not sure if it will render properly with that control though.

          Like

      • Berry Miltenburg October 13, 2016 / 2:03 am

        Ok, i tried that and no luck. I also added $arr = $null just to see if that worked, if i could get any output but not even that worked. I tried the code without GUi and then i got 1 string just like one item, but the GUI is still showing nothing. Any more ideas or should i just give up 🙂

        Thanks for your help!

        Like

        • FoxDeploy October 13, 2016 / 10:31 am

          this will work.

          forEach ($user in $arr){
          $WPFlistView.AddChild([pscustomobject]@{‘Computer’=$ComputerName;’Groupname’=$groupname;’Members’=$user})

          }

          Like

        • Berry Miltenburg October 14, 2016 / 1:17 am

          Thanks, that worked great!

          Like

  46. rainer-michael kennedy October 24, 2016 / 6:39 pm

    Absolutely amazing guide. I am new to adding GUI’s to Powershell so i’m not so good at the moment! 🙂

    I have completed the script however the Get-Variable WPF* is not finding anything, and when i run the script without the ‘ ‘ between the show dialog at the bottom, I just get a blank iVision Azure Accelerator pop-up.

    My code can be found here – http://pastebin.com/m4PauNm0

    Many Thanks!

    Like

    • FoxDeploy October 24, 2016 / 6:40 pm

      Thanks for posting a sample! I’ll check it out and get back to you later today

      Like

      • rainer-michael kennedy October 24, 2016 / 6:41 pm

        Much appreciated!

        I may have commented twice by accident… Apologies.

        Like

Have a code issue? Share your code by going to Gist.github.com and pasting your code there, then post the link here!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.