如何在没有索引的情况下使用 PowerShell 访问 JSON 文件中的数组对象
How to use PowerShell to access array object within JSON file without an index
高级概念
此 PowerShell 脚本将在众多 SQL 服务器之间共享。如果服务器的名称在 JSON 文件中,它将 运行 类似于 Set-Service -Name SQLEngine_InstanceA -StartType Manual
使用 JSON 文件中的 SQL 服务名称并更改其启动类型为“禁用”、“按需”、“手动”或“自动”。然后它将启动 JSON 文件中列出的那些服务。
目标
特定格式的JSON文件,脚本需要根据JSON文件中指定的参数进行操作。该脚本将检查 JSON 文件中是否存在执行服务器的名称,然后根据 JSON 文件参数更新服务启动类型。它还会检查 JSON 文件中的每个参数,以确定是否应该对其采取行动。
我需要完成的基础知识:
- 服务器 运行定期(每 15 分钟)执行此 PowerShell 脚本,以了解 SQL 服务是否会在 window 内停止维护。
- 针对 JSON 文件
StartServices.json
编写 运行 脚本,其中包含:
- 服务器名称
- 开始时间
- 服务
- 服务名称
- 订单
- 启动模式
- 如果 ServerName 与
$env:COMPUTERNAME
和 startAt >= $Current_Time
匹配,它将继续下一步。
- 它应该遍历匹配计算机名称的每个服务,特别是在指定的“顺序”中,运行
Start-Service -Name $ServiceName -StartType $StartMode
。顺序很重要,因为我们需要 starting/stopping 某些服务优先于其他服务。
我卡在了第 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
}
高级概念
此 PowerShell 脚本将在众多 SQL 服务器之间共享。如果服务器的名称在 JSON 文件中,它将 运行 类似于 Set-Service -Name SQLEngine_InstanceA -StartType Manual
使用 JSON 文件中的 SQL 服务名称并更改其启动类型为“禁用”、“按需”、“手动”或“自动”。然后它将启动 JSON 文件中列出的那些服务。
目标
特定格式的JSON文件,脚本需要根据JSON文件中指定的参数进行操作。该脚本将检查 JSON 文件中是否存在执行服务器的名称,然后根据 JSON 文件参数更新服务启动类型。它还会检查 JSON 文件中的每个参数,以确定是否应该对其采取行动。
我需要完成的基础知识:
- 服务器 运行定期(每 15 分钟)执行此 PowerShell 脚本,以了解 SQL 服务是否会在 window 内停止维护。
- 针对 JSON 文件
StartServices.json
编写 运行 脚本,其中包含:- 服务器名称
- 开始时间
- 服务
- 服务名称
- 订单
- 启动模式
- 如果 ServerName 与
$env:COMPUTERNAME
和startAt >= $Current_Time
匹配,它将继续下一步。 - 它应该遍历匹配计算机名称的每个服务,特别是在指定的“顺序”中,运行
Start-Service -Name $ServiceName -StartType $StartMode
。顺序很重要,因为我们需要 starting/stopping 某些服务优先于其他服务。
我卡在了第 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
}