PowerShell脚本报Cannot index into a null array错误及变量清理疑问
问题解决:PowerShell脚本空数组索引错误及变量清理优化
错误原因
报错核心是:当用户目录为空时,Get-ChildItem $user.FullName返回空值,$LastAccessTime变量变为null,直接通过$LastAccessTime[0]索引数组元素就会触发"Cannot index into a null array"错误。同时脚本中Clear-Variable的位置不合理,清理了循环外定义的变量,属于无效操作。
修复后的完整脚本
# =========================== Log Template ============================== $LogPath = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs' $LogName = $LogPath + "\Set-TeamsFirewallRule.log" If ((Test-Path $LogPath) -eq $false) { New-Item -Path 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs' -ItemType Directory } # =========================== Log Template ============================== Start-Transcript -Path $LogName -Force #Get all the user profiles that are on the system $users = Get-ChildItem (Join-Path -Path $env:SystemDrive -ChildPath 'Users') -Exclude 'Public', 'Administrator','Help*','svc*','defaultuser*' -ErrorAction SilentlyContinue #Generate a date code for accounts that have had activity in the last 40 days $StaleAccountDate = (Get-Date).AddDays(-40) if ($null -ne $users) { #Check for any firewall rules that block Teams access and disable them Write-Output "Checking for firewall rules that block Teams Access" $TeamsBlock = Get-NetFirewallRule -Name *Teams* | Where-Object {($_.action -eq "Block") -and ($_.Enabled -eq 'True')} If ($null -ne $TeamsBlock) { Foreach ($Rule in $TeamsBlock) { Write-Output "Disabling blocking firewall rule $($Rule.DisplayName)" Set-NetFirewallRule $Rule.Name -Enabled False } } foreach ($user in $users) { #Check the last time something was written to the file path for the user we are checking $LastAccessTime = Get-ChildItem $user.FullName -ErrorAction SilentlyContinue | Sort-Object lastwritetime -Descending # 先判断数组是否为空,避免索引错误 if ($null -eq $LastAccessTime -or $LastAccessTime.Count -eq 0) { Write-Output "Skipping $($user.Name) because no files found in user directory" continue } # 使用if-else替代两个独立if,逻辑更严谨 If ($LastAccessTime[0].LastWriteTime -le $StaleAccountDate) { Write-Output "Skipping $($user.Name) because the last access time on the account is too old" } Else { Write-Output "Checking $($user.FullName)" #Generate the path that will be checked $progPath = Join-Path -Path $user.FullName -ChildPath "AppData\Local\Microsoft\Teams\Current\Teams.exe" if (Test-Path $progPath) { #Check that the firewall rule already exists, if it does skip, if not, add it $RuleCheck = Get-NetFirewallApplicationFilter -Program $progPath -ErrorAction SilentlyContinue if ($Null -eq $RuleCheck) { Write-Output "Creating new firewall rules for $($user.Name)" $ruleName = "Teams.exe for user $($user.Name)" #Here we add some things into the actual Rule name so that it is friendly and easily searchable. We also want the rule name and display name to match. "UDP", "TCP" | ForEach-Object { New-NetFirewallRule -Name ($RuleName + " " + $_.ToString()) -DisplayName ($RuleName + " " + $_.ToString()) -Direction Inbound -Profile Any -Program $progPath -Action Allow -Protocol $_ } } Else { Write-Output "Looks like there are already rules in place for $($user.Name) so we will not add any" } } Else { Write-Output "Looks like $($user.Name) has not launched Teams, we will be skipping" } } # 只清理当前循环内定义的变量,避免影响外部变量 Clear-Variable RuleCheck, progPath, LastAccessTime -ErrorAction SilentlyContinue } } # =========================== Log Template ============================== Stop-Transcript # =========================== Log Template ==============================
关键修复点
- 空数组判断:在访问
$LastAccessTime[0]前,先检查变量是否为空或数组元素数量为0,避免索引错误 - 逻辑优化:将两个独立的
if判断改为if-else,避免重复执行判断逻辑,覆盖所有分支情况 - 变量清理调整:仅清理循环内部定义的变量,移除对循环外变量
TeamsBlock的无效清理 - 权限容错:给
Get-ChildItem添加-ErrorAction SilentlyContinue,避免因权限不足无法读取用户目录导致脚本中断
内容的提问来源于stack exchange,提问作者Admaine
相关产品推荐
相关产品推荐

