How to use correct runspace in powershell?

56 views Asked by At

I have GUI with button, I want to show GUI and keep doing some process. If the process finished, I need to click button and do some process too.

I have updated my code to use runspace:

    Add-Type -AssemblyName System.Windows.Forms

# Create the runspace
$Runspace = [runspacefactory]::CreateRunspace()
$Runspace.ApartmentState = [System.Threading.ApartmentState]::STA
$Runspace.Open()

# Create the PowerShell session and assign the runspace
$PS = [powershell]::Create()
$PS.Runspace = $Runspace

# Define the code for the form
$formScript = {
    Add-Type -AssemblyName System.Drawing
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName PresentationFramework
    [System.Windows.Forms.Application]::EnableVisualStyles()

    #--- create main form ---#
    # get screen info, if multiple screen, get the primary one.
    $screen_info = [System.Windows.Forms.Screen]::AllScreens
    $screen_width = $screen_info[0].WorkingArea.Width
    $screen_height = $screen_width * (9 / 16) - 40

    # Get the screen's DPI
    $screenDpiYArea = [Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Height

    # Calculate a base font size (adjust this as needed)
    if ($screenDpiYArea -eq 1032) {
        $base_fontsize = 0.02
        $warning_adjust = 1.5
    }
    elseif ($screenDpiYArea -eq 1200) {
        $base_fontsize = 0.015
        $warning_adjust = 2
    }


    # Calculate the adjusted font size based on DPI
    $adjusted_fontSize = ($screenDpiYArea * $base_fontsize) / 2

    # Icon resize
    $base_iconsize = 0.05
    $pictureBoxHeight = ($screenDpiYArea * $base_iconsize) / 2

    # Label location
    $base_labelY = 0.006
    $adjusted_location = ($screenDpiYArea * $base_labelY) / 2

    # main form cottingnfigurationnfiguration
    $main_form = New-Object System.Windows.Forms.Form 
    $main_form.AutoSize = $True
    $main_form.ShowIcon = $false
    $main_form.AutoScroll = $True
    $main_form.ControlBox = $false
    $main_form.WindowState = "Normal"
    $main_form.MaximizeBox = $false
    $main_form.StartPosition = "CenterScreen"
    $main_form.FormBorderStyle = "Sizable"
    $main_form.Add_KeyDown( {
            if ($_.KeyCode -eq "Escape") 
            { $main_form.Close() }
        
        }
    )

    # adjust screen size if < 1280
    if ($screen_width -le 1280) {
        Write-Host "-le 1280"
        $main_form.Size = New-Object System.Drawing.Size( ($screen_width / 1.3), ($screen_height * 1.2))
        $header_height = 5
        $header_width = 22
    }
    elseif ($screen_width -gt 1280 -or $screen_width -lt 1367) {
        Write-Host "-gt 1280"
        $main_form.Size = New-Object System.Drawing.Size( ($screen_width / 1.5), ($screen_height / 1.2) )
        $header_height = 6
        $header_width = 25
    }
    elseif ($screen_width -ge 1920) {
        Write-Host "-ge 1920"
        $main_form.Size = New-Object System.Drawing.Size( ($screen_width / 2.5), ($screen_height / 2) )
    }
    else {
        Write-Host "els"
        $main_form.Size = New-Object System.Drawing.Size( ($screen_width / 2), ($screen_height / 1.5) )
    }
    # set up up pannel
    $panel_up = New-Object system.Windows.Forms.Panel
    $panel_up_height = $main_form.height / 17
    $panel_up.width = $main_form.Width
    $panel_up.height = $panel_up_height
    $panel_up.AutoSize = $true
    $panel_up.Dock = [System.Windows.Forms.DockStyle]::Top
    $panel_up.location = New-Object System.Drawing.Point(3, -2)
    $panel_up.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#77B1AD")
    $main_form.Controls.Add($panel_up)

    # set up title bar
    $label_up = New-Object System.Windows.Forms.Label
    $label_up.Size = New-Object System.Drawing.Size(($main_form.Width * 1.1), 80)
    $label_up.Font = New-Object System.Drawing.Font("Tahoma", ($main_form.width / 60), [System.Drawing.FontStyle]::Bold, [System.Drawing.GraphicsUnit]::Pixel)
    $label_up.Text = "Tool"
    $label_up.AutoSize = $true
    $label_up.Location = New-Object System.Drawing.Size(($main_form.Size.Width / $header_width), ($panel_up_height / $header_height))
    $label_up.ForeColor = "#FFFFFF"
    $panel_up.Controls.Add($label_up)

    # set up logo
    [reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
    $get_logo = (Get-Item ".\LOGO.png")
    $logo = [System.Drawing.Image]::Fromfile($get_logo)
    $pictureBox = New-object Windows.Forms.PictureBox
    $pictureBox.Image = $logo
    $pictureBox.SizeMode = "Autosize"
    $pictureBox.location = New-Object System.Drawing.Point(5, ($panel_up_height / 8))
    $panel_up.controls.add($pictureBox)

    # Calculate the space to leave for buttons at the bottom
    $buttonSpace = $main_form.Height / 5.5  # Adjust this value as needed

    # set up bottom panel 
    $panel_bottom = New-Object System.Windows.Forms.Panel
    $panel_bottom.width = $panel_up.Width 
    $panel_bottom.height = 1.2
    $panel_bottom.AutoSize = $true
    $panel_bottom.Location = New-Object System.Drawing.Point(3, ($main_form.Height - $buttonSpace))
    $panel_bottom.BackColor = "#7BB0AD"
    $main_form.Controls.Add($panel_bottom)

    # Calculate the remaining space after the bottom panel
    $remainingSpace = $main_form.Height - ($panel_bottom.Location.Y + $panel_bottom.Height)

    # Calculate the vertical position for buttons in the middle of the remaining space
    $buttonHeightPosition = $panel_bottom.Location.Y + $panel_bottom.Height + ($remainingSpace - 30) / 3.5

    # Create and configure the first button
    $button_close = New-Object System.Windows.Forms.Button
    $button_close.Text = "Close"
    $button_close.Size = New-Object System.Drawing.Size(100, 30)
    $button_close.Location = New-Object System.Drawing.Point(($panel_bottom.Width - 120), $buttonHeightPosition)
    $button_close.Font = New-Object System.Drawing.Font("Tahoma", $adjusted_fontSize)  # Adjust the font size as needed
    $button_close.BackColor = "#F2F4EF"
    $main_form.Controls.Add($button_close)

    # Create and configure the second button
    $button_reboot = New-Object System.Windows.Forms.Button
    $button_reboot.Text = "Reboot"
    $button_reboot.Size = New-Object System.Drawing.Size(100, 30)
    $button_reboot.Location = New-Object System.Drawing.Point(($panel_bottom.Width - 240), $buttonHeightPosition)
    $button_reboot.Font = New-Object System.Drawing.Font("Tahoma", $adjusted_fontSize)  # Adjust the font size as needed
    $main_form.Controls.Add($button_reboot)

    # Create and configure the third button
    $button_shutdown = New-Object System.Windows.Forms.Button
    $button_shutdown.Text = "Shutdown"
    $button_shutdown.Size = New-Object System.Drawing.Size(100, 30)
    $button_shutdown.Location = New-Object System.Drawing.Point(($panel_bottom.Width - 360), $buttonHeightPosition)
    $button_shutdown.Font = New-Object System.Drawing.Font("Tahoma", $adjusted_fontSize)  # Adjust the font size as needed
    $main_form.Controls.Add($button_shutdown)

    # Create and configure the first panel for processing information
    $global:panel_processing = New-Object System.Windows.Forms.GroupBox
    $panel_processing.Width = $main_form.Width / 1.5
    $panel_processing.Height = ($main_form.Height - $panel_up_height - $remainingSpace) - 100
    $panel_processing.Location = New-Object System.Drawing.Point(7, ($panel_up.Height * 1.9))
    $panel_processing.BackColor = "#F2F4EF"
    $panel_processing.Text = "F l o w   S t e p"
    $panel_processing.Font = New-Object System.Drawing.Font("Tahoma", $adjusted_fontSize)
    $main_form.Controls.Add($panel_processing)

    # Create and configure the second panel (beside processing panel)
    $panel_config = New-Object System.Windows.Forms.GroupBox
    $panel_config.Width = ($main_form.Width - $panel_processing.Width ) - 50
    $panel_config.Height = $panel_processing.Height
    $panel_config.Location = New-Object System.Drawing.Point(($panel_processing.Right + 18), ($panel_up.Height * 1.9))
    $panel_config.BackColor = "#F2F4EF"
    $panel_config.Text = "C o n f i g u r a t i o n"
    $panel_config.Font = New-Object System.Drawing.Font("Tahoma", $adjusted_fontSize)
    $panel_config.ForeColor = "#676565"

    $main_form.Controls.Add($panel_config)


    # Create a gradient brush
    $gradientBrush = New-Object System.Drawing.Drawing2D.LinearGradientBrush(
        $main_form.ClientRectangle,
        "#F2F4EF",
        "#77B1AD", 
        [System.Drawing.Drawing2D.LinearGradientMode]::Horizontal
    )

    # Paint event to draw the gradient background
    $main_form.Add_Paint({
            $eventArgs = $_
            $graphics = $eventArgs.Graphics
            $graphics.FillRectangle($gradientBrush, $main_form.ClientRectangle)
        })
   
    # Create a button on the main form
    $button_close.Add_Click({
            # Display a confirmation dialog
            $confirmation = [System.Windows.Forms.MessageBox]::Show("Are you sure you want to reboot the unit?", "Reboot Confirmation", [System.Windows.Forms.MessageBoxButtons]::OKCancel, [System.Windows.Forms.MessageBoxIcon]::Question)

            # If the user clicks OK, simulate a delay and then show the reboot message
            if ($confirmation -eq [System.Windows.Forms.DialogResult]::OK) {
                Start-Sleep -Seconds 2  # Simulate a delay of 2 seconds

                # Simulate the reboot message
                Add-Type -AssemblyName System.Windows.Forms
                [System.Windows.Forms.MessageBox]::Show("Simulating unit reboot...`nUnit rebooted successfully.", "Reboot Simulation", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)

                # Perform the actual reboot
                $main_form.Close()
            }
        })

    # Add the button to the main form
    $main_form.Controls.Add($btnStart)

    # Show the main form
    [Windows.Forms.Application]::Run($main_form)
}

# Run the form script in a separate runspace
$FormPS = [powershell]::Create()
$FormPS.Runspace = $Runspace
$FormPS.AddScript($formScript)
$AsyncHandle = $FormPS.BeginInvoke()

# Add other some process related to main form
function flowstep {
    param (
        $icon, $step, $new_height
    )
    $global:panel_processing = New-Object System.Windows.Forms.GroupBox

    $pictureBox = New-Object System.Windows.Forms.PictureBox
    $pictureBox.Image = [System.Drawing.Image]::FromFile($icon)
    $pictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom
    $pictureBox.Size = New-Object System.Drawing.Size($pictureBoxHeight, $pictureBoxHeight)
    $pictureBox.Location = New-Object System.Drawing.Point(10, $new_height)

    $global:label = New-Object System.Windows.Forms.Label
    $label.Size = New-Object System.Drawing.Size(($panel_processing.Width / 2), 30)
    $label.Location = New-Object System.Drawing.Point(($pictureBox.Location.X + $pictureBox.Width + 5), ($pictureBox.Location.Y + $adjusted_location))

    $panel_processing.Controls.Add($pictureBox)
    $panel_processing.Controls.Add($label)

    $label.Text = $step

    if ($icon -like ".\prcs.png") {
        $label.ForeColor = "#CACACA"  # Set label color to gray
    }
    else {
        $label.Refresh()
        $label.ForeColor = "#000000"  # Set label color to black
    }

    return $pictureBox
}

# Step 1
$pictureBox1 = flowstep ".\pass.png" "Start unlocking" "35"

# Close the runspace for the form script
$FormPS.EndInvoke($AsyncHandle)
$Runspace.Close()
$Runspace.Dispose()

Why this part :

function flowstep {
    param (
        $icon, $step, $new_height
    )
    $global:panel_processing = New-Object System.Windows.Forms.GroupBox

    $pictureBox = New-Object System.Windows.Forms.PictureBox
    $pictureBox.Image = [System.Drawing.Image]::FromFile($icon)
    $pictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom
    $pictureBox.Size = New-Object System.Drawing.Size($pictureBoxHeight, $pictureBoxHeight)
    $pictureBox.Location = New-Object System.Drawing.Point(10, $new_height)

    $global:label = New-Object System.Windows.Forms.Label
    $label.Size = New-Object System.Drawing.Size(($panel_processing.Width / 2), 30)
    $label.Location = New-Object System.Drawing.Point(($pictureBox.Location.X + $pictureBox.Width + 5), ($pictureBox.Location.Y + $adjusted_location))

    $panel_processing.Controls.Add($pictureBox)
    $panel_processing.Controls.Add($label)

    $label.Text = $step

    if ($icon -like ".\prcs.png") {
        $label.ForeColor = "#CACACA"  # Set label color to gray
    }
    else {
        $label.Refresh()
        $label.ForeColor = "#000000"  # Set label color to black
    }

    return $pictureBox
}

# Step 1
$pictureBox1 = flowstep ".\pass.png" "Start unlocking" "35"

Does not executed?

My expectation once the GUI show, all the process keep running. And button will able to click once the process finished.

Anyone can give me idea please. Thanks

0

There are 0 answers