如何正确将XAML代码导入Powershell

时间:2019-05-14 15:50:45

标签: visual-studio powershell xaml

我正在尝试在Powershell中使用VisualStudio创建的GUI。

因此,我必须将Visual Studio中的XAML代码导入到脚本中

这是我到目前为止所得到的:

[xml]$XAML = @"
<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    <Grid Margin="0,0,2,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0*"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Name="Enter_Hostname_Label" Content="Enter Hostname:" HorizontalAlignment="Left" Height="26" Margin="9,19,0,0" VerticalAlignment="Top" Width="98" Grid.Column="1"/>
        <TextBox Name="Textbox" HorizontalAlignment="Left" Height="21" Margin="15,43,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="119" Grid.Column="1"/>
        <Label Name="Available_Hostnames_Label" Content="Available Hostnames:" HorizontalAlignment="Left" Height="26" Margin="11,83,0,0" VerticalAlignment="Top" Width="125" Grid.Column="1"/>
        <ListBox Name="Listbox" Grid.ColumnSpan="2" HorizontalAlignment="Left" Height="141" Margin="15,108,0,0" VerticalAlignment="Top" Width="119"/>
        <Button Name="Continue_Button" Grid.ColumnSpan="2" Content="Continue" HorizontalAlignment="Left" Height="21" Margin="143,108,0,0" VerticalAlignment="Top" Width="84" Click="Button_Click"/>
        <Button Name="Search_Button" Grid.ColumnSpan="2" Content="Search" HorizontalAlignment="Left" Height="21" Margin="143,43,0,0" VerticalAlignment="Top" Width="84" Click="Button_Click"/>
    </Grid>
</Window> 
"@ 

[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
try{
   $Form=[Windows.Markup.XamlReader]::Load( (New-Object System.Xml.XmlNodeReader $XAML) )
} catch {
   Write-Host "Windows.Markup.XamlReader konnte nicht geladen werden. Mögliche Ursache: ungültige Syntax oder fehlendes .net"
}
#Fenster anzeigen:
$Form.ShowDialog()

但是我收到一条错误消息,内容为: 该值不能转换为类型“ System.Xml.XmlDocument”。错误:“名称不允许以符号'<'开头,十六进制值为0x3C

但是我无法更改此设置,因为如果这样做,GUI代码将无法工作

我在互联网上进行了很多搜索,但找不到解决方案。似乎对每个这样的人都有效

有人可以告诉我我的脚本出了什么问题吗?

2 个答案:

答案 0 :(得分:0)

要添加按钮单击处理程序,可以在WPF外部指定操作,如下所示:

[xml]$XAML = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <Grid Margin="0,0,2,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0*"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Name="Enter_Hostname_Label" Content="Enter Hostname:" HorizontalAlignment="Left" Height="26" Margin="9,19,0,0" VerticalAlignment="Top" Width="98" Grid.Column="1"/>
        <TextBox Name="Textbox" HorizontalAlignment="Left" Height="21" Margin="15,43,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="119" Grid.Column="1"/>
        <Label Name="Available_Hostnames_Label" Content="Available Hostnames:" HorizontalAlignment="Left" Height="26" Margin="11,83,0,0" VerticalAlignment="Top" Width="125" Grid.Column="1"/>
        <ListBox Name="Listbox" Grid.ColumnSpan="2" HorizontalAlignment="Left" Height="141" Margin="15,108,0,0" VerticalAlignment="Top" Width="119"/>
        <Button Name="Continue_Button" Grid.ColumnSpan="2" Content="Continue" HorizontalAlignment="Left" Height="21" Margin="143,108,0,0" VerticalAlignment="Top" Width="84" />
        <Button Name="Search_Button" Grid.ColumnSpan="2" Content="Search" HorizontalAlignment="Left" Height="21" Margin="143,43,0,0" VerticalAlignment="Top" Width="84" /> 
    </Grid>
</Window> 
"@ 
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
$Form=[Windows.Markup.XamlReader]::Load( (New-Object System.Xml.XmlNodeReader $XAML) )
$Form.FindName('Continue_Button').add_Click({
    param([System.Windows.Controls.Button]$sender, $e)
    Write-Host 'some action here'
})
$Form.ShowDialog()

答案 1 :(得分:0)

有关如何使用Visual Studio创建PowerShell GUI的完整系列。

使用Visual Studio在几分钟内创建PowerShell GUI –一个新希望

https://foxdeploy.com/2015/04/10/part-i-creating-powershell-guis-in-minutes-using-visual-studio-a-new-hope

https://foxdeploy.com/2015/04/16/part-ii-deploying-powershell-guis-in-minutes-using-visual-studio

有很多屏幕截图和分步说明来做到这一点。因此无法在此处发布。对于XAML,作者提供了以下示例:

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

<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="524.256" Width="332.076">    
    <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="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="UserName" HorizontalAlignment="Left" Height="46" Margin="56,162,0,0" VerticalAlignment="Top" Width="138" FontSize="16"/>
</Grid>
</Window>

将其导入PowerShell

#Your XAML goes here :)
$inputXML = @"
<Window x:Class="Azure.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="524.256" Width="332.076">
    <Grid Margin="0,0,174,0">
    </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}
    }

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

#===========================================================================
# Use this space to add code to the various form elements in your GUI
#===========================================================================


#Reference 

#Adding items to a dropdown/combo box
    #$vmpicklistView.items.Add([pscustomobject]@{'VMName'=($_).Name;Status=$_.Status;Other="Yes"})

#Setting the text of a text box to the current PC name    
    #$WPFtextBox.Text = $env:COMPUTERNAME

#Adding code to a button, so that when clicked, it pings a system
# $WPFbutton.Add_Click({ Test-connection -count 1 -ComputerName $WPFtextBox.Text
# })
#===========================================================================
# Shows the form
#===========================================================================
write-host "To show the form, run the following" -ForegroundColor Cyan
'$Form.ShowDialog() | out-null'