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

问题描述

我正在处理一个脚本,该脚本会提示您复制整个文件夹结构,包括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 ($sourceDrive.Length -eq 0) {
    break
}

(关于使用breakreturn还是exit,请看here。)

当然,如果用户单击“确定”但未填写输入框,则字符串也将为空。但是我认为您可以平等地对待这两种情况。或者,您可以使用Windows窗体创建自己的prompt dialog,然后返回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时都按“取消”,则脚本退出