1

我使用功能foreach-parallel运行许多脚本块,如运行空间,第一个加载管理单元正确,但接下来都返回 2 错误

1..5 | Foreach-Parallel -Throttle 5 -Timeout 5 -sleeptimer 5 {
   add-PSSnapin 'Quest.ActiveRoles.ADManagement'
    try {
        get-qadUser 'Domain\me'
    } catch {
        return "$($Error[0].Exception)"
    }
}

我的错误是:

add-PSSnapin :已添加具有相同键的项目

get-qadUser : 函数不存在

4

4 回答 4

1

在 runspacePool 中,该命令Add-PSSnapin不起作用Import-Module!它需要添加初始默认状态而不是 ScriptBlock:

    $ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
    [void]$ISS.ImportPSSnapIn('Quest.ActiveRoles.ADManagement', [ref]$null)
    [void]$ISS.ImportPSModule('PSTerminalServices')
    $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
    $RunspacePool.Open()
于 2016-03-15T09:59:09.387 回答
0

我在上面对我认为您应该做的事情发表了评论,但为了澄清您将要确保在调用之前加载管理单元,因此请确保在运行Foreach-parallel.

add-PSSnapin 'Quest.ActiveRoles.ADManagement'

Foreach-Parallel -Throttle 5 -Timeout 5 -sleeptimer 5 {
   get-qadUser 'domain\testUser'
}
于 2016-03-11T17:42:36.790 回答
0

有一种简单的方法可以测试 cmdlet,如果找不到,请添加 PSSnapin 或Import-Module

将以下内容添加到脚本的开头将检查是否存在 CMDLET,如果未找到,请添加它。

IF(
 Get-Command get-qadUser -ErrorAction SilentlyContinue){}
ELSE{add-PSSnapin 'Quest.ActiveRoles.ADManagement'}
于 2016-03-11T17:46:25.343 回答
0

最后我使用另一个代码,我使用的是这样的:

$Servers | Run-Parallel -scriptBlock $ScriptBlock -TimeOut 10 -PSModules 'PSTerminalServices' -PSSnapins 'Quest.ActiveRoles.ADManagement' | out-gridView

完整代码

    function Run-Parallel {
        <#
            .Synopsis
                This is a quick and open-ended script multi-threader searcher
                http://www.get-blog.com/?p=189#comment-28834
                Improove by Alban LOPEZ 2016

            .Description
                This script will allow any general, external script to be multithreaded by providing a single
                argument to that script and opening it in a seperate thread.  It works as a filter in the 
                pipeline, or as a standalone script.  It will read the argument either from the pipeline
                or from a filename provided.  It will send the results of the child script down the pipeline,
                so it is best to use a script that returns some sort of object.

                Authored by Ryan Witschger - http://www.Get-Blog.com

            .PARAMETER ScriptBlock
                This is where you provide the PowerShell ScriptBlock that you want to multithread.  

            .PARAMETER ItemObj
                The ItemObj represents the arguments that are provided to the child script.  This is an open ended
                argument and can take a single object from the pipeline, an array, a collection, or a file name.  The 
                multithreading script does it's best to find out which you have provided and handle it as such.  
                If you would like to provide a file, then the file is read with one object on each line and will 
                be provided as is to the script you are running as a string.  If this is not desired, then use an array.

            .PARAMETER InputParam
                This allows you to specify the parameter for which your input objects are to be evaluated.  As an example, 
                if you were to provide a computer name to the Get-Process cmdlet as just an argument, it would attempt to 
                find all processes where the name was the provided computername and fail.  You need to specify that the 
                parameter that you are providing is the "ComputerName".

            .PARAMETER AddParam
                This allows you to specify additional parameters to the running command.  For instance, if you are trying
                to find the status of the "BITS" service on all servers in your list, you will need to specify the "Name"
                parameter.  This command takes a hash pair formatted as follows:  

                @{"key" = "Value"}
                @{"key1" = "Value"; "key2" = 321; "key3" = 1..9}

            .PARAMETER AddSwitch
                This allows you to add additional switches to the command you are running.  For instance, you may want 
                to include "RequiredServices" to the "Get-Service" cmdlet.  This parameter will take a single string, or 
                an aray of strings as follows:

                "RequiredServices"
                @("RequiredServices", "DependentServices")

            .PARAMETER MaxThreads
                This is the maximum number of threads to run at any given time.  If resources are too congested try lowering
                this number.  The default value is 20.

            .PARAMETER SleepTimer
                This is the time between cycles of the child process detection cycle.  The default value is 200ms.  If CPU 
                utilization is high then you can consider increasing this delay.  If the child script takes a long time to
                run, then you might increase this value to around 1000 (or 1 second in the detection cycle).

            .PARAMETER TimeOut
                this is the timeOut for slower instance, only each other are returned

            .PARAMETER PSModules
                List of PSModule name to include for use in ScriptBlock

            .PARAMETER PSSapins
                List of PSSapin name to include for use in ScriptBlock

            .EXAMPLE
                Both of these will execute the scriptBlock and provide each of the server names in AllServers.txt
                while providing the results to GridView.  The results will be the output of the child script.

                gc AllServers.txt | Run-Parallel $ScriptBlock_GetTSUsers -MaxThreads $findOut_AD.ActiveDirectory.Servers.count -PSModules 'PSTerminalServices' | out-gridview
        #>
        Param(
            [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
                $ItemObj,
            [ScriptBlock]$ScriptBlock = $null, 
            $InputParam = $Null,
            [HashTable] $AddParam = @{},
            [Array] $AddSwitch = @(),
            $MaxThreads = 20,
            $SleepTimer = 200,
            $TimeOut = 5,
            [string[]]$PSSapins = $null,
            [string[]]$PSModules = $null
        )
        Begin{
            $ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
            ForEach ($Snapin in $PSSapins){
                [void]$ISS.ImportPSSnapIn($Snapin, [ref]$null)
            }
            ForEach ($Module in $PSModules){
                [void]$ISS.ImportPSModule($Module)
            }
            $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
            $RunspacePool.Open()
            $Jobs = @()
            if ($CommonObject.Settings.Debug) {$CommonObject.host.ui.WriteLine("[  Start  ] :")}
        }
        Process{
            Write-Progress -Activity "Preloading Threads" -Status "Starting Job $($jobs.count)"
            #ForEach ($Object in $ItemObj){
                if ($ItemObj){
                    $PowershellThread = [powershell]::Create().AddScript($ScriptBlock)

                    If ($InputParam -ne $Null){
                        $PowershellThread.AddParameter($InputParam, $ItemObj.ToString()) | out-null
                    }Else{
                        $PowershellThread.AddArgument($ItemObj.ToString()) | out-null
                    }
                    ForEach($Key in $AddParam.Keys){
                        $PowershellThread.AddParameter($Key, $AddParam.$key) | out-null
                    }
                    ForEach($Switch in $AddSwitch){
                        $PowershellThread.AddParameter($Switch) | out-null
                    }
                    $PowershellThread.RunspacePool = $RunspacePool
                    $Handle = $PowershellThread.BeginInvoke()
                    $Job =  [pscustomobject][ordered]@{Handle=''; Thread=''; object=''}
                    $Job.Handle = $Handle
                    $Job.Thread = $PowershellThread
                    $Job.Object = $ItemObj.ToString()
                    $Jobs += $Job
                    if ($CommonObject.Settings.Debug) {$CommonObject.host.ui.WriteLine("`t$ItemObj")}
                }
            #}
        }
        End{
            $ResultTimer = Get-Date
            While (@($Jobs | Where-Object {$_.Handle -ne $Null}).count -gt 0)  {

                $Remaining = "$($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).object)"
                If ($Remaining.Length -gt 60){
                    $Remaining = $Remaining.Substring(0,60) + "..."
                }
                Write-Progress `
                    -Activity "Waiting for Jobs - $($MaxThreads - $($RunspacePool.GetAvailableRunspaces())) of $MaxThreads threads running" `
                    -PercentComplete (($Jobs.count - $($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).count)) / $Jobs.Count * 100) `
                    -Status "$(@($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False})).count) remaining - $remaining" 

                ForEach ($Job in $($Jobs | Where-Object {$_.Handle.IsCompleted -eq $True})){
                    $Job.Thread.EndInvoke($Job.Handle)
                    $Job.Thread.Dispose()
                    $Job.Thread = $Null
                    $Job.Handle = $Null
                    $ResultTimer = Get-Date
                }
                If (($(Get-Date) - $ResultTimer).totalseconds -gt $TimeOut){
                    $NOK = $($Jobs | Where-Object {$_.Handle})
                    if ($CommonObject.Settings.Debug) {$CommonObject.host.ui.WriteErrorLine("[ TimeOut ] $($NOK.count) : $($NOK.object)")}
                    $NOK | %{
                        if ($CommonObject.Settings.Debug) {$CommonObject.host.ui.WriteErrorLine("[ stop ] $($_.object)")}
                        $_.thread.Stop() | Out-Null
                        if ($CommonObject.Settings.Debug) {$CommonObject.host.ui.WriteErrorLine("[ dispose ] $($_.object)")}
                        $_.thread.Dispose()
                        if ($CommonObject.Settings.Debug) {$CommonObject.host.ui.WriteErrorLine("[ null ] $($_.object)")}
                        $_.Thread = $Null
                        $_.Handle = $Null
                    }
                    $RunspacePool.Close() | Out-Null
                    $RunspacePool.Dispose() | Out-Null
                    exit
                }
                Start-Sleep -Milliseconds $SleepTimer
            } 
            $RunspacePool.Close() | Out-Null
            $RunspacePool.Dispose() | Out-Null
        } 
    }
于 2016-04-04T13:06:04.677 回答