I have been working with Powershell for a time now, it is not the ideal programming environment, but got stuck with my program.
My program is an GUI with a marquee progressbar and a search job.
What my program does: After you run the script with Powershell it will restart Powershell in STA mode if the mode is MTA. After that it will ask for a folder location. After you entered the folder location it will start the search job and will search the location for files. Every file will be stored into an array. That array will be printed out into the tempfile.txt that will be saved on your desktop. Meanwhile the job is searching for the files the GUI will display a form with a Marquee Progress bar.
What my program needs to do: After the job is finished with searching and storing the files it must close the form.
I have tried it to do with the $formSearchingFiles.Close() command but I have noticed Jobs can not close their 'parent' thread, so this job will not be able to close the form.
I have also tried to solve it with the Wait-Job cmdlet but then the Marquee Progress bar will freeze, or the form will not show up at all.
I have looked alot around internet for solutions but I can not find one that suits this problem. I was thinking about multi-processing, but I do not know if this is possible in Powershell 2.0 (I am limited to 2.0 or lower).
I also do not know if there is a way that the Search-Job can notify the main thread that it is finished with the task, so that the main thread can continue with the program, without freezing the progress bar.
I hope I have explained enough about the program and my problem.
# Get the path of the script
$scriptPath = ((Split-Path $script:MyInvocation.MyCommand.Path) + "\")
$scriptName = $MyInvocation.MyCommand.Name
$script = $scriptPath + $scriptName
# Check if powershell is running in STA(Single Threaded Apartment) or MTA(Multi Threaded Apartment) mode.
# If it is running in MTA mode then restart Powershell in STA mode.
if ([threading.thread]::CurrentThread.GetApartmentState() -eq "MTA")
{
Write-Host Restarting Powershell in STA mode
& $env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exe -sta "& {&'$script'}"
}
else
{
$folderPath = $currentFolderLocation.Text
$tempFile = $currentStagingLocation.Text
$tempFile += "\fileArray.txt"
function OnApplicationLoad {
return $true #return true for success or false for failure
}
function OnApplicationExit {
$script:ExitCode = 0 #Set the exit code for the Packager
}
function Call-Searching_pff {
[void][reflection.assembly]::Load("mscorlib, 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("System, 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")
[void][reflection.assembly]::Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[void][reflection.assembly]::Load("System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
[System.Windows.Forms.Application]::EnableVisualStyles()
$formSearchingFiles = New-Object 'System.Windows.Forms.Form'
$label = New-Object 'System.Windows.Forms.Label'
$progressbar = New-Object 'System.Windows.Forms.ProgressBar'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
$FormEvent_Load={
$folderPath = &read-host "Enter path"
$tempFile = (([Environment]::GetFolderPath("Desktop")) + "\tempfile.txt" )
$SearchJob = Start-Job -scriptblock {
param ($folderPath, $tempFile)
$fileArray = @()
# Get all files and folders under the specified path
$items = Get-ChildItem -Path $folderPath -Recurse
foreach ($item in $items)
{
# Check if the item is a file or a folder
if (!($item.PSIsContainer))
{
# Extract path of file with path of entered folder
$extractedPath = $item.FullName
$extractedPath = $extractedPath.Replace($folderPath, "")
$fileArray += $extractedPath
}
}
# Save array in temporary file
$fileArray | out-file $tempFile
$formSearchingFiles.Close() #Does not work inside job :(
} -ArgumentList @($folderPath, $tempFile)
}
$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$formSearchingFiles.WindowState = $InitialFormWindowState
}
$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$formSearchingFiles.remove_Load($FormEvent_Load)
$formSearchingFiles.remove_Load($Form_StateCorrection_Load)
$formSearchingFiles.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch [Exception]{ }
}
# formSearchingFiles
$formSearchingFiles.Controls.Add($label)
$formSearchingFiles.Controls.Add($progressbar)
$formSearchingFiles.ClientSize = '394, 122'
$formSearchingFiles.FormBorderStyle = 'FixedDialog'
$formSearchingFiles.MaximizeBox = $False
$formSearchingFiles.Name = "formSearchingFiles"
$formSearchingFiles.StartPosition = 'CenterScreen'
$formSearchingFiles.Text = "Compatibility Checker"
$formSearchingFiles.add_Load($FormEvent_Load)
# label
$label.Location = '12, 27'
$label.Name = "label"
$label.Size = '368, 26'
$label.TabIndex = 1
$label.Text = "Searching for files, please wait.."
$label.TextAlign = 'MiddleCenter'
# progressbar
$progressbar.Location = '12, 68'
$progressbar.MarqueeAnimationSpeed = 40
$progressbar.Name = "progressbar"
$progressbar.Size = '370, 30'
$progressbar.Style = 'Marquee'
$progressbar.TabIndex = 0
#Save the initial state of the form
$InitialFormWindowState = $formSearchingFiles.WindowState
#Init the OnLoad event to correct the initial state of the form
$formSearchingFiles.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$formSearchingFiles.add_FormClosed($Form_Cleanup_FormClosed)
#Show the Form
return $formSearchingFiles.ShowDialog()
} #End Function
#Call OnApplicationLoad to initialize
if((OnApplicationLoad) -eq $true)
{
#Call the form
Call-Searching_pff | Out-Null
#Perform cleanup
OnApplicationExit
}
}