SQL Serverと対話する必要があるPowershellスクリプトを作成しようとしているため、スクリプトの一部にinvoke-sqlcmdが含まれます。ただし、スクリプトをSQL Serverのジョブとしてスケジュールすることはできないため、認証に使用されるWindowsアカウントとして機能するエージェントを利用します。代わりに、任意のWindowsアカウントで別のサービスを使用して実行されます。 invoke-sqlcmdのドキュメントには、-Usernameおよび-PasswordパラメーターはWindowsではなくSQL Server認証用であり、SQL Serverパラメーターが指定されていない場合、認証用のスクリプトを実行しているWindowsアカウントをデフォルトで使用することが記載されています。
Invoke-sqlcmdが認証に使用されているアカウントではなく、認証に任意のWindowsアカウントを使用できるようにする方法はありますか?可能な解決策は、スクリプトを実行するSQL Serverインスタンスにアカウントを作成し、コマンドでSQL Server認証オプションを使用することですが、理想的にはそうする必要はありません。他のいくつかの調査でも、証明書は追跡可能なオプションである可能性があることが示されていますが、invoke-sqlcmdが証明書を取得したり、提案された方法で証明書を利用したりできるとは思いません。私はここで間違っているかもしれません。
ジョブを実行するアカウントに、クエリを実行するために必要なSQL Serverへのアクセス許可を付与できます。それが一番簡単でしょう。タスクスケジューラを使用する場合は、使用するアカウントを指定する方法も用意されています。
次善の策は、SQL認証を使用することです。
最後に、PowerShellを使用して新しいスレッドを呼び出し、別のWindowsアカウントで実行し、そのスレッドでInvoke-sqlを使用できます。ただし、パスワードは何らかの方法で保存する必要があります(通常はファイルで暗号化されます)。これは最善の解決策ではなく、私が使用することをお勧めするものでもありません。
別の方法として、Invoke-Sqlcmd
を使用するライブラリ用にStart-Job
のラッパーを作成しました。
function Invoke-InternalSqlcmd {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)][string] $Query,
[Parameter(Mandatory=$true)][string] $Database,
[Parameter(Mandatory=$false)][System.Management.Automation.PSCredential] $Credential
)
if (-not $Credential) {
return Invoke-SqlCmd -Query $Query -Database $Database
}
else {
$ScriptBlock = {
param($Query,$Database)
$ErrorActionPreference = 'Stop';
return @{ Result = Invoke-SqlCmd -Query $Query -Database $Database }
}
$Job = Start-Job -Credential $Credential -ScriptBlock $ScriptBlock -ArgumentList $Query,$Database
$JobResult = Wait-Job $Job;
if ($JobResult.State -eq 'Completed') {
return (Receive-Job $Job).Result
}
throw [Exception]::new("Error occurred while executing sql as $($Credential.UserName) $([System.Environment]::NewLine)$($JobResult.ChildJobs[0].JobStateInfo.Reason)", $JobResult.ChildJobs[0].JobStateInfo.Reason)
}
}
長所
Invoke-Sqlcmd
が返す正確な結果を返します短所
ErrorActionPreference
を尊重せず、常にエラーが発生します。必要に応じて修正できます。WinRMにアクセスできないロックダウン環境で実行しています。タスクが長時間実行されているため、これは私のニーズに適しています。より良いパフォーマンスが必要な場合は、WinRMを使用して問題がなければ、ジョブコードをRunspaces
に簡単に置き換えることができます。