使用嵌入式 XAML GUI 在 Powershell 脚本中更改标题栏图标
Changing title bar icon in Powershell script with embedded XAML GUI
这是我的第一个 post。我正在 Powershell 中编写一个脚本启动器应用程序,其中包含用于 GUI 的嵌入式 XAML 代码。 XAML 在 Visual Studio 中进行了粗略处理,然后导出到 Powershell 并手动进行了调整。简单且可维护,但我一直在尝试更改应用程序的标题栏图标。更改图标是内部品牌需要。
通用 Powershell 图标确实出现在我的应用程序的标题栏中。我想我已经尝试采用本网站和其他地方提到的每一种 XAML 和 code-behind 技术来安装我自己的 ICO 图标。没有快乐。有些需要使用 Visual Studio,我希望不要再使用它。最简单的建议 XAML 路线似乎是添加这样一行...
Icon="MyFavicon.ico"
...在下面测试台的标题行下方。但这会引发此错误:
Exception calling "Load" with "1" argument(s): "Failed to create a 'Icon' from the text 'StribLogoFavicon.ico'."
At M:\Scripting\Saxophone\Test\trivial_xaml_and_ps_for_icon_troubleshooting_v18.ps1:26 char:2
+ $Window = [Windows.Markup.XamlReader]::Load($Reader)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : XamlParseException
You cannot call a method on a null-valued expression.
At M:\Scripting\Saxophone\Test\trivial_xaml_and_ps_for_icon_troubleshooting_v18.ps1:28 char:1
+ $Window.ShowDialog()
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
FWIW,同一个 ICO 文件以前在该项目的 HTA 版本的标题栏中工作。我还尝试了第二个 ICO 文件。
ICO 文件的位置对于我的部署目的并不重要。我试过脚本的根文件夹和子文件夹。
这是我项目的基本框架。谁能提出解决方案?也许我们可以使用这个测试平台来记录一个易于确认的测试平台。谢谢!
#Trivial pared-down app GUI for icon troubleshooting
Add-Type -AssemblyName presentationframework, presentationcore, windowsbase
#Begin XAML code for GUI
[xml]$xaml = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Demo_WPF_Window"
Title="How to change icon at left?" Height="150" Width="320" WindowStyle="SingleBorderWindow" Background="#FFECBD5A" ResizeMode="NoResize"
>
<Grid x:Name="Grid">
<Grid Margin="18,64,0,18">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="126*"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
</Grid>
<Label x:Name="Label_Icon_testbed" Content="Icon is ICO file in same folder as PS1 script" HorizontalAlignment="Left" Height="45" Margin="19,10,0,0" VerticalAlignment="Top" Width="240" FontSize="11" FontWeight="Bold" Grid.ColumnSpan="2"/>
</Grid>
</Window>
"@
#Prepare the GUI
$Reader = New-Object System.Xml.XmlNodeReader $xaml
$Window = [Windows.Markup.XamlReader]::Load($Reader)
#Render the GUI
$Window.ShowDialog()
我能够通过在 Window 加载事件中设置图标来添加图标:
#region Load the Assemblies
Add-Type -assemblyName PresentationFramework
Add-Type -assemblyName PresentationCore
Add-Type -assemblyName WindowsBase
#endregion
#region XAML
[xml]$XAML = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Testing" Height="200" Width="300" >
</Window>
"@
#endregion XAML
#Load the XAML and catch a failure
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{$Window=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host "Unable to load Windows.Markup.XamlReader. Some possible causes for this problem include: .NET Framework is missing PowerShell must be launched with PowerShell -sta, invalid XAML code was encountered."; exit}
##XAML Should have loaded NOW
#Set all "Names" as Variables
$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object{
Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name)
}
#region EVENTS
$Window.add_Loaded({
$Window.Icon = "C:\Path\to\Icon.ico"
})
#endregion EVENTS
##Show the Window - Wrap ShowDialog in the Async Dispatcher to prevent powershell from crashing on second run
$async = $window.Dispatcher.InvokeAsync({
$window.ShowDialog() | Out-Null
})
$async.Wait() | Out-Null
这是 Shamus 的有效答案 -- 非常感谢! -- 与上面测试平台代码的底部集成:
$Reader = New-Object System.Xml.XmlNodeReader $xaml
$Window = [Windows.Markup.XamlReader]::Load($Reader)
$Window.add_Loaded({
$Window.Icon = "C:\full\path\to\favicon.ico"
})
$Window.ShowDialog()
这是我的第一个 post。我正在 Powershell 中编写一个脚本启动器应用程序,其中包含用于 GUI 的嵌入式 XAML 代码。 XAML 在 Visual Studio 中进行了粗略处理,然后导出到 Powershell 并手动进行了调整。简单且可维护,但我一直在尝试更改应用程序的标题栏图标。更改图标是内部品牌需要。
通用 Powershell 图标确实出现在我的应用程序的标题栏中。我想我已经尝试采用本网站和其他地方提到的每一种 XAML 和 code-behind 技术来安装我自己的 ICO 图标。没有快乐。有些需要使用 Visual Studio,我希望不要再使用它。最简单的建议 XAML 路线似乎是添加这样一行...
Icon="MyFavicon.ico"
...在下面测试台的标题行下方。但这会引发此错误:
Exception calling "Load" with "1" argument(s): "Failed to create a 'Icon' from the text 'StribLogoFavicon.ico'."
At M:\Scripting\Saxophone\Test\trivial_xaml_and_ps_for_icon_troubleshooting_v18.ps1:26 char:2
+ $Window = [Windows.Markup.XamlReader]::Load($Reader)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : XamlParseException
You cannot call a method on a null-valued expression.
At M:\Scripting\Saxophone\Test\trivial_xaml_and_ps_for_icon_troubleshooting_v18.ps1:28 char:1
+ $Window.ShowDialog()
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
FWIW,同一个 ICO 文件以前在该项目的 HTA 版本的标题栏中工作。我还尝试了第二个 ICO 文件。
ICO 文件的位置对于我的部署目的并不重要。我试过脚本的根文件夹和子文件夹。
这是我项目的基本框架。谁能提出解决方案?也许我们可以使用这个测试平台来记录一个易于确认的测试平台。谢谢!
#Trivial pared-down app GUI for icon troubleshooting
Add-Type -AssemblyName presentationframework, presentationcore, windowsbase
#Begin XAML code for GUI
[xml]$xaml = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Demo_WPF_Window"
Title="How to change icon at left?" Height="150" Width="320" WindowStyle="SingleBorderWindow" Background="#FFECBD5A" ResizeMode="NoResize"
>
<Grid x:Name="Grid">
<Grid Margin="18,64,0,18">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="126*"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
</Grid>
<Label x:Name="Label_Icon_testbed" Content="Icon is ICO file in same folder as PS1 script" HorizontalAlignment="Left" Height="45" Margin="19,10,0,0" VerticalAlignment="Top" Width="240" FontSize="11" FontWeight="Bold" Grid.ColumnSpan="2"/>
</Grid>
</Window>
"@
#Prepare the GUI
$Reader = New-Object System.Xml.XmlNodeReader $xaml
$Window = [Windows.Markup.XamlReader]::Load($Reader)
#Render the GUI
$Window.ShowDialog()
我能够通过在 Window 加载事件中设置图标来添加图标:
#region Load the Assemblies
Add-Type -assemblyName PresentationFramework
Add-Type -assemblyName PresentationCore
Add-Type -assemblyName WindowsBase
#endregion
#region XAML
[xml]$XAML = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Testing" Height="200" Width="300" >
</Window>
"@
#endregion XAML
#Load the XAML and catch a failure
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{$Window=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host "Unable to load Windows.Markup.XamlReader. Some possible causes for this problem include: .NET Framework is missing PowerShell must be launched with PowerShell -sta, invalid XAML code was encountered."; exit}
##XAML Should have loaded NOW
#Set all "Names" as Variables
$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object{
Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name)
}
#region EVENTS
$Window.add_Loaded({
$Window.Icon = "C:\Path\to\Icon.ico"
})
#endregion EVENTS
##Show the Window - Wrap ShowDialog in the Async Dispatcher to prevent powershell from crashing on second run
$async = $window.Dispatcher.InvokeAsync({
$window.ShowDialog() | Out-Null
})
$async.Wait() | Out-Null
这是 Shamus 的有效答案 -- 非常感谢! -- 与上面测试平台代码的底部集成:
$Reader = New-Object System.Xml.XmlNodeReader $xaml
$Window = [Windows.Markup.XamlReader]::Load($Reader)
$Window.add_Loaded({
$Window.Icon = "C:\full\path\to\favicon.ico"
})
$Window.ShowDialog()