在当前脚本上下文中运行PowerShell后台任务

时间:2018-12-06 14:46:59

标签: powershell sharepoint background-process sharepoint-online

我已经编写了一个GUI脚本来在SharePoint Online(SPO)中执行各种管理任务。

一个特定的api调用来获取SPO组需要很长时间(大约150秒)。我已经使用SPO cmdlet测试了此调用,还使用SharePoint DLL手动获取了组,这两个过程大致相同。问题在于查询SharePoint意味着您需要询问组集合,然后在该集合中查找每个组,然后进行检索。这是一个很大的电话,因为我正在使用的SPO网站大约有300个小组。

为了加快通话速度,我想到了异步执行每个通话的想法,以使所有通话一次(而不是一个接一个)发送出去。

我使用以下资源提出了解决方案:Adam the automators blogthis SO answerthis blog on limiting no of executing tasks

我从前两个来源实现解决方案时,代码在测试脚本中有效,但在主要解决方案中无效。我之所以要求PowerShell分配300个不同的进程,是因为我的计算机(虽然功能强大)很快就使CPU和RAM使用率最大化。因此,我实施了第3个源代码来限制我同时运行的任务数量。

现在,当我去调用SPO api时,进程执行范围会引起问题。要使用PowerShell SPO库(cmdlet),您需要调用connect函数,该函数会验证您的SPO凭据并建立连接:

Connect-SPOService -Url https://$orgName.sharepoint.com/ -Credential $credentials

在您拨打电话之前,没有电话可用。

让我们看一下我的功能:

function Get-Sharepoint-Groups-Async {
    Begin {
        $sw = [Diagnostics.Stopwatch]::StartNew()

        Write-Debug ("Starting {0} " -f $MyInvocation.MyCommand)

        #Create an hashtable variable 
        [hashtable]$Return = @{} 
        $Return.OutCode = 0
        $Return.OutData = {}
        $Return.OutDataShort = ""
    }

    Process {
        try {
            $web = $context.Web

            $groupCollection = $web.SiteGroups

            $context.Load($groupCollection)
            $context.ExecuteQuery()

            $jobs = @()

            $maxConcurrentJobs = 25

            foreach ($spGroup in $groupCollection) {
                $Check = $false
                while ($Check -eq $false) {
                    if ((Get-Job -State 'Running').Count -lt $maxConcurrentJobs) {
                        $jobs += Start-Job -ScriptBlock $sScriptBlock -ArgumentList @($groupTitle, $context)
                        $Check = $true #To stop endless looping and proceed to the next object in the list.
                    }
                }
            }

            Wait-Job -Job $jobs | Out-Null
            $results = Receive-Job -Job $jobs

            $groups = @()
            foreach ($job in $jobs) {
                $group = New-Object PSObject
                $group | Add-Member NoteProperty LoginName $job.LoginName
                $group | Add-Member NoteProperty Title $job.Title
                $group | Add-Member NoteProperty Users $job.Users
                $group | Add-Member NoteProperty Roles $job.Roles
            }

            $Return.OutData = $groups
        } catch {
            Write-Error $Error.item(0)
            $Return.OutCode = 2
            $Return.OutData = $Error.item(0)
            $Return.OutDataShort = $Error.item(0)
        }
    }

    End {
        $sw.Stop()

        Write-Debug ("Ending {0} " -f $MyInvocation.MyCommand)

        $outmsg = "Function: Get-SharePoint-Groups-Async took '$($sw.Elapsed.TotalSeconds)s' to execute."
        Write-Host $outmsg

        return $Return
    }
}

这是执行的$scriptBlock代码:

$sScriptBlock = {
    Param($spGroup, $context)

    try {  
        Write-Host -ForegroundColor DarkGreen "Loading group: $($spGroup.Title)"

        $context.Load($spGroup)
        $context.ExecuteQuery()

        $groupUsers = $spGroup.Users
        $context.Load($groupUsers)
        $context.ExecuteQuery()

        #Get group users (easier to use cmdlet then query sp)
        $spGroupUsers = Get-SPOUser -Site $Site -Group $spGroup.Title

        $users = @()

        foreach ($spUser in $spGroupUsers) {
            $users += $spUser.LoginName
        }

        $group = New-Object PSObject
        $group | Add-Member NoteProperty LoginName $spGroup.LoginName
        $group | Add-Member NoteProperty Title $spGroup.Title
        $group | Add-Member NoteProperty Users $users
        $group | Add-Member NoteProperty Roles "Unknown"

        return $group
    } catch {
        Write-Error $Error.item(0)
        return $null
    }
}

无论我在执行块内做什么,我都无法使用当前的脚本上下文。如果我使用SPO cmdlet,则每次都需要调用connect,这会使调用效率低下,因此同步进行会更快。如果我尝试使用上下文(在脚本的其他位置设置,并且可以在任何地方使用)查询SPO API,则会收到错误消息,指出方法不存在。

我并没有做太多的工作,我还没有真正看到人们在SharePoint上的其他地方这样做,所以我有点卡住了。

关于如何从后台任务中查询SPO而不每次都调用connect的任何想法?

PS:Connect不会返回我可以传递给这些进程的任何东西。

0 个答案:

没有答案