2

以下に概説する方法を使用してローカル データベースを呼び出す際に問題が発生します。

エラーメッセージ

invoke-sqlcmd : 値を null にすることはできません。パラメータ名: 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

ゴール

server.txt (構成ファイル) にリストされている SQL インスタンスに対して、PowerShell 経由でクエリを実行しようとしています。


2 つのコンポーネント-

  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
}
#===============================================================================

ここで、インポートされた変数をフォーマットし、function= の実行中にそれらをループすることで、魔法を実現します。

#===============================================================================
#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) が表示されます。

明らかに何かが欠けています...スタックとGoogleを1日検索しましたが、何も見つかりませんでした。うまくいけば、PowerShell について見落としているか、まだ理解していない小さなことです。

助けてくれてありがとう!

4

1 に答える 1

1

パラメータを参照$ServerNameしてい-ServerInstanceます。文字列が必要で、文字列の配列を提示しています。また、ForEach最後の 2 回はループを間違って使用しています。の自動変数ではなく、変数名である必要があります$_。例:

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 に答える