FolderBrowserDialog вывести на передний план - PullRequest
0 голосов
/ 04 января 2019

У меня есть следующая функция PowerShell, которая работает хорошо, но окно открывается в фоновом режиме позади PowerShell ISE.

# Shows folder browser dialog box and sets to variable
function Get-FolderName() {
    Add-Type -AssemblyName System.Windows.Forms
    $FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{
        SelectedPath = 'C:\Temp\'
        ShowNewFolderButton = $false
        Description = "Select Staging Folder."
    }
    # If cancel is clicked the script will exit
    if ($FolderBrowser.ShowDialog() -eq "Cancel") {break}
    $FolderBrowser.SelectedPath
} #end function Get-FolderName

Я вижу, что есть свойство .TopMost, которое можно использовать сOpenFileDialog класс, но это не похоже на FolderBrowserDialog класс.

Я что-то упустил?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Надежный способ сделать это - добавить фрагмент кода на C # в функцию. С этим кодом вы можете получить дескриптор Windows, который реализует интерфейс IWin32Window. Использование этого маркера в функции ShowDialog обеспечит отображение диалогового окна сверху.

Function Get-FolderName {   
    # To ensure the dialog window shows in the foreground, you need to get a Window Handle from the owner process.
    # This handle must implement System.Windows.Forms.IWin32Window
    # Create a wrapper class that implements IWin32Window.
    # The IWin32Window interface contains only a single property that must be implemented to expose the underlying handle.
    $code = @"
using System;
using System.Windows.Forms;

public class Win32Window : IWin32Window
{
    public Win32Window(IntPtr handle)
    {
        Handle = handle;
    }

    public IntPtr Handle { get; private set; }
}
"@

    if (-not ([System.Management.Automation.PSTypeName]'Win32Window').Type) {
        Add-Type -TypeDefinition $code -ReferencedAssemblies System.Windows.Forms.dll -Language CSharp
    }
    # Get the window handle from the current process
    # $owner = New-Object Win32Window -ArgumentList ([System.Diagnostics.Process]::GetCurrentProcess().MainWindowHandle)
    # Or write like this:
    $owner = [Win32Window]::new([System.Diagnostics.Process]::GetCurrentProcess().MainWindowHandle)

    # Or use the the window handle from the desktop
    # $owner =  New-Object Win32Window -ArgumentList (Get-Process -Name explorer).MainWindowHandle
    # Or write like this:
    # $owner = [Win32Window]::new((Get-Process -Name explorer).MainWindowHandle)

    $FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{
        SelectedPath = 'C:\Temp\'
        ShowNewFolderButton = $false
        Description = "Select Staging Folder."
    }
    # set the return value only if a selection was made
    $result = $null
    If ($FolderBrowser.ShowDialog($owner) -eq "OK") {
        $result = $FolderBrowser.SelectedPath
    }
    # clear the dialog from memory
    $FolderBrowser.Dispose()

    return $result
}

Get-FolderName

Вы также можете выбрать объект Shell.Application с чем-то вроде этого:

# Show an Open Folder Dialog and return the directory selected by the user.
function Get-FolderName {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)]
        [string]$Message = "Select a directory.",

        [string]$InitialDirectory = [System.Environment+SpecialFolder]::MyComputer,

        [switch]$ShowNewFolderButton
    )

    $browserForFolderOptions = 0x00000041                                  # BIF_RETURNONLYFSDIRS -bor BIF_NEWDIALOGSTYLE
    if (!$ShowNewFolderButton) { $browserForFolderOptions += 0x00000200 }  # BIF_NONEWFOLDERBUTTON

    $browser = New-Object -ComObject Shell.Application
    # To make the dialog topmost, you need to supply the Window handle of the current process
    [intPtr]$handle = [System.Diagnostics.Process]::GetCurrentProcess().MainWindowHandle

    # see: https://msdn.microsoft.com/en-us/library/windows/desktop/bb773205(v=vs.85).aspx
    $folder = $browser.BrowseForFolder($handle, $Message, $browserForFolderOptions, $InitialDirectory)

    $result = $null
    if ($folder) { 
        $result = $folder.Self.Path 
    } 

    # Release and remove the used Com object from memory
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($browser) | Out-Null
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()


    return $result
}

$folder = Get-FolderName
if ($folder) { Write-Host "You selected the directory: $folder" }
else { "You did not select a directory." }
0 голосов
/ 04 января 2019

Надеюсь, это поможет

Add-Type -AssemblyName System.Windows.Forms
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$FolderBrowser.Description = 'Select the folder containing the data'
$result = $FolderBrowser.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true }))
if ($result -eq [Windows.Forms.DialogResult]::OK){
$FolderBrowser.SelectedPath
} else {
exit
}

// Редактировать для комментария

Существует 2 варианта (перегрузки) метода ShowDialog ().

См. Документацию: http://msdn.microsoft.com/en-us/library/system.windows.forms.openfiledialog.showdialog%28v=vs.110%29.aspx

Во втором варианте вы можете указать окно, которое должно быть матерью диалога.

Topmost следует использовать экономно или не использовать вообще!Если несколько окон являются самыми верхними, то какие из них самые верхние?;-)) Сначала попытайтесь установить ваше окно как мать, затем OpenfileDialog / SaveFileDialog всегда должен отображаться над вашим окном:

$openFileDialog1.ShowDialog($form1)

Если этого недостаточно, возьмите Topmost.

Ваш диалогОкно наследует свойства от матери.Если ваше главное окно является самым верхним, то диалоговое окно также является самым верхним.

Вот пример, который устанавливает диалог Самое верхнее.

В этом примере, однако, используется новое несвязанное окно, поэтомудиалог не связан.

$openFileDialog1.ShowDialog((New - Object System.Windows.Forms.Form - Property @{TopMost = $true; TopLevel = $true}))
...