用foreach改变开关行为

时间:2015-07-24 21:52:47

标签: xml powershell switch-statement

我的XML文件包含:

<Setting>
    <Application Id="Main_Form" Name="Office365: Run scripts">
        <task Id="1" Script="SPO-SCDefaults.ps1" Name="Create default Site Collection structure" />
        <task Id="2" Script="SPO-FileMig.ps1" Name="Datacopy to SharePoint cloud" />
        <task Id="3" Script="EXO-AddAdminDistri.ps1" Name="Exchange: Add admin user to distributiongroups" />
        <task Id="4" Script="empty.ps1" Name="Todo..." />
    </Application>
</Setting>

和脚本一样:

$Xml = [xml](Get-Content $ScriptPath\Settings.xml)

function Do-PromptTask
{   
    $task1 = $Xml.Setting.Application.task.name[0]
    $task2 = $Xml.Setting.Application.task.name[1]
    $task3 = $Xml.Setting.Application.task.name[2]
    $task4 = $Xml.Setting.Application.task.name[3]
    $task1_exec = $Xml.Setting.Application.task.script[0]
    $task2_exec = $Xml.Setting.Application.task.script[1]
    $task3_exec = $Xml.Setting.Application.task.script[2]
    $task4_exec = $Xml.Setting.Application.task.script[3]

    switch -wildcard (Prompt-SelectionList "Chose task to run:" @($task1,$task2,$task3,$task4))
    {
        $task1{$task_result = $task1_exec}
        $task2{$task_result = $task2_exec}
        $Task3{$task_result = $task3_exec}
        $Task4{$task_result = $task4_exec}
        ""{Exit} #End Selection (cancel selected)
        "*"{Do-PromptTask} #Keep prompting until "cancel" selected
    }
    Write-Host "$ScriptPath\Bin\$task_result"
}

Do-PromptTask

我认为应该更容易将其更改为:

function Do-PromptTask
{
    switch -wildcard (Prompt-SelectionList "Chose task to run:" @($task['name'])) # Array of all names
    {
        foreach ($node in $Xml.Setting.Application.task) {
            $task['name']{$task_result = $task_exec['script']}
        }
        ""{Exit} #End Selection (cancel selected)
        "*"{Do-PromptTask} #Keep prompting until "cancel" selected
    }
    Write-Host "$ScriptPath\Bin\$task_result"
}

Do-PromptTask

这可能吗?我也许正确的方式?我希望能够在XML中添加项目时动态生成表单中的列表

3 个答案:

答案 0 :(得分:0)

我想我会完全避免使用switch,并且这样做:

function Do-PromptTask
{   
    $sel = $null
    while ($Xml.Setting.Application.task.name -notcontains $sel) {
        $sel = Prompt-SelectionList "Chose task to run:" $Xml.Setting.Application.task.name
        if ([String]::IsNullOrEmpty($sel)) {
            exit
        }
    }
    $task_result = & ($Xml.Setting.Application.task | Where-Object { $_.name -eq $sel } | Select-Object -ExpandProperty Script)

    Write-Host "$ScriptPath\Bin\$task_result"
}

基本上利用XML的数组属性,从不引用单个索引。

答案 1 :(得分:0)

我不会使用Switch,因为你希望它是动态的。我将哈希表与您的任务名称一起用作键,您的任务可以作为值块以scriptblocks的形式执行。像这样:

Do{
    $AllTasks = @{}
    $Xml.Setting.Application.task | ForEach{$AllTasks.add($_.Name,[scriptblock]::Create($_.Script))}
    $Sel = Prompt-SelectionList "Chose task to run:" $AllTasks.Keys
    If(!$Sel -match "Cancel"){$AllTasks[$Sel].Invoke()}
}While($Sel -notmatch "Cancel")

答案 2 :(得分:0)

我使用@TheMadTechnician中的代码找到答案,在执行表单的代码下面,并在路径中返回脚本名称。相当挑战,但它适用于XML并且是动态的。

$Xml = [xml](Get-Content $ScriptPath\Settings.xml)
. "$ScriptPath\Bin\O365-Functions.ps1"

$Sel = $null

Do {
    $AllTasks = @{}

    $Xml.Setting.Application.task | ForEach { $AllTasks.add($_.Name,[scriptblock]::Create($_.Script)) }
    $Sel = Prompt-SelectionList "Chose task to run:" @($AllTasks.Keys)

    $TaskResult = $ScriptPath+"\Bin\"+$AllTasks[$Sel].ToString()
    Invoke-Expression "&'$TaskResult'"

} While( $Sel -notmatch $null )

感谢您的帮助!