如何在PowerShell脚本中更新JSON键字段?解决字段未找到错误
问题分析与解决
错误根源
你的JSON结构中record是数组,每个元素是仅包含单个日期键(如20230214)的对象,但代码中直接通过$json.record.$date访问,这是错误的——数组没有名为日期值的属性,必须先遍历数组找到包含目标日期键的元素,这就是"字段未找到"错误的核心原因。
另外还有两个隐性问题:
- JSON示例用
total_active字段,但代码中用total_active_minutes,字段名不统一 - 时间差计算时如果
outTime早于inTime,会得到负数,不符合实际逻辑
修复后的完整代码
<# Set-UserStatus.ps1 **************************************************************** * ATTACH THIS SCRIPT TO USER LOGIN & LOGOUT * **************************************************************** #> <# Logon – 4624 (Security event log) -- 4634 Logoff – 4647 (Security event log) Startup – 6005 (System event log) RDP Session Reconnect – 4778 (Security event log) RDP Session Disconnect – 4779 (Security event log) Locked – 4800 (Security event log) Unlocked – 4801 (Security event log) #> function Add-to-JSON{ param ( [String] $date, [String] $name, [String] $compName, [String] $inTime, [String] $outTime ) Write-Output $date $name $compName $inTime $outTime $jsonfile = "E:\RK\Projects\Extras\tmp\"+$compName+"_"+$name+"_7.json" # 初始化或读取JSON if (!(Test-Path -Path $jsonfile -PathType Leaf)){ $json = [PSCustomObject]@{record = @()} } else{ $json = Get-Content -Path $jsonfile | Out-String | ConvertFrom-Json } # 处理时间差,确保结束时间不早于开始时间 $start = [DateTime]$inTime $end = [DateTime]$outTime if ($end -lt $start) { $temp = $start $start = $end $end = $temp } $time_diff = (New-TimeSpan -Start $start -End $end).TotalMinutes $alreadyAddedFlag = $false # 查找已有日期记录 $existingRecord = $json.record | Where-Object { $_ | Get-Member -Name $date -MemberType NoteProperty } if (-not $existingRecord){ # 新增日期记录 $new_session = @{ "sin_time"= $inTime; "sout_time"=$outTime; "message"=""; "active_time"= $time_diff } $today_dt = [PSCustomObject]@{ "in_time"=$inTime; "out_time"=$outTime; "total_active"= $time_diff ; "session"= @($new_session) } # 包装成带日期键的对象 $dateEntry = [PSCustomObject]@{$date = $today_dt} $json.record += $dateEntry } else{ # 获取日期对应的具体数据 $dateData = $existingRecord.$date if ($dateData.out_time -eq $outTime){ $alreadyAddedFlag = $true } else{ # 更新总时长和退出时间 $dateData.total_active = $dateData.total_active + $time_diff $dateData.out_time = $outTime # 新增会话 $new_session = @{ "sin_time"= $inTime; "sout_time"=$outTime; "message"=""; "active_time"= $time_diff } $dateData.session += $new_session } } Write-Output $json.record $alreadyAddedFlag if (!$alreadyAddedFlag){ $json | ConvertTo-Json -Depth 100 | Out-File $jsonfile -Encoding utf8 } } function Get-EntryExitTime{ $username, $computername, $date = Get-Details $startTime = "" $endTime = "" # 获取最晚的进入/解锁时间作为开始时间 $time1 = Get-Time -ComputerName $computername -Username $username -process "Login" $time2 = Get-Time -ComputerName $computername -Username $username -process "Unlock" $startTime = if ($time1 -ge $time2) { $time1 } else { $time2 } # 获取最晚的退出/锁定时间作为结束时间 $time1 = Get-Time -ComputerName $computername -Username $username -process "Logout" $time2 = Get-Time -ComputerName $computername -Username $username -process "Lock" $endTime = if ($time1 -ge $time2) { $time1 } else { $time2 } Add-to-JSON -date $date -name $username -compName $computername -inTime $startTime -outTime $endTime } function Get-Time{ param( [Parameter (Mandatory = $true)] [String]$ComputerName, [Parameter (Mandatory = $true)] [String]$Username, [Parameter (Mandatory = $true)] [ValidateSet("Login","Unlock","Lock","Logout")] [String]$process ) $cmds = @{Login=4624; Unlock=4801; Lock=4800; Logout=4647} $cmd = Get-EventLog -LogName Security -ComputerName $ComputerName -InstanceId $cmds[$process] -Message *$Username* -Newest 1 return $cmd.TimeGenerated } function Get-Details{ $username = $((Get-WMIObject -class Win32_ComputerSystem).username -split "\\")[1] $computername = $env:COMPUTERNAME $date = (Get-Date).ToString('yyyyMMdd') return $username, $computername, $date } Get-EntryExitTime
关键改动说明
- 日期记录查找逻辑:用
Where-Object结合Get-Member遍历record数组,找到包含目标日期键的元素,替代原代码中直接访问数组属性的错误方式 - 字段名统一:将代码中的
total_active_minutes、active_time_minutes改为与JSON示例一致的total_active、active_time - 时间差修正:先判断开始/结束时间的先后顺序,避免出现负的时长
- 数组类型处理:新增会话时确保
session始终是数组(原代码中第一次添加时是单个对象,后续添加会出错) - 编码规范:输出JSON时指定
-Encoding utf8,避免中文乱码问题
内容的提问来源于stack exchange,提问作者R.K
相关产品推荐
相关产品推荐

