json - 如何使用 PowerShell 在没有索引的情况下访问 JSON 文件中的数组对象

标签 json sql-server windows powershell service

高级概念

此 PowerShell 脚本将在多个 SQL 服务器之间共享。如果服务器的名称在 JSON 文件中,它将使用 JSON 文件中的 SQL 服务名称运行类似于 Set-Service -Name SQLEngine_InstanceA -StartType Manual 的操作,并将其启动类型更改为“已禁用” 、“按需”、“手动”或“自动”。然后它将启动 JSON 文件中列出的那些服务。

目标

特定格式的JSON文件,脚本需要根据JSON文件中指定的参数进行操作。该脚本将检查执行服务器的名称是否存在于 JSON 文件中,然后根据 JSON 文件参数更新服务启动类型。它还将检查 JSON 文件中的每个参数,以确定是否应该对其采取行动。

我需要完成的基础知识:

  1. 服务器定期(每 15 分钟)运行此 PowerShell 脚本,以了解 SQL 服务是否会在该窗口内关闭以进行维护。
  2. 脚本针对包含以下内容的 JSON 文件 StartServices.json 运行:
    • 服务器名
    • 起点
    • 服务
      • 服务名称
      • 订单
      • 开始模式
  3. 如果 ServerName 匹配 $env:COMPUTERNAME 并且 startAt >= $Current_Time 它将继续下一步。
  4. 它应该遍历与计算机名称匹配的每个服务,特别是在指定的“顺序”中,然后运行 ​​Start-Service -Name $ServiceName -StartType $StartMode。顺序很重要,因为我们需要先于其他服务启动/停止某些服务。

我卡在了第 4 步。这是我用来访问参数的脚本的简化示例。我无法清楚地引用服务部分,因为 PowerShell 在通过 ConvertFrom-JSON 摄取时会在该级别创建一个数组。数组的问题是我想避免对索引进行硬编码,因为可能只有 3 个服务或超过 5 个服务需要操作。

我想通过类似 $content.Server_Name["ServerABC"].Services 或类似的基于对象的方法访问这个元素。

示例 PowerShell 脚本

# Declare Variables
$InputFile = 'C:\temp\StartServices.json'
$ParsedRaw = Get-Content -Raw -Path $InputFile | ConvertFrom-Json
$vPSObject = $ParsedRaw
$serverName = $vPSObject.serverName
$services = $vPSObject.services #this just lists ALL service names, order, and startMode

# Check if JSON file exists
if (Test-Path -Path $InputFile -PathType Leaf) {
  Write-Host "JSON File Exists"

# Check if Server name is in list
  if ($serverName -contains $env:COMPUTERNAME) {
    $currentServerIndex = $serverName.IndexOf($env:COMPUTERNAME)
    Write-Host "The current index of $env:COMPUTERNAME is $currentServerIndex"
  
# Check if StartAt time in JSON is after the current time
    $DateTimeNow = Get-Date
    $DateTimeEvent = [DateTime]::ParseExact($vPSObject.startAt[$currentServerIndex], 'yyy-MM-dd HH:mm:ss', $null) # this format needed to match JSON time formatting
    if ($DateTimeEvent -gt $DateTimeNow.DateTime) {
      Write-Host "This will run since startAt is in the future"

# Area I'm stuck - Getting Service Start Mode & Status without using Indexes
    $StartTypeEngine = Get-Service -Name $vPSObject.serverName[$currentServerIndex].services.serviceName[0] | Select -Property starttype -ExpandProperty starttype
    $StartTypeBrowser = Get-Service -Name $vPSObject.serverName[$currentServerIndex].services.serviceName[1] | Select -Property starttype -ExpandProperty starttype
    $StartTypeAgent = Get-Service -Name $vPSObject.serverName[$currentServerIndex].services.serviceName[2] | Select -Property starttype -ExpandProperty starttype    

# If Variables are more dynamic the rest of the code would be as simple as:
    ForEach ($service in $services){
    Set-Service -Name $service.serviceName -StartType $service.StartupMode
    Start-Service -Name $service.serviceName 
    Write-Host "The service $service.serviceName has started and it's startup mode is set to $service.StartMode"
}
    }  

  }

}

示例 JSON

[
 {
  "serverName": "Main_SQL_Server",
  "startAt" : "2021-10-14 10:00:00",
  "services": [
    { 
    "serviceName": "MSSQL$Cluster",
    "order": 1,
    "startupMode": "manual"
    },
    {
    "serviceName": "MsDtsServer",
    "order": 2,
    "startupMode": "manual"
    },
    {
    "serviceName": "SQLBrowser$Cluster",
    "order": 3,
    "startupMode": "manual"
    },
    {
    "serviceName": "SQLAgent$Cluster",
    "order": 4,
    "startupMode": "automatic"
    }
  ]
 },
{
  "serverName": "Other_SQL_Server",
  "startAt" : "2021-10-14 11:00:00",
  "services": [
    { 
    "serviceName": "MSSQL$Backup",
    "order": 1,
    "startupMode": "manual"
    },
    {
    "serviceName": "MsDtsServer",
    "order": 2,
    "startupMode": "auto"
    },
    {
    "serviceName": "SQLBrowser$Backup",
    "order": 3,
    "startupMode": "auto"
    },
    {
    "serviceName": "SQLAgent$Backup",
    "order": 4,
    "startupMode": "manual"
    }
   ]
  }
]

最佳答案

这不难!因此,您为每台服务器提供了一系列服务,对吗?

{
  "serverName": "Main_SQL_Server",
  "startAt" : "2021-10-14 10:00:00",
  "services": [
    { 
    "serviceName": "MSSQL$Cluster",
    "order": 1,
    "startupMode": "manual"
    },
    {
    "serviceName": "MsDtsServer",
    "order": 2,
    "startupMode": "manual"
    },
    {
    "serviceName": "SQLBrowser$Cluster",
    "order": 3,
    "startupMode": "manual"
    },
    {
    "serviceName": "SQLAgent$Cluster",
    "order": 4,
    "startupMode": "automatic"
    }
  ]
 }

我们可以这样加载它:

$js = get-content c:\temp\stack.json

然后我们可以像这样只选择一个特定的服务器:

$server = $js | where serverName -eq Main_SQL_Server

然后您可以使用 foreach 循环遍历服务器。

forEach ($service in ($server.services | sort order)){
   Set-Service -Name $service.ServiceName -StartupType $service.StartupMode 
}

关于json - 如何使用 PowerShell 在没有索引的情况下访问 JSON 文件中的数组对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69273124/

相关文章:

java - 用 StringBuilder 附加一个逗号

javascript - 从 d3.js 中的 JSON 更新和弦图数据

sql - 在 SQL 中选择单行的最快方法是什么? (SQL 服务器)

javascript - 使用 JSON 对象创建表,为什么最后一行有两行 'td' 和第一个空行

sql - varchar 列上的标识键 - T-SQL

sql-server - SQL 中 VARCHAR 的 String.IsNullOrEmpty 类似函数?

windows - "Followup: MachineOwner"是什么意思?

windows - 在不同模块中 Access VBA Form Private Sub 调用 Public Function

c# - 桌面图标操作 - 当启用带有图片旋转的主题时如何获取 SysListView32 的句柄

json - 在为下游应用程序写入HDFS时,JSON与CSV文件格式的Mertis