Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winforms FolderBrowser对话框带到前面_Winforms_Powershell_Folderbrowserdialog - Fatal编程技术网

Winforms FolderBrowser对话框带到前面

Winforms FolderBrowser对话框带到前面,winforms,powershell,folderbrowserdialog,Winforms,Powershell,Folderbrowserdialog,我有下面的PowerShell函数,它工作得很好,但是窗口在PowerShell ISE后面的后台打开 显示文件夹浏览器对话框并设置为变量 函数Get FolderName{ 添加类型-AssemblyName System.Windows.Forms $FolderBrowser=新对象System.Windows.Forms.FolderBrowser对话框-属性@{ SelectedPath='C:\Temp' ShowNewFolderButton=$false Description=

我有下面的PowerShell函数,它工作得很好,但是窗口在PowerShell ISE后面的后台打开

显示文件夹浏览器对话框并设置为变量 函数Get FolderName{ 添加类型-AssemblyName System.Windows.Forms $FolderBrowser=新对象System.Windows.Forms.FolderBrowser对话框-属性@{ SelectedPath='C:\Temp' ShowNewFolderButton=$false Description=选择暂存文件夹。 } 如果单击“取消”,脚本将退出 如果$FolderBrowser.ShowDialog-eq取消{break} $FolderBrowser.SelectedPath }end函数Get FolderName 我可以看到OpenFileDialog类可以使用.topmest属性,但它似乎没有转移到FolderBrowserDialog类

我遗漏了什么吗?

希望这能有所帮助

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方法有两种重载变体

见文件:

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

最上面的部分应该少用或根本不用!如果多个窗口是最上面的,那么哪个窗口是最上面的- 首先尝试将窗口设置为母窗口,然后OpenfileDialog/SaveFileDialog应始终显示在窗口上方:

$openFileDialog1.ShowDialog($form1)
如果这还不够,就拿最上面的

您的对话窗口继承了母亲的属性。如果主窗口是最上面的,则对话框也是最上面的

下面是一个将对话设置为最顶层的示例

但是,在本例中,使用了一个新的未绑定窗口,因此对话框处于未绑定状态

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

一种可靠的方法是向函数中添加一段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." }

我刚刚找到了一种获取PowerShell的iwin32窗口值的简单方法,因此表单可以是模态的。创建System.Windows.Forms.NativeWindow对象并为其分配PowerShell句柄

function Show-FolderBrowser 
{       
    Param ( [Parameter(Mandatory=1)][string]$Title,
            [Parameter(Mandatory=0)][string]$DefaultPath = $(Split-Path $psISE.CurrentFile.FullPath),
            [Parameter(Mandatory=0)][switch]$ShowNewFolderButton)

    $DefaultPath = UNCPath2Mapped -path $DefaultPath; 

    $FolderBrowser = new-object System.Windows.Forms.folderbrowserdialog;
    $FolderBrowser.Description = $Title;
    $FolderBrowser.ShowNewFolderButton = $ShowNewFolderButton;
    $FolderBrowser.SelectedPath = $DefaultPath;
    $out = $null;

    $caller = [System.Windows.Forms.NativeWindow]::new()
    $caller.AssignHandle([System.Diagnostics.Process]::GetCurrentProcess().MainWindowHandle)

    if (($FolderBrowser.ShowDialog($caller)) -eq [System.Windows.Forms.DialogResult]::OK.value__)
    {
        $out = $FolderBrowser.SelectedPath;
    }

    #Cleanup Disposabe Objects
    Get-Variable -ErrorAction SilentlyContinue -Scope 0  | Where-Object {($_.Value -is [System.IDisposable]) -and ($_.Name -notmatch "PS\s*")} | ForEach-Object {$_.Value.Dispose(); $_ | Clear-Variable -ErrorAction SilentlyContinue -PassThru | Remove-Variable -ErrorAction SilentlyContinue -Force;}

    return $out;
}

好的,我确实在搜索中找到了这个方法,但它似乎并不总是有效,只是似乎阻止了vscode在控制台中接受密钥输入,以便在之后进行凭证调用。希望在我提供的原始代码中向我的属性列表中添加TopMost=$true,但不喜欢它,也不明白为什么它可以用于您的…?@jaapap不幸的是,您的编辑都是关于OpenFileDialog,而不是Hi-Theo,非常感谢您的帮助和提供此代码。由于截止日期的关系,我不得不把这个要求放在列表的后面,但如果可以的话,我会重新考虑。对于迟来的答复表示歉意,但我们对此表示感谢。