FolderBrowserDialog置于最前面

时间:2019-01-04 10:38:08

标签: winforms powershell folderbrowserdialog

我具有以下运行良好的PowerShell功能,但是该窗口在PowerShell ISE背后的背景中打开。

Device.BeginInvokeOnMainThread

我看到有一个Device.BeginInvokeOnMainThread(() => { await App.Current.MainPage.DisplayAlert("Hello", "message", "OK"); }); 类可以使用的# 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类中。

我想念什么吗?

3 个答案:

答案 0 :(得分:2)

希望这会有所帮助

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
}

//编辑以评论

ShowDialog()方法有两种变体(重载)。

请参阅文档:http://msdn.microsoft.com/en-us/library/system.windows.forms.openfiledialog.showdialog%28v=vs.110%29.aspx

在第二个变体中,您可以指定应该作为对话框之母的窗口。

最上面的部分应该很少使用或根本不使用!如果多个窗口位于最顶层,那么哪个位于最顶层? ;-)) 首先尝试将您的窗口设置为母亲,然后OpenfileDialog / SaveFileDialog应始终出现在窗口上方:

$openFileDialog1.ShowDialog($form1)

如果那还不够,请选择最高。

您的对话窗口继承了母亲的属性。如果您的母窗口位于最上方,则对话框也位于最上方。

这里是将对话设置为最高的示例。

但是,在此示例中,使用了一个新的未绑定窗口,因此该对话框未绑定。

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

答案 1 :(得分:1)

一种可靠的方法是在函数中添加一段C#代码。 使用该代码,您可以获得实现IWin32Window接口的Windows句柄。在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." }

答案 2 :(得分:0)

我刚刚找到一种简单的方法来获取PowerShell的IWin32Window值,因此表单可以是模态的。创建一个System.Windows.Forms.NativeWindow对象,并将PowerShell的句柄分配给它。

If Not Exist "flag.txt" (Echo 1)>"flag txt"