1

我正在尝试将我的 PowerShell 项目转换为可执行程序 (.exe)。经过一番研究,我找到了 PowerGUI。将我的 .ps1 文件转换为 exe 后,我遇到了一些问题:

首先,启动程序需要很长时间(大约 15 秒),这是正常的还是我可以做些什么来改善它?

其次,如果我退出程序,我会收到一条 Windows 错误消息,说明程序意外停止工作。有没有办法隐藏这条消息?

这是我的 ps1 代码,我从博客中获得了其中的一部分,这是我的第一个 PowerShell 代码,所以不要对我苛刻;)

 $inputXML = @"
<Window x:Class="BlogPostIII.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:BlogPostIII"
        mc:Ignorable="d"
        Title="Organizer" Height="540" Width="540" FontSize="18.667">
    <Grid x:Name="background">
        <Button x:Name="OK" Content="OK" HorizontalAlignment="Left" Height="41" Margin="420,458,0,0" VerticalAlignment="Top" Width="100" FontSize="18.667"/>
        <Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Left" Height="41" Margin="315,458,0,0" VerticalAlignment="Top" Width="100" FontSize="18.667"/>
        <TextBox x:Name="TextBox1" HorizontalAlignment="Left" Height="30" Margin="108,216,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBlock x:Name="TextBlock1" HorizontalAlignment="Left" Height="30" Margin="108,36,0,0" TextWrapping="Wrap" Text="Soort bewerking:" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBox x:Name="TextBox2" HorizontalAlignment="Left" Height="30" Margin="108,291,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBlock x:Name="TextBlock2" HorizontalAlignment="Left" Height="30" Margin="108,111,0,0" TextWrapping="Wrap" Text="Naam Machine:" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBox x:Name="TextBox3" HorizontalAlignment="Left" Height="30" Margin="108,366,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBlock x:Name="TextBlock3" HorizontalAlignment="Left" Height="30" Margin="108,185,0,0" TextWrapping="Wrap" Text="Naam van opdrachtgevend bedrijf:" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBlock x:Name="TextBlock4" HorizontalAlignment="Left" Height="30" Margin="108,261,0,0" TextWrapping="Wrap" Text="Naam product:" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <TextBlock x:Name="TextBlock5" HorizontalAlignment="Left" Height="30" Margin="108,336,0,0" TextWrapping="Wrap" Text="Product ID:" VerticalAlignment="Top" Width="300" FontSize="18.667"/>
        <ComboBox x:Name="combobox1" HorizontalAlignment="Left" Margin="108,66,0,0" VerticalAlignment="Top" Width="300"/>
        <ComboBox x:Name="combobox2" HorizontalAlignment="Left" Margin="108,140,0,0" VerticalAlignment="Top" Width="300"/>
    </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

#===========================================================================
# List the Comboboxes
#===========================================================================

$WPFcombobox1.AddText('Draaien')
$WPFcombobox1.AddText('Frezen')
$WPFcombobox1.AddText('Slijpen')

$WPFcombobox2.AddText('Doosan 3100LM')
$WPFcombobox2.AddText('Doosan 123')
$WPFcombobox2.AddText('machine 3')
$WPFcombobox2.AddText('machine 4')
$WPFcombobox2.AddText('machine 5')


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


#$WPFMakeUserbutton.Add_Click({(Get-FormFields)})


$WPFOK.Add_Click({
    $1 = $WPFcomboBox1.Text
    $2 = $WPFcomboBox2.Text
    $3 = $WPFtextBox1.Text
    $4 = $WPFtextBox2.Text
    $5 = $WPFtextBox3.Text + " Werkblad"
    New-Item C:\Users\Bjorn\Documents\Powershell\$1\$2\$3\$4\ -Force -type directory
    Copy-Item C:\Users\Bjorn\Documents\Powershell\Test_werkblad.docx C:\Users\Bjorn\Documents\Powershell\$1\$2\$3\$4\
    Rename-Item C:\Users\Bjorn\Documents\Powershell\$1\$2\$3\$4\Test_werkblad.docx C:\Users\Bjorn\Documents\Powershell\$1\$2\$3\$4\$5.docx
    Invoke-Item C:\Users\Bjorn\Documents\Powershell\$1\$2\$3\$4
    Invoke-Item C:\Users\Bjorn\Documents\Powershell\$1\$2\$3\$4\$5.docx
    $Form.Close()})

$WPFCancel.Add_Click({
    $Form.Close()})


#===========================================================================
# Shows the form
#===========================================================================
write-host "To show the form, run the following" -ForegroundColor Cyan

function Show-Form{
$Form.ShowDialog() | out-null

}

Show-Form
4

2 回答 2

1

15 秒的暂停是 PowerShell 在后台初始化。这在 Windows 7 上尤其明显

警告:在大多数情况下(包括 PowerGUI)将 PowerShell“编译”为 EXE 是将原始 PS1 文件填充到自解压 EXE 中。您可以使用 7-Zip 或 WinZip 执行相同的操作。

PowerGUI“已编译”的 EXE 将您的脚本执行锁定到您在 DEV 盒上拥有的任何版本或 PowerShell + .Net。IOW:如果您在使用 PowerShell v4 的 PC 上编译但仅在脚本中使用 Write-host(例如),则目标 PC 将需要 PowerShell v4+ 才能运行!

于 2015-11-16T15:52:35.633 回答
1

大约15 秒我不知道为什么。你能提供更多细节吗?您应该在每条消息中添加日志记录并添加时间戳...这样您应该能够找到慢速部分。

关于避免错误消息,你应该用try/catch包围你的代码。例如:

    [...]

    write-host "To show the form, run the following" -ForegroundColor Cyan

    function Show-Form
    {
     $Form.ShowDialog() | out-null
    }

    try
    {
     Show-Form
    }
    catch
    {
     $ErrorMessage = $_.Exception.Message
     # Show friendly message with error and/or log the error)
    }

阅读您的代码后,这里有一些可能有用的额外建议:

  • 不要硬编码路径。(如“C:\Users\Bjorn\Documents\Powershell\”)
  • 你真的需要 PowerShell 吗?听起来 C# WinForms 会更好地完成这项任务。
  • 将 XML 存储在文件中并读取它,而不是将其放在 $inputXML 变量中的代码中。
于 2015-11-16T13:24:39.223 回答