BrowseForFolders 不显示在顶部

BrowseForFolders doesn't display on top

我正在编写 PS 脚本,下面的代码块显示下面的对话框 windows 形式的 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) 

有什么办法让它显示在最上面吗? 这是问题的屏幕截图:

您可以试试这个替代方法:

function Select-Folder {
    [CmdletBinding()]
    param (
        #  sets the descriptive text displayed above the tree view control in the dialog box
        [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)]
        [string]$Message = "Please select a directory.",

        # sets the (pre)selected path
        [Parameter(Mandatory=$false, Position=1)]
        [string]$InitialDirectory,

        # sets the root folder where the browsing starts from
        [Parameter(Mandatory=$false)]
        [System.Environment+SpecialFolder]$RootFolder = [System.Environment+SpecialFolder]::Desktop,

        # sets a value indicating whether the 'New Folder' button appears in the folder browser dialog box
        [switch]$ShowNewFolderButton
    )
    Add-Type -AssemblyName System.Windows.Forms
    [System.Windows.Forms.Application]::EnableVisualStyles()

    $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
    $dialog.Description         = $Message
    $dialog.SelectedPath        = $InitialDirectory
    $dialog.RootFolder          = $RootFolder
    $dialog.ShowNewFolderButton = $ShowNewFolderButton.IsPresent

    $selected = $null

    # force the dialog TopMost:
    # because the owning window will not be used after the dialog has been closed,
    # you can simply create a new form inside the method call.
    $result = $dialog.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true; TopLevel = $true}))
    if ($result -eq [Windows.Forms.DialogResult]::OK){
        $selected = $dialog.SelectedPath
    }
    # clear the FolderBrowserDialog from memory
    $dialog.Dispose()
    # return the selected folder
    $selected
} 

Select-Folder -Message 'Select the folder where the move scripts reside' -ShowNewFolderButton

shows an alternative, WinForms-based way to invoke a folder-browsing dialog, via the System.Windows.Forms.FolderBrowserDialog class.

但是,似乎 您原来的方法中缺少的只是将表单的 window 句柄 (hWND, .Handle) 作为第一个参数传递给 Shell.Application COM 对象的 .BrowseForFolder() method 使其成为对话框的 所有者 window,因此在顶部显示对话框它的 - 即使表单本身具有 .TopMost 属性 集:

$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)

这是一个简化的、独立的示例(需要 PSv5+,但可以适应更早的版本):

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()