再次感謝您對我上一個問題的幫助,但我遇到了另一個問題。如上所述,如果在 cmd 中運行,下面代碼中的 exe 會在運行時立即輸出進度。
然而,表單中的文本框是空白的,并且有延遲,在整個輸出被粘貼到文本框之前看起來什么都沒有發生。
我在網上看過并提到了一個 forms.application do events 方法,但不推薦使用它并且有點草率。
我有什么想法可以讓這個現場直播嗎?我確實嘗試了一個訊息框,但我需要在 exe 運行之前關閉它,我仍然需要等待。
我指的是 xiso_build 函式中 xtract-iso.exe 的文本框輸出
代碼:
Function xiso_build {
Set-Location -Path $PSScriptRoot # change to root folder of this script wherever it's run from
[System.Windows.Forms.Messagebox]::Show("Building, Please Wait...")
$outputBox.text= & .\extract-xiso.exe -r $selected_file 2>&1 | out-string # '2>&1' needs to be there otherwise any errors get outputted to terminal, out-string for better formatting
}
##########################################################################################################################
# the main form
$form = New-Object System.Windows.Forms.Form
$form.StartPosition = 'CenterScreen'
$form.Text = 'Xbox Iso Extractor'
$form.Size = '600,600'
# Choose iso label
# Create a "computer name" label control and add it to the form
# Set label location, text, size, etc
$Label1 = New-Object Windows.Forms.Label
$label1.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 12, [System.Drawing.FontStyle]::Bold)
$Label1.Size = '180,40'
$Label1.Location = '10,20'
$Label1.Text = "Select An Xbox ISO:"
$Label1.Font.Bold
$form.Controls.Add($Label1)
# textbox
$isotextBox = New-Object System.Windows.Forms.TextBox
$isotextBox.Location = '10,60'
$isotextBox.Size = '320,200'
$form.Controls.Add($isotextBox)
# open file button
$Select_Iso_button = New-Object System.Windows.Forms.button
$Select_Iso_button.Text = 'Choose ISO'
$Select_Iso_button.Size = '100,25'
$Select_Iso_button.Location = '350,60'
$form.controls.Add($Select_Iso_button)
# below code: on click run 'iso_open func above and run global '$selected_file_path' variable from fun, then insert path and file into textbox
# save this selected text into var called $selected_file then execute var
$Select_Iso_button.Add_Click({iso_open; $global:selected_file = $isotextBox.Text = $selected_file_path; $selected_file})
# Output of xtract-iso textbox
$outputBox = New-Object System.Windows.Forms.TextBox #creating the text box
$outputBox.Location = '10,150' #location of the text box (px) in relation to the primary window's edges (length, height)
$outputBox.Size = New-Object System.Drawing.Size(565,200) #the size in px of the text box (length, height)
$outputBox.MultiLine = $True #declaring the text box as multi-line
$outputBox.ScrollBars = "Vertical" #adding scroll bars if required
$form.Controls.Add($outputBox) #activating the text box inside the primary window
# Build Iso Button
$build_button = New-Object System.Windows.Forms.button
$build_button.Text = 'Build ISO'
$build_button.Size = '200,50'
$build_button.Location = '10,360'
# $button.Anchor = 'Bottom,left' # uncomment to move button down to bottom left of app window
$form.Controls.Add($build_button)
$build_button.Add_Click({xiso_build}) # run 'xiso_build' func from above
uj5u.com熱心網友回復:
默認情況下,在將輸入物件的格式化表示輸出為單個多行字串之前,首先收集所有輸入。[1]Out-String
為了從執行的命令中獲得近乎實時的反饋,您需要在行可用時$output.Text 迭代地附加行,您可以通過呼叫來完成:ForEach-Object
$sep = ''; $outputBox.text = ''
& .\extract-xiso.exe -r $selected_file 2>&1 |
ForEach-Object {
# Append the line at hand to the text box.
$outputBox.AppendLine($sep $_); $sep = "`n"
# Keep the form responsive - THIS MAY NOT BE ENOUGH - see below.
[System.Windows.Forms.Application]::DoEvents()
}
[System.Windows.Forms.Application]::DoEvents()[2]用于在命令執行時保持表單回應,但請注意,這依賴于您的.\extract-xiso.exe呼叫生成的連續輸出行以相對較短的連續發出(原因是表單無法處理任何用戶事件,而 PowerShell 是等待發出下一個輸出行)。
如果這不能使您的表單保持足夠的回應速度,您將需要一種不同的方法,例如使用后臺作業來運行您的可執行檔案,并使用.Show()而不是.ShowDialog()來顯示您的表單,并使用后續的手動[System.Windows.Forms.Application]::DoEvents()回圈定期輪詢后臺新輸出線的作業。
以下簡化的獨立示例演示了此方法:
Add-Type -AssemblyName System.Windows.Forms
# === Helper functions:
# Launches the external program in a a background job and store
# the job-inf variable in script-level variable $job.
function Start-ExtractionJob {
$script:job = Start-Job {
# Simulate a long-running call to an external program.
# Here is where you'd make your & .\extract-xiso.exe ... call
1..20 | % { cmd /c "echo line $_" 2>&1; Start-Sleep 1 }
}
}
# Adds an output line to the $ouputBox text box
function Add-TextBoxLine {
param([string] $line)
if ($prevLen = $outputBox.Text.Length) {
$sep = "`r`n"
}
else {
$sep = ''
}
$outputBox.AppendText($sep $line)
# Scroll to the *start* of the new line to prevent horizontal scrolling.
$outputBox.Select($prevLen $sep.Length, 0)
}
# === Create the form.
$form = [System.Windows.Forms.Form] @{
StartPosition = 'CenterScreen'
Text = 'Xbox Iso Extractor'
Size = '600,600'
}
# Mutiline text box that will receive the program's output, line by line.
$outputBox = [System.Windows.Forms.TextBox] @{
Location = '10,150'
Size = [System.Drawing.Size]::new(565, 200)
MultiLine = $true
ScrollBars = "Vertical" #adding scroll bars if required
}
$form.Controls.Add($outputBox)
# Build Iso Button
$build_button = [System.Windows.Forms.Button] @{
Text = 'Build ISO'
Size = '200,50'
Location = '10,360'
}
$form.Controls.Add($build_button)
# Set up the button event handler for launching
# the external program in a background job.
$build_button.Add_Click({
$this.Enabled = $false
$outputBox.Clear()
Add-TextBoxLine "=== Launching..."
Start-ExtractionJob
})
# --- Manage display of the form and handle job output.
$job = $null
$form.Show() # Show form asynchronously.
while ($form.Visible) {
# While the form is visible, process events periodically.
[System.Windows.Forms.Application]::DoEvents()
# If a job has been launched, collect its output on an ongoing basis.
# If the job has completed, remove it, and reenable the launch button.
if ($job) {
$job | Receive-Job | ForEach-Object {
# $outputBox.Text = $nl $_; $outputBox.Select($outputBox.Text.Length $nl.Length, 0); $outputBox.ScrollToCaret()
Add-TextBoxLine $_
}
# Check if the job has terminated, for whatever reason.
if ($job.State -in 'Completed', 'Failed') {
$job | Remove-Job; $job = $null
Add-TextBoxLine '=== Completed'
$build_button.Enabled = $true
}
# Sleep a little.
Start-Sleep -Milliseconds 100
}
}
# ... clean up job, if necessary, ...
[1] 雖然有一個-Stream開關可以逐行輸出格式化表示的行,但這在這里無濟于事,因為實時反饋的關鍵是$output.Text 迭代分配,因為行可用。
[2][System.Windows.Forms.Application]::DoEvents()通常可能會出現問題(它本質上是阻塞.ShowDialog()呼叫在幕后回圈中所做的),但在這種受限場景中(假設只顯示一種形式)它應該沒問題。有關背景資訊,請參閱此答案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/537456.html
標籤:电源外壳窗体
