PowerShell操作SharePoint Online列表:无法更新已有列表项
问题背景
需要完成Hyper-V虚拟机列表到SharePoint Online列表的同步,要求:
- 不存在的VM项自动创建
- 已存在的VM项更新状态
当前已实现列表创建、列配置和新增项,但更新逻辑错误,导致所有列表项被覆盖为同一VM信息,临时用删除重建的方式替代,需要正确的增量同步逻辑。
修正后的完整脚本
#Config Variables $vmhost = "<serverhostname>" $ListName = $vmhost $folderpath = "C:\scheduled tasks\hyperv-host-vm-collation-scheduled-task" # 导出Hyper-V VM列表到CSV $output = "$folderpath\$vmhost.csv" Get-VM -ComputerName $vmhost | Select-Object Name,State | Export-Csv -Path $output -NoTypeInformation $vms = Import-Csv $output $SiteURL = "<SharePointOnlineURL>" #Setup Credentials - 后续可替换为REST API获取的凭据 $UserName = "" $Password = '' $SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force $Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword #Connect to PnP Online Connect-PnPOnline -Url $SiteURL -Credentials $Cred # 检查列表是否存在,不存在则创建并配置列 $List = Get-PnPList -Identity $ListName -ErrorAction SilentlyContinue If($List -ne $Null) { Write-Host -ForegroundColor Yellow "列表已存在,开始同步VM信息" } Else { Write-Host -ForegroundColor Green "列表不存在,创建新列表" # 创建列表 $List = New-PnPList -Title $ListName -Template GenericList -EnableVersioning # 添加State文本列 Add-PnPField -List $ListName -Type Text -DisplayName State -InternalName State -AddToDefaultView -ErrorAction Stop # 将默认Title列重命名为Name Set-PnPField -List $ListName -Identity Title -Values @{Title="Name"} -ErrorAction Stop } # -------------------------- 核心同步逻辑 -------------------------- # 获取SharePoint列表中已有的VM项,存储为哈希表:Key=VM名称,Value=列表项ID $existingVMs = @{} Get-PnPListItem -List $ListName -Fields "Title", "Id" | ForEach-Object { $existingVMs[$_.FieldValues.Title] = $_.Id } # 遍历每个VM,执行新增或更新 foreach($vm in $vms){ $vmName = $vm.Name.Trim() $vmState = $vm.State.Trim() if($existingVMs.ContainsKey($vmName)){ # VM已存在,更新状态 Write-Host -ForegroundColor Cyan "更新VM: $vmName" Set-PnPListItem -List $ListName -Identity $existingVMs[$vmName] -Values @{ "Title" = $vmName "State" = $vmState } # 从哈希表中移除已处理的项,剩余的就是SharePoint中存在但Hyper-V已删除的VM $existingVMs.Remove($vmName) } else{ # VM不存在,新增项 Write-Host -ForegroundColor Green "新增VM: $vmName" Add-PnPListItem -List $ListName -Values @{ "Title" = $vmName "State" = $vmState } } } # 可选:删除SharePoint中存在但Hyper-V已不存在的VM项 if($existingVMs.Count -gt 0){ Write-Host -ForegroundColor Red "清理已删除的VM项:$($existingVMs.Keys -join ', ')" foreach($deletedVM in $existingVMs.Keys){ Remove-PnPListItem -List $ListName -Identity $existingVMs[$deletedVM] -Force } } # 断开连接 Disconnect-PnPOnline
关键逻辑说明
- 哈希表存储已有VM:通过
Get-PnPListItem获取列表中所有VM的名称和ID,存入哈希表$existingVMs,实现通过VM名称快速查找对应列表项ID,避免嵌套循环导致的重复更新问题。 - 增量同步逻辑:
- 遍历CSV中的每个VM,检查哈希表中是否存在该名称:存在则调用
Set-PnPListItem更新状态;不存在则调用Add-PnPListItem新增。 - 处理完成的VM从哈希表中移除,剩余的键即为SharePoint中存在但Hyper-V已删除的VM,可选择清理。
- 遍历CSV中的每个VM,检查哈希表中是否存在该名称:存在则调用
- 避免重复操作:移除原脚本的嵌套循环,每个VM仅处理一次,解决了所有列表项被覆盖为同一VM信息的问题。
内容的提问来源于stack exchange,提问作者Zippyduda
相关产品推荐
相关产品推荐

