我有以下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我可以看到有一个可以与OpenFileDialog类一起使用的.TopMost属性,但是这个属性似乎没有传递给FolderBrowserDialog类。
我是不是遗漏了什么?
发布于 2019-01-04 18:44:55
希望这能有所帮助
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
在第二个变体中,您可以指定应该是对话框母窗口的窗口。
Topmost应该少用,否则根本不用!如果多个窗口在最上面,那么哪个是最上面的?;-))首先尝试将您的窗口设置为母窗口,然后OpenfileDialog / SaveFileDialog应始终显示在您的窗口上方:
$openFileDialog1.ShowDialog($form1)如果这还不够,那就取最上面的。
您的对话窗口继承了母对话框的属性。如果你的主窗口是最上面的,那么对话框也是最上面的。
下面是一个将对话设置在最上面的示例。
但是,在本例中,使用了一个新的未绑定窗口,因此该对话框未绑定。
$openFileDialog1.ShowDialog((New - Object System.Windows.Forms.Form - Property @{TopMost = $true; TopLevel = $true}))发布于 2019-01-04 19:38:20
执行此操作的一种可靠方法是向函数添加一段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." }发布于 2020-02-13 04:05:58
我刚刚找到了一种简单的方法来获取PowerShell的IWin32Window值,这样表单就可以是模态的。创建一个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;
}https://stackoverflow.com/questions/54037292
复制相似问题