【问题标题】:Problems converting ps1 to exe using PowerGUI使用 PowerGUI 将 ps1 转换为 exe 的问题
【发布时间】:2015-11-16 13:15:49
【问题描述】:

我正在尝试将我的 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

【问题讨论】:

    标签: powershell powergui


    【解决方案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 变量中的代码中。

    【讨论】:

    • 感谢您的回复,我尝试了try/catch方法,但没有解决问题。我将尝试 C# WinForms,经过一些研究,我发现用它制作可执行文件要容易得多。我从一些人的博客中获得了 XML 位,并围绕它编写了代码,这就是我这样做的原因。
    【解决方案2】:

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

    CAVEAT:在大多数情况下(包括 PowerGUI)将 PowerShell“编译”为 EXE 是将原始 PS1 文件填充到自解压 EXE 中。你可以用 7-Zip 或 WinZip 做同样的事情。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-11
      • 2023-04-06
      • 1970-01-01
      • 2021-05-23
      • 2016-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多