PowerShell工作流中使用Connect-PnPOnline获取SharePoint组信息遇连接问题
Hey there! Let's break down what's causing that connection error in your PowerShell Workflow and fix it up so you can get all your SharePoint group member data properly.
Why You're Seeing That Error
The core issue here is PowerShell Workflow's automatic object serialization. When you store your PnP connection in $KeepAlive and reference it in the ForEach-Parallel block via $workFlow:KeepAlive, the connection object gets deserialized (turned into a plain data object) to pass between workflow runspaces. But Get-PnPGroupMembers needs a live, original SPOnlineConnection object—not this deserialized version. That's why you get the type mismatch error.
Fixed Workflow Code
Here's a revised version of your script that addresses the connection problem and builds your desired array of group/member objects:
workflow GetGroup { param( [Parameter(Mandatory)] [String]$SPOSite, [System.Management.Automation.PSCredential]$SPOCreds ) # Initialize an empty array to store our final results $GroupMemberResults = @() # Use InlineScript to fetch groups with a raw, non-serialized connection $GetGroups = InlineScript { Connect-PnPOnline -Url $using:SPOSite -Credentials $using:SPOCreds # Grab only the properties we need to minimize data passed to parallel blocks Get-PnPGroup | Select-Object LoginName, Title } # Process groups in parallel - lower throttle limit to avoid SPO throttling ForEach -Parallel -ThrottleLimit 10 ($Group in $GetGroups) { try { # Create a fresh PnP connection INSIDE each parallel block $Connection = Connect-PnPOnline -Url $using:SPOSite -Credentials $using:SPOCreds -ReturnConnection # Fetch members for the current group $GroupMembers = Get-PnPGroupMembers -Identity $Group.LoginName -Connection $Connection # Build custom objects for each member $MemberEntries = $GroupMembers | ForEach-Object { [PSCustomObject]@{ GroupName = $Group.Title MemberName = $_.Title MemberEmail = $_.Email } } # Add entries to the shared workflow results array $workflow:GroupMemberResults += $MemberEntries } catch { # Optional: Add error handling for failed group processing Write-Warning "Failed to process group $($Group.Title): $_" } } # Output the complete set of results $GroupMemberResults } # Run the workflow with your site and credentials GetGroup -SPOSite "https://xxx.sharepoint.com/sites/xx" -SPOCreds (Get-Credential)
Key Changes Explained
- InlineScript for Group Fetching: Using
InlineScriptensures we get raw group objects without serialization issues, which makes passing them to parallel blocks smoother. - Per-Parallel-Block Connections: Each parallel runspace gets its own fresh PnP connection—no more trying to reuse a deserialized connection object that won't work.
- Lower Throttle Limit: SharePoint Online has strict concurrency limits. Setting
ThrottleLimitto 10 (adjust based on your tenant's tolerance) prevents you from hitting 429 "Too Many Requests" errors. - Error Handling: The
try/catchblock lets the workflow keep running even if one group fails to process, so you don't lose all your progress. - Structured Results: We build the exact
PSCustomObjectstructure you wanted, with group name, member name, and member email, then collect all entries in a single array.
Quick Notes
- Test the throttle limit: Start with 10 and adjust up if you don't hit throttling, but don't go too high (SPO typically blocks more than 20 concurrent connections).
- Credential passing: The
$using:prefix is critical for accessing workflow parameters insideInlineScriptand parallel blocks.
内容的提问来源于stack exchange,提问作者Paul Murith

