我试图获取远程服务器硬件规格,并希望将它们插入到也位于远程服务器上的SQL Server表中。我收到以下错误。
Invoke-SQLcmd:'@'附近的语法不正确。 Msg 102,Level 15,State 1,Procedure,Line 5。
码:
$ServerName = "SQLSRV"
$DatabaseName = "Automation"
$conn=New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Server = $SQLServer; Database = $SQLDBName;
User ID= automationusr; Password= Password@SQL"
$conn.ConnectionString=$ConnectionString
$conn.Open()
$ServerListFile = "C:\Scripts\ServerList.txt"
$ServerList = Get-Content $ServerListFile -ErrorAction SilentlyContinue
$Result = @()
ForEach($computername in $ServerList)
{
$AVGProc = Get-WmiObject -computername $computername win32_processor |
Measure-Object -property LoadPercentage -Average | Select Average
$OS = gwmi -Class win32_operatingsystem -computername $computername |
Select-Object @{Name = "MemoryUsage"; Expression = {“{0:N2}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize) }}
$vol = Get-WmiObject -Class win32_Volume -ComputerName $computername -Filter "DriveLetter = 'C:'" |
Select-object @{Name = "C PercentFree"; Expression = {“{0:N2}” -f (($_.FreeSpace / $_.Capacity)*100) } }
$result += [PSCustomObject] @{
ServerName = "'$computername'"
CPULoad = "'$($AVGProc.Average)%'"
MemLoad = "'$($OS.MemoryUsage)%'"
CDrive = "'$($vol.'C PercentFree')%'"
QDate = "'$(Get-Date -Format "yyyyMMdd")'"
}
Foreach($Entry in $Result)
{
$QDate=$TESTTB01.Date
$ServerName=$TESTTB01.SName
$CPULoad=$TESTTB01.ACPU
$MemLoad=$TESTTB01.MEMU
$CDrive=$TESTTB01.DRVC
$insertquery="
INSERT INTO [dbo].[TESTTB01]
(Date,SName,ACPU,MEMU,DRVC)
VALUES
('['$ENTRY.QDate']','['$ENTRY.ServerName']','['$Entry.CPULoad']','['$Entry.MemLoad']','['$Entry.CDrive']')
GO
"
Invoke-SQLcmd -ServerInstance 'SQLSRV' -query $insertquery -U automationusr -P Password@SQL -Database Automation
}
}
我想创建一个任务,可以执行代码获取远程服务器的配置,并在每15分钟后在SQL Server表中插入变量
"..."
)中,您不能直接嵌入属性访问表达式,如$ENTRY.QDate
;相反,你必须将它们包含在$(...)
中:
有关PowerShell字符串扩展规则的概述,请参阅this answer。
如果没有封闭的$(...)
,$ENTRY
将整体字符串化,在[pscustomobject]
实例的情况下会导致类似哈希表的字符串表示形式以@
开头,这就是破坏了您的查询。'['...']'
不是引用字符串文字的正确方法。因此:
$insertquery="
INSERT INTO [dbo].[TESTTB01]
(Date,SName,ACPU,MEMU,DRVC)
VALUES
($($ENTRY.QDate), $($ENTRY.ServerName), $($Entry.CPULoad), $($Entry.MemLoad),$($Entry.CDrive))
GO
退一步:考虑听取Larnu的建议来参数化你的查询,而不是将值作为文字嵌入查询字符串中。
最终的代码是
$ServerName = "SQLSRV"
$DatabaseName = "Automation"
$conn=New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Server = $SQLServer; Database = $SQLDBName;
User ID= automationusr; Password= Password@SQL"
$conn.ConnectionString=$ConnectionString
$conn.Open()
$ServerListFile = "C:\Scripts\ServerList.txt"
$ServerList = Get-Content $ServerListFile -ErrorAction SilentlyContinue
$Result = @()
ForEach($computername in $ServerList)
{
$AVGProc = Get-WmiObject -computername $computername win32_processor |
Measure-Object -property LoadPercentage -Average | Select Average
$OS = gwmi -Class win32_operatingsystem -computername $computername |
Select-Object @{Name = "MemoryUsage"; Expression = {“{0:N2}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize) }}
$vol = Get-WmiObject -Class win32_Volume -ComputerName $computername -Filter "DriveLetter = 'C:'" |
Select-object @{Name = "C PercentFree"; Expression = {“{0:N2}” -f (($_.FreeSpace / $_.Capacity)*100) } }
$result += [PSCustomObject] @{
ServerName = "'$computername'"
CPULoad = "'$($AVGProc.Average)%'"
MemLoad = "'$($OS.MemoryUsage)%'"
CDrive = "'$($vol.'C PercentFree')%'"
QDate = "'$(Get-Date -Format "yyyyMMdd hh:MM:ss tt")'"
}
Foreach($Entry in $Result)
{
$QDate=$TESTTB01.Date
$ServerName=$TESTTB01.SName
$CPULoad=$TESTTB01.ACPU
$MemLoad=$TESTTB01.MEMU
$CDrive=$TESTTB01.DRVC
}
$insertquery="
INSERT INTO [dbo].[TESTTB01]
(Date,SName,ACPU,MEMU,DRVC)
VALUES
($($ENTRY.QDate), $($ENTRY.ServerName), $($Entry.CPULoad), $($Entry.MemLoad),$($Entry.CDrive))
GO
"
Invoke-SQLcmd -ServerInstance 'SQL01' -query $insertquery -U automationusr -P Password@SQL -Database Automation
}