I'm writing PS Script and following block of code shows dialogbox below windows forms gui.
$btn1 = New-Object Windows.Forms.Button
$btn1.Text = "Wybierz folder projektowy"
$btn1.Location = New-Object System.Drawing.Point(170,140)
$btn1.Size = New-Object System.Drawing.Size(160,20)
$btn1.add_Click({
function Select-Folder($message='Select a folder', $path = 0) {
$object = New-Object -comObject Shell.Application
$object.topmost=$true
$folder = $object.BrowseForFolder(0, $message, 0, $path)
if ($folder -ne $null) {
$folder.self.Path
}
}
$folderPath = Select-Folder 'Select the folder where the move scripts reside'
If ($folderPath) {
Set-Content -Path "C:\Projekty\logs\temp_path.txt" -Value $folderPath.ToString() -Encoding Unicode
write-host $folderPath
get-content -Path "C:\Projekty\logs\temp_path.txt"
}
Else { Write-Host 'I do not have a folder path' }
})
$form_acl.Controls.Add($btn1)
Is there any way to make it display on top? Here's screenshot of a problem:
Theo's helpful answer shows an alternative, WinForms-based way to invoke a folder-browsing dialog, via the System.Windows.Forms.FolderBrowserDialog
class.
However, it seems that all that is missing from your original approach is to pass your form's window handle (hWND, .Handle
) as the first argument to the Shell.Application
COM object's .BrowseForFolder()
method, which makes it the dialog's owner window and therefore shows the dialog on top of it - even if the form itself has the .TopMost
property set:
$folder = (New-Object -ComObject Shell.Application).BrowseForFolder(
$form_acl.Handle, # Pass your form's window handle to make it the owner window
$message,
0,
$path)
Here's a simplified, self-contained example (requires PSv5+, but can be adapted to earlier versions):
using namespace System.Windows.Forms
using namespace System.Drawing
Add-Type -AssemblyName System.Windows.Forms
# Create a sample topmost form with a single
# button that invokes a folder-browsing dialog.
($form = [Form] @{
Text = "Topmost Form"
Size = [Size]::new(300, 100)
TopMost = $true # Make the form topmost.
StartPosition = 'CenterScreen'
}).Controls.AddRange(@(
($folderBrowseButton = [Button] @{
Location = [Point]::new(70, 20)
Size = [Size]::new(160,30)
Text = 'Browse for Folder'
})
))
$folderBrowseButton.add_Click({
$path = 'C:\'
# IMPORTANT: Pass $form.Handle, the form's window handle (HWND) as the first argument, which
# makes the form the owning window, ensuring that the dialog is displayed on
# top - even if the form itself is set to topmost.
$folder = (New-Object -ComObject Shell.Application).BrowseForFolder(
$form.Handle,
'Pick a target folder:',
0, # Options
$path # Starting directory path.
)
if ($null -ne $folder) {
Write-Verbose -vb ('Folder picked: ' + $folder.self.Path)
} else {
Write-Verbose -vb 'Folder browsing canceled.'
}
})
$null = $form.ShowDialog()