Jerome Buholzer
Jerome Buholzer

Reputation: 31

Powershell can't load Windows.Markup.XamlReader

I just took the sample code from foxdeploy.com to create a PowerShell script with GUI.

It works on a Windows 10 machine, but for some reason it doesn't on a Windows 7 or Windows Server 2008 R2, where it should be running at the end (not this code but the final PS script with GUI).

Here's the code:

#ERASE ALL THIS AND PUT XAML BELOW between the @" "@
$inputXML = @"
<Window x:Class="WpfApplication2.MainWindow"
        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:WpfApplication2"
        mc:Ignorable="d"
        Title="FoxDeploy Awesome Tool" Height="416.794" Width="598.474" Topmost="True">
    <Grid Margin="0,0,45,0">
        <Image x:Name="image" HorizontalAlignment="Left" Height="100" Margin="24,28,0,0" VerticalAlignment="Top" Width="100" Source="C:\Users\Stephen\Dropbox\Docs\blog\foxdeploy favicon.png"/>
        <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="get-DiskInfo" HorizontalAlignment="Left" Height="35" Margin="393,144,0,0" VerticalAlignment="Top" Width="121" FontSize="18.667"/>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="35" Margin="186,144,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="168" FontSize="16"/>
        <Label x:Name="label" Content="ComputerName" HorizontalAlignment="Left" Height="46" Margin="24,144,0,0" VerticalAlignment="Top" Width="138" FontSize="16"/>
        <ListView x:Name="listView" HorizontalAlignment="Left" Height="156" Margin="24,195,0,0" VerticalAlignment="Top" Width="511" FontSize="16">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Drive Letter" DisplayMemberBinding ="{Binding 'Drive Letter'}" Width="120"/>
                    <GridViewColumn Header="Drive Label" DisplayMemberBinding ="{Binding 'Drive Label'}" Width="120"/>
                    <GridViewColumn Header="Size(MB)" DisplayMemberBinding ="{Binding Size(MB)}" Width="120"/>
                    <GridViewColumn Header="FreeSpace%" DisplayMemberBinding ="{Binding FreeSpace%}" Width="120"/>
                </GridView>
            </ListView.View>
        </ListView>

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

#===========================================================================
# Store Form 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
#===========================================================================

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

The script seems to fail at line 49 at the $Form.FindName

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

What I noticed so far, is that $Form doesn't return anything on Windows 7 while on Windows 10 it returns some properties. So I think the real problem is at line 42:

 try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."}

And when I execute the script just to line 43, it returns the catch-message.

So how can I fix this? The latest .NET version is installed and I guess the syntax should be alright because it works on Wondows 10.

Upvotes: 3

Views: 9994

Answers (3)

Chainick
Chainick

Reputation: 51

[Windows.Markup.XamlReader] requires the PresentationFramework assembly so add the following code at the beginning of your file:

Add-Type -Assembly PresentationFramework

Upvotes: 5

user2864830
user2864830

Reputation: 1

I know it's several years late. But i just ran into this issue playing around with WPF/Powershell.

I ended up going through and removing each item in groups , and then one by one, to see if it was one of the objects causing this error.

Turned out that when i was designing my WPF in visual studio i double clicked one, which i knew i did... just didnt think it would mess anything up.

The " TextChanged="EndHour_txtBox_Copy_TextChanged" line is what was throwing this erorr for me. Just something to look out for in the future. Not all WPF items work out of the box.

Upvotes: 0

fabrisodotps1
fabrisodotps1

Reputation: 132

I had the same problem. I have designed a form in VS 2015 Enterprise. The XAML was exactly the same as your (Tutorial from FoxDeploy). On my personal client (Windows 7, Powershell 4.0, .NET Framework 4.0) it was working fine. But when I was trying to launch the the script on a Windows Server 2008 R2 (Powershell 2.0, .NET 3.5) I ran into the same problem as you did. Updateing the .NET & Powershell version was not a opinion, bencause its a productive system where customers are using services. So I found a workaround to run my XAML on this environment:

I edited the XAML "window" tag from this:

<Window x:Class="WpfApplication2.MainWindow"
    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:WpfApplication2"
    mc:Ignorable="d"
    Title="FoxDeploy Awesome Tool" Height="416.794" Width="598.474" Topmost="True">

to this:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="FoxDeploy Awesome Tool" Height="416.794" Width="598.474" Topmost="True">

After this as a last step I had to run the powershell in single threaded apartment mode.

powershell -sta

Powershell ISE is already by default in this mode.

I can't explain why removed code made this error happening on the system but maybe I can help some other guys who have to fight with XAML & Powershell on an "old" windows environment.

Upvotes: 2

Related Questions