2

我在使用下面概述的方法调用本地数据库时遇到问题。

错误信息

invoke-sqlcmd :值不能为空。参数名称:ServerInstance At C:\filelocation\HealthCheckCombined.ps1:86 char:3 1.invoke-sqlcmd -query $agentquery -serverinstance $servername ... 2.~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument:(:) [Invoke-Sqlcmd],ArgumentNullException + FullyQualifiedErrorId:CannotGetServerInstance,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand


环境

  • 服务器 2016 候选人 3
  • 服务器 2012
  • SQL Server 2014
  • SQL Server 2012
  • PowerShell 3.0、4.0 和 5.0

目标

我正在尝试通过 PowerShell 对 servers.txt(配置文件)中列出的任何 SQL 实例运行查询。


两个组件-

  1. 外部配置文件 (servers.txt)
  2. 包含函数的 PowerShell 脚本,循环以从 servers.txt 创建一个数组并执行该函数。

所以servers.txt的内容看起来像=

server=test2k16\powershell
server=test2k16\healthcheck

这是我导入文本文件并创建函数的部分=

#===============================================================================
#Configurable variables
#===============================================================================
$configfile = 'C:\filelocation\servers.txt'
Import-Module "sqlps"
#===============================================================================

#===============================================================================
#SQL Agent Jobs
#===============================================================================
function SQLAgent{
$agentquery= @"
    declare @count int
    select @count = count(1) from msdb.dbo.sysjobs as sj
    join msdb.dbo.sysjobhistory as sjh on sj.job_id = sjh.job_id
    where sj.enabled != 0
    and sjh.sql_message_id > 0
    and sjh.run_date > CONVERT(char(8), (select dateadd (day,(-30), getdate())), 112)
    and sjh.Step_id <= 1

    if (@count >= 1)
        begin
            select distinct sj.name as SQLJobName
            from msdb.dbo.sysjobs as sj
            join msdb.dbo.sysjobhistory as sjh on sj.job_id = sjh.job_id
            where sj.enabled != 0
            and sjh.sql_message_id > 0
            and sjh.run_date > CONVERT(char(8), (select dateadd (day,(-30), getdate())), 112)
            and sjh.Step_id <= 1
        order by name
    end

        else
        begin
            Select 'No Job Failed in Last Month' as SQLJobName
        end
"@

        invoke-sqlcmd -query $agentquery -serverinstance $servername -username "user" -password "password" | Format-Table -AutoSize -Wrap
}
#===============================================================================

现在我通过格式化导入的变量并在运行函数时循环它们来实现魔法=

#===============================================================================
#Run Health Check for each server
#===============================================================================
$import = $(foreach ($line in get-content $configfile) {$line.tolower().split(" ")}) | sort | get-unique
ForEach ($_ in $import){
    $servername = $import.trimstart("server=")
}
ForEach ($_ in $servername){
    SQLAgent
}
#===============================================================================

迄今为止的发现

  • 在函数中提取代码并导入文本文件可以正常工作。没有错误。
  • 如果我将脚本更改为仅在循环中显示这些变量,则循环中的 $servername 变量会显示正确的值(test2k16\powershell & test2k16\healthcheck)

我显然错过了一些东西......我已经搜索堆栈和谷歌一天了,但什么也没找到。希望这是我忽略或还不了解 PowerShell 的一些小问题。

提前感谢您的帮助!

4

1 回答 1

1

您正在引用参数$ServerName-ServerInstance它需要一个字符串,而您正在向它展示一个字符串数组。此外,您ForEach最近两次错误地使用了循环。它应该是一个变量名,而不是$_. 例子:

ForEach($Server in $ServerName){
    SQLAgent
}

然后将您-ServerInstance的函数更改为 reference $Server。更好的是,为您的函数设置参数并在循环中为其提供所需的信息。

Function SQLAgent($Server){
    <Code goes here!>
    invoke-sqlcmd -query $agentquery -serverinstance $server -username "user" -password "password" | Format-Table -AutoSize -Wrap
}
$ServerList = Get-Content $configfile | ForEach{$_.Split('=')[1]}
ForEach($Item in $ServerList){
    SQLAgent -Server $Item
}
于 2015-10-02T20:34:38.607 回答