WebView2 in PowerShell Winform GUI - winforms

I have not been able to find any information on this so I'm not sure its entirely possible. I'm currently trying to integrate the WebView2 control into my PowerShell Winform GUI. I can see while debugging my script that the webView2 control is created, but nothing ever loads. I have the WebView2 runtime installed.
This is what I have so far:
function Show-test-WebView2Control_psf {
#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
[void][reflection.assembly]::LoadFile('C:\Tests\Assemblies\Debug\Microsoft.Web.WebView2.WinForms.dll')
[void][reflection.assembly]::LoadFile('C:\Tests\Assemblies\Microsoft.Web.WebView2.Core.dll')
[void][reflection.assembly]::LoadFile('C:\Tests\Assemblies\Microsoft.Web.WebView2.Wpf.dll')
[void][reflection.assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][reflection.assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
#endregion Import Assemblies
#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$form1 = New-Object 'System.Windows.Forms.Form'
$buttonRefresh = New-Object 'System.Windows.Forms.Button'
$buttonGo = New-Object 'System.Windows.Forms.Button'
$textbox1 = New-Object 'System.Windows.Forms.TextBox'
[Microsoft.Web.WebView2.WinForms.WebView2] $webview = New-Object 'Microsoft.Web.WebView2.WinForms.WebView2'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
#endregion Generated Form Objects
#----------------------------------------------
# User Generated Script
#----------------------------------------------
$form1_Load={
#TODO: Initialize Form Controls here
$webview.Source = ([uri]::new($textbox1.Text))
$webview.Visible = $true
}
$webview_Ready = {
$webview.NavigateToString("https://www.google.com")
}
$webview_CoreWebView2Ready={
$webview.Source = [System.Uri]$textbox1.Text
}
$buttonGo_Click={
#TODO: Place custom script here
$webview.Source = [System.Uri] $textbox1.Text;
}
$webview_SourceChanged={
$form1.Text = $webview.Source.AbsoluteUri;
}
# --End User Generated Script--
#----------------------------------------------
#region Generated Events
#----------------------------------------------
$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
}
$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$buttonGo.remove_Click($buttonGo_Click)
$webview.remove_CoreWebView2Ready($webview_CoreWebView2Ready)
$webview.remove_SourceChanged($webview_SourceChanged)
$form1.remove_Load($form1_Load)
$form1.remove_Load($Form_StateCorrection_Load)
$form1.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
}
#endregion Generated Events
#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
$form1.SuspendLayout()
#
# form1
#
$form1.Controls.Add($buttonRefresh)
$form1.Controls.Add($buttonGo)
$form1.Controls.Add($textbox1)
$form1.Controls.Add($webview)
$form1.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$form1.AutoScaleMode = 'Font'
$form1.ClientSize = New-Object System.Drawing.Size(619, 413)
$form1.Name = 'form1'
$form1.Text = 'Form'
$form1.add_Load($form1_Load)
#
# buttonRefresh
#
$buttonRefresh.Location = New-Object System.Drawing.Point(13, 13)
$buttonRefresh.Name = 'buttonRefresh'
$buttonRefresh.Size = New-Object System.Drawing.Size(75, 23)
$buttonRefresh.TabIndex = 3
$buttonRefresh.Text = 'Refresh'
$buttonRefresh.UseVisualStyleBackColor = $True
#
# buttonGo
#
$buttonGo.Location = New-Object System.Drawing.Point(538, 9)
$buttonGo.Name = 'buttonGo'
$buttonGo.Size = New-Object System.Drawing.Size(75, 23)
$buttonGo.TabIndex = 2
$buttonGo.Text = 'Go'
$buttonGo.UseVisualStyleBackColor = $True
$buttonGo.add_Click($buttonGo_Click)
#
# textbox1
#
$textbox1.Location = New-Object System.Drawing.Point(96, 13)
$textbox1.Name = 'textbox1'
$textbox1.Size = New-Object System.Drawing.Size(435, 20)
$textbox1.TabIndex = 1
$textbox1.Text = 'https://www.bing.com'
#
# webview
#
$webview.Location = New-Object System.Drawing.Point(0, 49)
$webview.Name = 'webview'
$webview.Size = New-Object System.Drawing.Size(619, 364)
$webview.TabIndex = 0
$webview.ZoomFactor = 1
$webview.add_SourceChanged($webview_SourceChanged)
$form1.ResumeLayout()
#endregion Generated Form Code
#----------------------------------------------
#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$form1.add_FormClosed($Form_Cleanup_FormClosed)
#Show the Form
return $form1.ShowDialog()
} #End Function
#Call the form
Show-test-WebView2Control_psf | Out-Null
Is there a way to do this? If so, can someone please tell me what I'm doing wrong?

Trying out your code on my own I had to resolve two issues:
From the webview2 nuget package (for reference I used the WebView2 nuget 1.0.781-prerelease package) I copied the winforms and core DLL from the net45 folder and I copied the x64 webview2loader.dll all into the wv2 folder. You need to ensure the webview2loader.dll of the appropriate CPU architecture is copied next to the core dll.
The default WebView2 user data folder is in the folder containing the host executable. In this case the host executable is powershell and the containing folder isn't writable by normal processes. So you need to change the user data folder which you can do via the CoreWebView2CreationProperties UserDataFolder property before the WebView2 is initialized.
I have the modified code below. Additional work is required to resize and close the WebView2 and resolve other issues.
function Show-test-WebView2Control_psf {
#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
# I've put the following files in `C:\users\davris\tmp\wv2`
# Microsoft.Web.WebView2.Core.dll
# Microsoft.Web.WebView2.WinForms.dll
# WebView2Loader.dll
[void][reflection.assembly]::LoadFile('C:\users\davris\tmp\wv2\Microsoft.Web.WebView2.WinForms.dll')
[void][reflection.assembly]::LoadFile('C:\users\davris\tmp\wv2\Microsoft.Web.WebView2.Core.dll')
[void][reflection.assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][reflection.assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
#endregion Import Assemblies
#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$form1 = New-Object 'System.Windows.Forms.Form'
$buttonRefresh = New-Object 'System.Windows.Forms.Button'
$buttonGo = New-Object 'System.Windows.Forms.Button'
$textbox1 = New-Object 'System.Windows.Forms.TextBox'
[Microsoft.Web.WebView2.WinForms.WebView2] $webview = New-Object 'Microsoft.Web.WebView2.WinForms.WebView2'
$webview.CreationProperties = New-Object 'Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties'
$webview.CreationProperties.UserDataFolder = "C:\users\davris\tmp\wv2\data";
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
#endregion Generated Form Objects
#----------------------------------------------
# User Generated Script
#----------------------------------------------
$form1_Load={
#TODO: Initialize Form Controls here
$webview.Source = ([uri]::new($textbox1.Text))
$webview.Visible = $true
}
$buttonGo_Click={
#TODO: Place custom script here
$webview.Source = [System.Uri] $textbox1.Text;
}
$webview_SourceChanged={
$form1.Text = $webview.Source.AbsoluteUri;
}
# --End User Generated Script--
#----------------------------------------------
#region Generated Events
#----------------------------------------------
$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
}
$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$buttonGo.remove_Click($buttonGo_Click)
$webview.remove_SourceChanged($webview_SourceChanged)
$form1.remove_Load($form1_Load)
$form1.remove_Load($Form_StateCorrection_Load)
$form1.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
}
#endregion Generated Events
#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
$form1.SuspendLayout()
#
# form1
#
$form1.Controls.Add($buttonRefresh)
$form1.Controls.Add($buttonGo)
$form1.Controls.Add($textbox1)
$form1.Controls.Add($webview)
$form1.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$form1.AutoScaleMode = 'Font'
$form1.ClientSize = New-Object System.Drawing.Size(619, 413)
$form1.Name = 'form1'
$form1.Text = 'Form'
$form1.add_Load($form1_Load)
#
# buttonRefresh
#
$buttonRefresh.Location = New-Object System.Drawing.Point(13, 13)
$buttonRefresh.Name = 'buttonRefresh'
$buttonRefresh.Size = New-Object System.Drawing.Size(75, 23)
$buttonRefresh.TabIndex = 3
$buttonRefresh.Text = 'Refresh'
$buttonRefresh.UseVisualStyleBackColor = $True
#
# buttonGo
#
$buttonGo.Location = New-Object System.Drawing.Point(538, 9)
$buttonGo.Name = 'buttonGo'
$buttonGo.Size = New-Object System.Drawing.Size(75, 23)
$buttonGo.TabIndex = 2
$buttonGo.Text = 'Go'
$buttonGo.UseVisualStyleBackColor = $True
$buttonGo.add_Click($buttonGo_Click)
#
# textbox1
#
$textbox1.Location = New-Object System.Drawing.Point(96, 13)
$textbox1.Name = 'textbox1'
$textbox1.Size = New-Object System.Drawing.Size(435, 20)
$textbox1.TabIndex = 1
$textbox1.Text = 'https://www.bing.com'
#
# webview
#
$webview.Location = New-Object System.Drawing.Point(0, 49)
$webview.Name = 'webview'
$webview.Size = New-Object System.Drawing.Size(619, 364)
$webview.TabIndex = 0
$webview.ZoomFactor = 1
$webview.add_SourceChanged($webview_SourceChanged)
$form1.ResumeLayout()
#endregion Generated Form Code
#----------------------------------------------
#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$form1.add_FormClosed($Form_Cleanup_FormClosed)
#Show the Form
return $form1.ShowDialog()
} #End Function
#Call the form
Show-test-WebView2Control_psf | Out-Null

Related

Make Entire Borderless Form Draggable from Certain Object

I have a borderless winform (WPF is not an option) that I am trying to make draggable from an object that is serving as a custom sidebar. I have searched around and found some things that allow me to drag the sidebar within the form, but I need to be able to move $Form with the sidebar. Any thoughts? It seems like I will need to use Add-Type with some C# here.
Ok, since we don't have the code to your form, here's a demo for you. It is just a not-pretty borderless form that uses a label to demonstrate the various events needed to drag the entire form around. (in your case this would be the sidebar)
Add-Type -AssemblyName System.Windows.Forms
# set up some globals for dragging
$global:dragging = $false
$global:mouseDragX = 0
$global:mouseDragY = 0
#Form
$form = New-Object System.Windows.Forms.Form
$form.FormBorderStyle = "None"
$form.Font = New-Object System.Drawing.Font("Microsoft Sans Serif", 9.0, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Point)
$form.MinimumSize = New-Object System.Drawing.Size(456, 547)
$form.AutoScaleDimensions = New-Object System.Drawing.SizeF(7.0, 15.0)
$form.AutoScaleMode = [System.Windows.Forms.AutoScaleMode]::Font
$form.ClientSize = New-Object System.Drawing.Size(440, 509)
$form.ShowIcon = $false
$form.StartPosition = "CenterScreen"
$form.TopMost = $true
#lblDrag (this is the object used for dragging the form)
$lblDrag = New-Object System.Windows.Forms.Label
$lblDrag.Name = "lblDrag"
$lblDrag.BackColor = [System.Drawing.Color]::LightYellow
$lblDrag.Location = New-Object System.Drawing.Point(172, 226)
$lblDrag.Size = New-Object System.Drawing.Size(117, 27)
$lblDrag.Anchor = "Top","Right"
$lblDrag.BorderStyle = "FixedSingle"
$lblDrag.Text = "Drag form.."
$lblDrag.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
# set the 'dragging' flag and capture the current mouse position
$lblDrag.Add_MouseDown( { $global:dragging = $true
$global:mouseDragX = [System.Windows.Forms.Cursor]::Position.X - $form.Left
$global:mouseDragY = [System.Windows.Forms.Cursor]::Position.Y -$form.Top
})
# move the form while the mouse is depressed (i.e. $global:dragging -eq $true)
$lblDrag.Add_MouseMove( { if($global:dragging) {
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea
$currentX = [System.Windows.Forms.Cursor]::Position.X
$currentY = [System.Windows.Forms.Cursor]::Position.Y
[int]$newX = [Math]::Min($currentX - $global:mouseDragX, $screen.Right - $form.Width)
[int]$newY = [Math]::Min($currentY - $global:mouseDragY, $screen.Bottom - $form.Height)
$form.Location = New-Object System.Drawing.Point($newX, $newY)
}})
# stop dragging the form
$lblDrag.Add_MouseUp( { $global:dragging = $false })
# add a button so you will be able to close the form
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Name = "btnClose"
$btnClose.Anchor = "Top","Right"
$btnClose.Location = New-Object System.Drawing.Point(172, 454)
$btnClose.Size = New-Object System.Drawing.Size(117, 27)
$btnClose.Text = "&Close"
$btnClose.UseVisualStyleBackColor = $true
$btnClose.UseMnemonic = $true
$btnClose.DialogResult = [System.Windows.Forms.DialogResult]::OK
# add controls to the form
$form.Controls.Add($btnClose)
$form.Controls.Add($lblDrag)
$form.AcceptButton = $btnClose
# show the form and play around with the dragging label
$form.ShowDialog()
# when done, dispose of the form
$form.Dispose()

powershell combobox items to variable

I am trying to create a powershell Script with a Gui that gives the user a drop list of available drives and then when the user selects the drive and clicks ok the script maps that drive as M:\
But I cant work out how to get the selected item in the combo box to be passed into the variable $MapDrive
#List of Drives To Map
$DriveList = #("0. DGL_Data","1. P1","2. DGLFSG3","3. p3 (TPC)","4. p4","6. p6","7. p7","8. p8","9. p9","10. p10","11. p11","12. p12")
#Displays With Drive to Map
$MapDrive = convert.ToString($Dropdown.SelectedItem)
Function MapDrive {
If ($MapDrive -eq $DriveList[0]){
Write-Output Sucess > "C:\Users\andy.burton\Desktop\Practice Selector\Success.txt"}
ElseIf ($MapDrive -eq $DriveList[1]){
Write-Output BooYah > "C:\Users\andy.burton\Desktop\Practice Selector\Yes.txt"
}
Else {
Write-Output Failure > "C:\Users\andy.burton\Desktop\Practice Selector\Failed.txt"}
}
#test Function
Function test {
Write-Output $MapDrive > "C:\Users\andy.burton\Desktop\Practice Selector\Success.txt"
}
#Function to Create Form
Function GenerateForm {
#Define Drive Selector Main Form
Add-Type -AssemblyName System.Windows.Forms
$DGL = New-Object system.Windows.Forms.Form
$DGL.Text = "DGL Practice Manager"
$DGL.TopMost = $true
$DGL.BackgroundImage = [system.drawing.image]::FromFile("C:\Users\andy.burton\Desktop\Practice Selector\Images\medical.jpg")
$DGL.Icon = New-Object system.drawing.icon("C:\Users\andy.burton\Desktop\Practice Selector\Images\medical2.ico")
$DGL.Width = 600
$DGL.Height = 265
$DGL.MinimizeBox = $False
$DGL.MaximizeBox = $False
#Label to Display Instuctions
$label2 = New-Object system.windows.Forms.Label
$label2.Text = "Select which drive"
$label2.BackColor = "#e4f3fa"
$label2.AutoSize = $true
$label2.Width = 25
$label2.Height = 10
$label2.location = new-object system.drawing.point(20,28)
$label2.Font = "Microsoft Sans Serif,10"
$DGL.controls.Add($label2)
#Dropdown Box For Selecting Practice
$Dropdown = New-Object system.windows.Forms.ComboBox
$Dropdown.BackColor = "#e4f3fa"
$DropDown.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
$Dropdown.Width = 243
$Dropdown.Height = 20
$Dropdown.location = new-object system.drawing.point(21,73)
$Dropdown.Font = "Microsoft Sans Serif,10"
$DropDown.items.addrange($DriveList)
$DGL.controls.Add($Dropdown)
#Cancel Button to Cancel drive Selection
$Cancelbutton = New-Object system.windows.Forms.Button
$Cancelbutton.Text = "Cancel"
$Cancelbutton.Width = 60
$Cancelbutton.Height = 30
$Cancelbutton.location = new-object system.drawing.point(210,120)
$Cancelbutton.Font = "Microsoft Sans Serif,10"
$DGL.CancelButton = $Cancelbutton
$CancelButton.Add_Click({ $DGL.close();[System.Windows.Forms.Application]::Exit($null)})
$DGL.controls.Add($Cancelbutton)
#OK Button to Select Drive
$OKbutton = New-Object system.windows.Forms.Button
$OKbutton.Text = "OK"
$OKbutton.Width = 60
$OKbutton.Height = 30
$OKbutton.location = new-object system.drawing.point(140,120)
$OKbutton.Font = "Microsoft Sans Serif,10"
$DGL.AcceptButton = $OKbutton
$MapDrive = convert.ToString($Dropdown.SelectedItem)
#On click call PracticeSelectedCallBack to launch the application
$OKbutton.Add_Click({test ; $DGL.close()})
$DGL.controls.Add($OKbutton)
#Display the Form
$DGL.Add_Shown({$DGL.Activate()})
$DGL.ShowDialog()
}
GenerateForm
I also want to hide the powershell window but not the gui I have tried -window hidden but that hid everything
The ComboBox has several events that you can tie into that will do various things. One of the events is a SelectedIndexChanged. You can add that event to your ComboBox object and update $MapDrive
This code $MapDrive = convert.ToString($Dropdown.SelectedItem) will only fire once during the initial compile. You have to use events to trigger code changes after compile during runtime.
Also, in Powershell you can use the following command [System.Windows.Forms.ComboBox] | gm to get a list of the methods, and properties of the object. You can use [System.Windows.Forms.checkedlistbox].GetEvents() to get a list of events of an object.

is it possible to control WMI events though runspace and the main form?

I am trying to create a background worker that will scan for a change in USB devices.
I am having a hard time trying to control WMI events outside the runspace.
Basically, when I close the window (AKA "form") I would like to cancel Wait-Event. But I cannot control it out side the runspace, so it gets stuck.
Is it possible?
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form1 = New-Object System.Windows.Forms.Form
$form1.Text = "My PowerShell Form"
$form1.Name = "form1"
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 1400
$System_Drawing_Size.Height = 600
$form1.ClientSize = $System_Drawing_Size
$Global:x = [Hashtable]::Synchronized(#{})
$x.Host = $Host
$x.Flag = $true
$rs = [RunspaceFactory]::CreateRunspace()
$rs.ApartmentState, $rs.ThreadOptions = "STA", "ReUseThread"
$rs.Open()
$rs.SessionStateProxy.SetVariable("x",$x)
$cmd = [PowerShell]::Create().AddScript({
Register-WmiEvent -Class Win32_DeviceChangeEvent -SourceIdentifier volumeChange
do {
$retEvent = Wait-Event -SourceIdentifier volumeChange
Remove-Event -SourceIdentifier volumeChange
} while ($x.Flag) #Loop until next event
Unregister-Event -SourceIdentifier volumeChange
})
$cmd.Runspace = $rs
$handle = $cmd.BeginInvoke()
$OnClosing = {
$x.Flag = $false
$x.Host.UI.WriteVerboseLine($x.Flag)
$cmd.EndInvoke($handle)
}
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.Add_Load($OnLoadForm_StateCorrection)
$form1.Add_Closing($OnClosing)
$form1.ShowDialog() | Out-Null

Start-Job\Receive-Job is hanging\freezing while getting results - PrimalForm CE GUI

I can start the job but how can I continue using my program while its getting the information, if I do a 'while' loop it just freezes the program until the results have completed.
Here is the script generated by PrimalForms CE edition, and my code is in button1_OnClick.
End result I want to have the script running to check for locked out AD users (but that can really be anything) then while that is running I want to review the previous results and unlock a user if needed...
#Generated Form Function
function GenerateForm {
########################################################################
# Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.10.0
# Generated On: 7/09/2015 2:24 PM
# Generated By: stojanp2
########################################################################
#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
#endregion
#region Generated Form Objects
$form1 = New-Object System.Windows.Forms.Form
$button3 = New-Object System.Windows.Forms.Button
$button2 = New-Object System.Windows.Forms.Button
$listView1 = New-Object System.Windows.Forms.ListView
$button1 = New-Object System.Windows.Forms.Button
$Users = New-Object System.Windows.Forms.ColumnHeader
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects
#----------------------------------------------
#Generated Event Script Blocks
#----------------------------------------------
#Provide Custom Code for events specified in PrimalForms.
$button3_OnClick =
{
#TODO: Place custom script here
}
$button1_OnClick =
{
Start-Job -Name FindUsers -ScriptBlock { Search-ADAccount -LockedOut | Select-Object * }#end Start-Job
Do {
Start-Sleep -Seconds 1
write-host "waiting" # so i can see its doing something in the console
} Until (#(Get-Job -Name FindUsers).State -eq "Completed")
Write-Host "done"
$us = Receive-Job -Name FindUsers
ForEach ($u IN $us){
$listView1.Items.Add($u.sAMAccountName)
}
Get-Job -Name FindUsers | Remove-Job -Force
}
$button2_OnClick =
{
#TODO: Place custom script here
}
$handler_listView1_SelectedIndexChanged =
{
#TODO: Place custom script here
}
$OnLoadForm_StateCorrection =
{ #Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
}
#----------------------------------------------
#region Generated Form Code
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 469
$System_Drawing_Size.Width = 271
$form1.ClientSize = $System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.Name = "form1"
$form1.Text = "Primal Form"
$button3.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 142
$System_Drawing_Point.Y = 418
$button3.Location = $System_Drawing_Point
$button3.Name = "button3"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 117
$button3.Size = $System_Drawing_Size
$button3.TabIndex = 3
$button3.Text = "button3"
$button3.UseVisualStyleBackColor = $True
$button3.add_Click($button3_OnClick)
$form1.Controls.Add($button3)
$button2.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 418
$button2.Location = $System_Drawing_Point
$button2.Name
= "button2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 117
$button2.Size = $System_Drawing_Size
$button2.TabIndex = 2
$button2.Text = "button2"
$button2.UseVisualStyleBackColor = $True
$button2.add_Click($button2_OnClick)
$form1.Controls.Add($button2)
$listView1.Columns.Add($Users)|Out-Null
$listView1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 73
$listView1.Location = $System_Drawing_Point
$listView1.Name = "listView1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 339
$System_Drawing_Size.Width = 247
$listView1.Size = $System_Drawing_Size
$listView1.TabIndex = 1
$listView1.UseCompatibleStateImageBehavior = $False
$listView1.View = 1
$listView1.add_SelectedIndexChanged($handler_listView1_SelectedIndexChanged)
$form1.Controls.Add($listView1)
$button1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 12
$button1.Location = $System_Drawing_Point
$button1.Name = "button1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 55
$System_Drawing_Size.Width = 247
$button1.Size = $System_Drawing_Size
$button1.TabIndex = 0
$button1.Text = "button1"
$button1.UseVisualStyleBackColor = $True
$button1.add_Click($button1_OnClick)
$form1.Controls.Add($button1)
$Users.Name = "Users"
$Users.Text = "User Names"
$Users.Width = 116
#endregion Generated Form Code
#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection)
#Show the Form
$form1.ShowDialog() | Out-Null
} #End Function
#Call the Function
GenerateForm
I can't speak about PrimalForm but in PowerShell Studio there is a seperate button called Button - Start Job in the section Toolbox > Control Sets:
When using this type of button an extra function is provided called Add-JobTracker that keeps track of the job progress and makes sure that the job is ran in the background in its own PowerShell session. So it doesn't freeze the interface and even updates a progress bar if you will.
More info on the SAPIEN page PowerShell Studio: Creating responsive forms.
The fact that your are doing a loop to check every time the status of the job is why the interface freezes. It will stop every time at that point and only frees up again when the job is completely done.
Maybe if you update PrimalForms to the latest version you'll have this function to.

Power shell script with GUI performs slowly

I have created a gui with powershell that allows me to copy files from inside folders into one place .
Example you have a folder A and in folder A there is Folder B and C inside all these folders you have a bunch of logfiles named logfile + date.log
My app can hunt through all the folders and move copy the log files to a single location.
The script works but when it is getting a list of files to copy it is slow and says "Not responding" at the top of the window next to where it says "Copy Files To One Directory"
I have added the script can you guys have a look and let me know how to speed it up.
The functions it hik are causing the problem are after the "These are the function I seems to be having a problem with"
Thank for the help.
The code
#------------------------------------------------------------------------
# Source File Information (DO NOT MODIFY)
# Source ID: 3020bcd1-4cba-4aca-968e-b4bc4ca05d76
# Source File: Copy\Copy.pfproj
#------------------------------------------------------------------------
#========================================================================
# Generated On: 11/15/2011 5:11 PM
# Generated By: justin
#========================================================================
#----------------------------------------------
#region Import Assemblies
#----------------------------------------------
[void][Reflection.Assembly]::Load("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][Reflection.Assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][Reflection.Assembly]::Load("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
[void][Reflection.Assembly]::Load("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][Reflection.Assembly]::Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][Reflection.Assembly]::Load("System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][Reflection.Assembly]::Load("System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
#endregion Import Assemblies
#Define a Param block to use custom parameters in the project
#Param ($CustomParameter)
function Main {
Param ([String]$Commandline)
#Note: This function starts the application
#Note: $Commandline contains the complete argument string passed to the packager
#Note: $Args contains the parsed arguments passed to the packager (Type: System.Array)
#Note: To get the script directory in the Packager use: Split-Path $hostinvocation.MyCommand.path
#Note: To get the console output in the Packager (Windows Mode) use: $ConsoleOutput (Type: System.Collections.ArrayList)
#TODO: Initialize and add Function calls to forms
if((Call-MainForm_pff) -eq "OK")
{
}
$global:ExitCode = 0 #Set the exit code for the Packager
}
#region Call-MainForm_pff
function Call-MainForm_pff
{
#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
[void][reflection.assembly]::Load("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][reflection.assembly]::Load("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
[void][reflection.assembly]::Load("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][reflection.assembly]::Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][reflection.assembly]::Load("System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][reflection.assembly]::Load("System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
#endregion Import Assemblies
#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$CopyFilesToOneDirectoy = New-Object System.Windows.Forms.Form
$labelExtension = New-Object System.Windows.Forms.Label
$labelFileName = New-Object System.Windows.Forms.Label
$Extension = New-Object System.Windows.Forms.TextBox
$FileName = New-Object System.Windows.Forms.TextBox
$buttonSetDestination = New-Object System.Windows.Forms.Button
$buttonSetSource = New-Object System.Windows.Forms.Button
$Dlabel = New-Object System.Windows.Forms.Label
$Slabel = New-Object System.Windows.Forms.Label
$DestinationFolder = New-Object System.Windows.Forms.TextBox
$SourceFolder = New-Object System.Windows.Forms.TextBox
$progress = New-Object System.Windows.Forms.ProgressBar
$buttonCopyFiles = New-Object System.Windows.Forms.Button
$sourcebrowserdialog = New-Object System.Windows.Forms.FolderBrowserDialog
$destinationbrowserdialog = New-Object System.Windows.Forms.FolderBrowserDialog
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects
#----------------------------------------------
# User Generated Script
#----------------------------------------------
$OnLoadFormEvent={
}
$buttonSetSource_Click={
$result = $sourcebrowserdialog.ShowDialog()
if ($result -eq 'Ok'){
$SourceFolder.Text =$sourcebrowserdialog.SelectedPath
}
else{
$SourceFolder.Text = ''
}
}
$buttonSetDestination_Click={
$result = $destinationbrowserdialog.ShowDialog()
if ($result -eq 'Ok'){
$DestinationFolder.Text =$destinationbrowserdialog.SelectedPath
}
else{
$DestinationFolder.Text = ''
}
}
$buttonCopyFiles_Click={
#TODO: Place custom script here
$progress.Value = 0
$CName = $FileName.Text
$CExtension = "." + $Extension.Text
$CSource = $SourceFolder.Text
$CDestination = $DestinationFolder.Text
CopyfFiles $CSource $CDestination $CName $CExtension
}
# --End User Generated Script--
#----------------------------------------------
#region Generated Events
#----------------------------------------------
$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$CopyFilesToOneDirectoy.WindowState = $InitialFormWindowState
}
$Form_StoreValues_Closing=
{
#Store the control values
$script:MainForm_Extension = $Extension.Text
$script:MainForm_FileName = $FileName.Text
$script:MainForm_DestinationFolder = $DestinationFolder.Text
$script:MainForm_SourceFolder = $SourceFolder.Text
}
$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$buttonSetDestination.remove_Click($buttonSetDestination_Click)
$buttonSetSource.remove_Click($buttonSetSource_Click)
$buttonCopyFiles.remove_Click($buttonCopyFiles_Click)
$CopyFilesToOneDirectoy.remove_Load($OnLoadFormEvent)
$CopyFilesToOneDirectoy.remove_Load($Form_StateCorrection_Load)
$CopyFilesToOneDirectoy.remove_Closing($Form_StoreValues_Closing)
$CopyFilesToOneDirectoy.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch [Exception]
{ }
}
#endregion Generated Events
#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
#
# CopyFilesToOneDirectoy
#
$CopyFilesToOneDirectoy.Controls.Add($labelExtension)
$CopyFilesToOneDirectoy.Controls.Add($labelFileName)
$CopyFilesToOneDirectoy.Controls.Add($Extension)
$CopyFilesToOneDirectoy.Controls.Add($FileName)
$CopyFilesToOneDirectoy.Controls.Add($buttonSetDestination)
$CopyFilesToOneDirectoy.Controls.Add($buttonSetSource)
$CopyFilesToOneDirectoy.Controls.Add($Dlabel)
$CopyFilesToOneDirectoy.Controls.Add($Slabel)
$CopyFilesToOneDirectoy.Controls.Add($DestinationFolder)
$CopyFilesToOneDirectoy.Controls.Add($SourceFolder)
$CopyFilesToOneDirectoy.Controls.Add($progress)
$CopyFilesToOneDirectoy.Controls.Add($buttonCopyFiles)
$CopyFilesToOneDirectoy.ClientSize = '458, 245'
$CopyFilesToOneDirectoy.Name = "CopyFilesToOneDirectoy"
$CopyFilesToOneDirectoy.StartPosition = 'CenterScreen'
$CopyFilesToOneDirectoy.Text = "Copy Files To One Directoy"
$CopyFilesToOneDirectoy.add_Load($OnLoadFormEvent)
#
# labelExtension
#
$labelExtension.AutoSize = $True
$labelExtension.Font = "Microsoft Sans Serif, 9.75pt, style=Bold"
$labelExtension.Location = '349, 54'
$labelExtension.Name = "labelExtension"
$labelExtension.Size = '75, 16'
$labelExtension.TabIndex = 11
$labelExtension.Text = "Extension"
#
# labelFileName
#
$labelFileName.AutoSize = $True
$labelFileName.Font = "Microsoft Sans Serif, 9.75pt, style=Bold"
$labelFileName.Location = '12, 54'
$labelFileName.Name = "labelFileName"
$labelFileName.Size = '79, 16'
$labelFileName.TabIndex = 10
$labelFileName.Text = "File Name"
#
# Extension
#
$Extension.Font = "Microsoft Sans Serif, 9.75pt"
$Extension.Location = '349, 74'
$Extension.Name = "Extension"
$Extension.Size = '93, 22'
$Extension.TabIndex = 9
#
# FileName
#
$FileName.Font = "Microsoft Sans Serif, 9.75pt"
$FileName.Location = '12, 74'
$FileName.Name = "FileName"
$FileName.Size = '300, 22'
$FileName.TabIndex = 8
#
# buttonSetDestination
#
$buttonSetDestination.Location = '349, 173'
$buttonSetDestination.Name = "buttonSetDestination"
$buttonSetDestination.Size = '93, 23'
$buttonSetDestination.TabIndex = 7
$buttonSetDestination.Text = "Set Destination"
$buttonSetDestination.TextAlign = 'MiddleLeft'
$buttonSetDestination.UseVisualStyleBackColor = $True
$buttonSetDestination.add_Click($buttonSetDestination_Click)
#
# buttonSetSource
#
$buttonSetSource.Location = '349, 123'
$buttonSetSource.Name = "buttonSetSource"
$buttonSetSource.Size = '93, 23'
$buttonSetSource.TabIndex = 6
$buttonSetSource.Text = "Set Source"
$buttonSetSource.UseVisualStyleBackColor = $True
$buttonSetSource.add_Click($buttonSetSource_Click)
#
# Dlabel
#
$Dlabel.AutoSize = $True
$Dlabel.Font = "Microsoft Sans Serif, 9.75pt, style=Bold"
$Dlabel.Location = '12, 154'
$Dlabel.Name = "Dlabel"
$Dlabel.Size = '135, 16'
$Dlabel.TabIndex = 5
$Dlabel.Text = "Destination Folder"
#
# Slabel
#
$Slabel.AutoSize = $True
$Slabel.Font = "Microsoft Sans Serif, 9.75pt, style=Bold"
$Slabel.Location = '12, 104'
$Slabel.Name = "Slabel"
$Slabel.Size = '106, 16'
$Slabel.TabIndex = 4
$Slabel.Text = "Source Folder"
#
# DestinationFolder
#
$DestinationFolder.Font = "Microsoft Sans Serif, 9.75pt"
$DestinationFolder.Location = '12, 174'
$DestinationFolder.Name = "DestinationFolder"
$DestinationFolder.Size = '300, 22'
$DestinationFolder.TabIndex = 3
$DestinationFolder.Text = "c:\td"
#
# SourceFolder
#
$SourceFolder.Font = "Microsoft Sans Serif, 9.75pt"
$SourceFolder.Location = '12, 124'
$SourceFolder.Name = "SourceFolder"
$SourceFolder.Size = '300, 22'
$SourceFolder.TabIndex = 2
$SourceFolder.Text = "c:\ts"
#
# progress
#
$progress.Location = '12, 212'
$progress.Name = "progress"
$progress.Size = '300, 23'
$progress.TabIndex = 1
#
# buttonCopyFiles
#
$buttonCopyFiles.Location = '349, 212'
$buttonCopyFiles.Name = "buttonCopyFiles"
$buttonCopyFiles.Size = '93, 23'
$buttonCopyFiles.TabIndex = 0
$buttonCopyFiles.Text = "Copy Files"
$buttonCopyFiles.UseVisualStyleBackColor = $True
$buttonCopyFiles.add_Click($buttonCopyFiles_Click)
#
# sourcebrowserdialog
#
$sourcebrowserdialog.RootFolder = 'MyComputer'
$sourcebrowserdialog.ShowNewFolderButton = $False
#
# destinationbrowserdialog
#
$destinationbrowserdialog.RootFolder = 'MyComputer'
$destinationbrowserdialog.ShowNewFolderButton = $False
#endregion Generated Form Code
#----------------------------------------------
#Save the initial state of the form
$InitialFormWindowState = $CopyFilesToOneDirectoy.WindowState
#Init the OnLoad event to correct the initial state of the form
$CopyFilesToOneDirectoy.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$CopyFilesToOneDirectoy.add_FormClosed($Form_Cleanup_FormClosed)
#Store the control values when form is closing
$CopyFilesToOneDirectoy.add_Closing($Form_StoreValues_Closing)
#Show the Form
return $CopyFilesToOneDirectoy.ShowDialog()
}
#endregion
#--------------------------------------------------------------------------------------------------------------------------------------------------
# These are the function I seems to be havig a problem with
#Sample function that provides the location of the script
function Get-ScriptDirectory
{
if($hostinvocation -ne $null)
{
Split-Path $hostinvocation.MyCommand.path
}
else
{
Split-Path $script:MyInvocation.MyCommand.Path
}
}
function ListOfFiles ($Source,$Name,$Extension){
$FileListArray = #()
foreach($file in Get-ChildItem $Source -Force -Recurse | Where-Object {$_.name -like $Name -and $_.Extension -eq $Extension})
{
If ($FileListArray -match "$file")
{
$NewFileName = $file.Directory.Name + "." + $file.Name
$FileListArray += ,#($file,$file.FullName,$NewFileName)
}
Else
{
$FileListArray += ,#($file,$file.FullName,$file)
}
}
Return $FileListArray
}
Function CopyfFiles ($Source,$Destination,$Name,$Extension){
$ListFiles = #(listOfFiles -Source $Source -Name $Name -Extension $Extension)
$ListFilesTemp = #()
Foreach ($CF in $ListFiles)
{
$Check = $Destination + "\"+ $CF[2]
#If The File is Not Already In The Destination Add It To The Temp Array
IF (Test-Path -Path "$Check")
{}
Else
{$ListFilesTemp += ,#($CF[0],$CF[1],$CF[2])}
$ListFiles = $ListFilesTemp
}
$progress.Minimum = 0
$progress.Maximum = $ListFiles.Count
$progress.Step = 1
Foreach ($File in $ListFiles)
{
$FileDestination = $Destination + "\"+ $File[2]
Copy-Item -Path $File[1] -Destination $FileDestination
$progress.PerformStep()
}
}
#Sample variable that provides the location of the script
[string]$ScriptDirectory = Get-ScriptDirectory
#--------------------------------------------------------------------------------------------------------------------------------------------------
#endregion
#Start the application
Main ($CommandLine)
<code>
"Not Responding" means the thread isn't waiting for windowing input (in your example the thread is running the powershell code). I don't think there is a trivial way to create new threads in Powershell. However, you might be able to make your GUI more responsive using PowerBoots and powershell jobs like in this example.
You are declaring local variables inside a function (Call-MainForm_pff) and using these variables in other function. That will not work. See sample code. Only $Var2 will be displayed.
#=================
Function One-Set-Value {
$Var1 = "This is a test."
}
Function Two-Display-Value
{
$Var2 = "This is a second test."
Write-Host "Var2" $Var2
Write-Host "Var1" $Var1
}
One-Set-Value
Two-Display-Value
#=================
Convert these variables in to functions. This will work with return values.

Resources