【问题标题】:How can I make my script stop when clicked on the cancel Button?单击取消按钮时,如何使脚本停止?
【发布时间】:2021-02-15 22:10:47
【问题描述】:

我正在编写一个脚本,它会提示您复制整个文件夹结构,包括 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/

提前致谢

马丁

【问题讨论】:

  • 我们的回答有帮助吗?

标签: windows powershell input inputbox


【解决方案1】:

就个人而言,我不明白您为什么要使用所有这些 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 的任何时候都按下“取消”,则脚本退出

【讨论】:

    【解决方案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
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 2020-04-11
      • 1970-01-01
      相关资源
      最近更新 更多