单击取消按钮时如何使我的脚本停止?

How can I make my script stop when clicked on the cancel Button?

我正在编写一个脚本,提示您复制整个文件夹结构,包括 ACL(权限)
我现在的问题是我怎样才能做到当我点击弹出窗口中的取消按钮时它实际上取消了?

我正在使用 powershell :)

**#----------------------Source Drive and Folder---------------------#
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$sourceDrive = [Microsoft.VisualBasic.Interaction]::InputBox("Please enter the source drive for copying `n(e.g: C)", "source drive", "")
$sourceFolder = [Microsoft.VisualBasic.Interaction]::InputBox("Please enter the source folder for copying `n(e.g: Folder\Something)", "source folder", "")
#----------------------Source Drive and Folder---------------------#

#-------------------Destination Drive and Folder-------------------#
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$destinationDrive = [Microsoft.VisualBasic.Interaction]::InputBox("Please enter the destination drive for copying `n(e.g: D)", "destination drive", "")
$destinationFolder = [Microsoft.VisualBasic.Interaction]::InputBox("Please enter the destination folder for copying `n(e.g: Folder1\Something2)", "destination folder", "")
#-------------------Destination Drive and Folder-------------------#

#--------------------Create new Folder for Copy--------------------#
$createNewFolder = [Microsoft.VisualBasic.Interaction]::InputBox("Do you want to create a new folder in this directory? `n(e.g: y/n)", "Create new folder", "")

if($createNewFolder -eq "n"){
    xcopy "$sourceDrive`:$sourceFolder" "$destinationDrive`:$destinationFolder" /O /X /E /H /K
}elseif($createNewFolder -eq "y") {
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
    $newFolder = [Microsoft.VisualBasic.Interaction]::InputBox("Please enter the name of the folder `n(e.g: somefolder)", "New folder", "")
    xcopy "$sourceDrive`:$sourceFolder" "$destinationDrive`:$newfolder$destinationFolder" /O /X /E /H /K
}else {

}
#--------------------Create new Folder for Copy--------------------#

#xcopy "$sourceDrive`:$sourceFolder" "$destinationDrive`:$destinationFolder" /O /X /E /H /K**

这也在 powershell.org 中发布:https://powershell.org/forums/topic/how-can-i-make-my-script-stop-when-clicked-on-the-cancel-button-2/

提前致谢

马丁

根据 documentation:

If the user clicks Cancel, a zero-length string is returned.

所以你总是可以做

if ($sourceDrive.Length -eq 0) {
    break
}

(至于用breakreturn还是exit,看here。)

当然,如果用户点击确定但没有填写输入框,字符串也会为空。但我认为你可以平等对待这两种情况。或者,您可以创建自己的 prompt dialog 和 Windows 表单,以及 return 一个 DialogResult。

请注意,这不是在 Powershell 脚本中获取输入的推荐方式。你应该使用 Read-Host:

$value = Read-Host "Enter value"

或者更好的是,使用 parameters(powershell 会自动提示输入)

param (
    [Parameter(Mandatory = $true, HelpMessage = "Please enter the source drive")]
    [ValidatePattern("[a-z]:")]
    [string]$SourceDrive
)

就我个人而言,我不明白您为什么要使用所有这些 InputBox,您只需使用 FolderBrowser 对话框(两次)就足够了。
通过使用该对话框,您还可以确保用户不会只是输入任何内容,并且您不必检查每一步。

下面的函数 Get-FolderPath 是一个辅助函数,用于包装 BrowseForFolder 对话框的调用,让您的生活更轻松。

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

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

        [switch]$ShowNewFolderButton
    )

    # Browse Dialog Options:
    # https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfoa
    $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

    # ShellSpecialFolderConstants for InitialDirectory:
    # https://docs.microsoft.com/en-us/windows/win32/api/shldisp/ne-shldisp-shellspecialfolderconstants#constants

    $folder = $browser.BrowseForFolder($handle, $Message, $browserForFolderOptions, $InitialDirectory)

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

    # 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
}

将它放在脚本的顶部,代码可以像这样简单:

$source = Get-FolderPath -Message 'Please enter the source folder to copy'
# if $null is returned, the user cancelled the dialog
if ($source) { 
    # the sourcefolder is selected, now lets do this again for the destination path
    # by specifying switch '-ShowNewFolderButton', you allow the user to create a new folder
    $destination = Get-FolderPath -Message 'Please enter the destination path to copy to' -ShowNewFolderButton
    if ($destination) {
        # both source and destination are now known, so start copying
        xcopy "$source" "$destination" /O /X /E /H /K
    }
}

如果用户在您两次调用 Get-FolderPath 的任何时候按 'Cancel',脚本将退出