Powershell invoke sqlcmd:值不能为null。参数名称:ServerInstance

Powershell invoke sqlcmd:值不能为null。参数名称:ServerInstance,powershell,sqlps,Powershell,Sqlps,我在使用下面概述的方法调用本地数据库时遇到问题 错误消息 调用sqlcmd:值不能为null。 参数名称:ServerInstance 在C:\filelocation\HealthCheckCombined.ps1:86 char:3 1.调用sqlcmd-query$agentquery-serverinstance$servername。。。 2. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +

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

错误消息

调用sqlcmd:值不能为null。 参数名称:ServerInstance 在C:\filelocation\HealthCheckCombined.ps1:86 char:3 1.调用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实例运行查询


两个组件-

  • 外部配置文件(servers.txt)
  • 包含函数的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)
    我显然错过了一些东西。。。我已经在stack和Google上搜索了一天,但什么也没找到。希望这是我对PowerShell所忽略或不了解的一些小问题


    提前感谢您的帮助

    您正在为
    -ServerInstance
    参数引用
    $ServerName
    。它需要一个字符串,而您正在用一个字符串数组来表示它。另外,您在过去两次中错误地使用了
    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
    }
    
    函数SQLAgent($Server){
    <代码在这里!>
    调用sqlcmd-query$agentquery-serverinstance$server-username“user”-password“password”| Format Table-AutoSize-Wrap
    }
    $ServerList=Get Content$configfile | ForEach{$\.Split('=')[1]}
    ForEach($ServerList中的项){
    SQLAgent-Server$Item
    }
    
    工作得很好,你刚刚挽救了这一天。我当时真的很难将我的思想集中在这个概念上,并且认为它是在循环中的-谢谢!