Invoke-SQLCmd具有不同的凭据

时间:2011-08-22 22:00:13

标签: sql-server powershell

背景: 我在本地运行一个必须以SYSTEM身份运行的脚本,让我们不了解为什么会这样。 :) 该脚本尝试使用简单查询检查MSSQL群集的运行状况。然而,我遇到的问题是本地SYSTEM帐户无权访问远程数据库。在这一点上,我已经尝试了很多东西,我将在稍后介绍,但我老实说,任何有意义的解决方案。如果这意味着在数据库中创建一个本地帐户,可以回答我的简单查询,那也很好。

到目前为止我有:

$Server = 'myserver.domain.tld'
$Database = 'myDatabase'
$Query = 'SELECT DB_NAME() AS DataBaseName'
$Username = 'myDomain\myUsername'
$Password = 'myPasswordWithPlainText'
Invoke-SQLCmd -ServerInstance $Server -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query -Username $Username -Password $Password

结果:Invoke-Sqlcmd : Login failed for user 'myDomain\myUsername'

也许Invoke-SQL没有采用我认为的Windows身份验证,但它不使用-Credential。所以我尝试使用Invoke-Command作为包装器。

$Server = 'myserver.domain.tld'
$Database = 'myDatabase'
$Query = 'SELECT DB_NAME() AS DataBaseName'
$Username = 'myDomain\myUsername'
$Password = 'myPasswordWithPlainText'
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd)
Invoke-Command -script {Invoke-SQLCmd -ServerInstance $Server -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query} -Credential $Credential

让我:Invoke-Command : Parameter set cannot be resolved using the specified named parameters.

所以......我被困住了。有什么想法吗?

6 个答案:

答案 0 :(得分:7)

我使用Get-Credential然后使用Invoke-Command -AsJob从.sql文件运行脚本。 e.g。

$s = 'myserver.domain.tld';
$scriptpath = 'C:\myfile.sql';
$cred = Get-Credential -credential domain\user;
$sess = New-PSSession -ComputerName $s -Credential $cred -Authentication CredSSP -Name 'S1';
$job1 = Invoke-Command -Session $sess -FilePath $scriptpath -AsJob -JobName 'J1';
  # -ArgumentList $args;

Get-Job | Wait-Job;
Get-Job -Name 'J1';

Get-PSSession | Remove-Session;
Get-Job | Remove-Job;

但请注意,$ cred行将启动确认/验证凭证的提示 - 我在脚本中也有数据库名称,因此我不确定如何更改此逻辑以将脚本指向任何数据库(如果需要为每台服务器定制)。

答案 1 :(得分:1)

对于这种事情我们在RUNAS /NETONLY

取得了很大的成功

不确定Powershell是否具有相同的功能(可能只是使用RUNAS / NETONLY运行Powershell)。如果您要将其构建到应用程序中,我们会使用Windows API重新启动:How to build RUNAS /NETONLY functionality into a (C#/.NET/WinForms) program?

另外:http://www.theinfraguy.com/2011/08/three-uses-for-runas-netonly.html

答案 2 :(得分:1)

您可以尝试提交作业并传递凭据。

#Submit the job with creds
$job = Start-Job {importsystemmodules; Invoke-Sqlcmd -Query 'select @@version'  -ServerInstance LOCALHOST} -Credential $creds | Get-Job | Wait-Job

#Receive the job
$jobInfo = Receive-Job -Job $job

这对我有用。

答案 3 :(得分:0)

如果您尚未检查用户是否有权访问数据库: - )

如果他这样做你可以支持解决问题并使用.net对象 - 不是很简洁,可能有其他问题,但可以使用连接字符串。

这是未经测试的: - )

$ConnectionString = "Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;"
$connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString);
$command = New-Object System.Data.SqlClient.SqlCommand;

$command.Connection = $connection;
$command.CommandType = [System.Data.CommandType]::Text;
$command.CommandText = "SELECT DB_NAME() AS DataBaseName";

$connection.open();

$reader = $command.ExecuteReader()

While($reader.Read()){
    # do something with $reader
}

$connection.Close()
$reader.Close()

答案 4 :(得分:0)

可悲的是,我尝试了所有这些(包括Matt的建议),然后是一些,我只是不能让它在以下参数下工作。 1)该脚本从作为SYSTEM帐户运行的服务启动。 2)系统位于与SQL群集不同的域/子网/等中。 3)查询必须实时运行并实时返回,因为查询只是更大脚本的一部分。

现在,我已经抛弃并创建了一个本地SQL登录名,然后使用Invoke-SQL和-username和-password选项。这不是我想要处理的情况,但它是什么。谢谢大家!

答案 5 :(得分:0)

无需远程登录即可运行SQL查询。您可以使用以下函数并根据需要传递变量。无论哪个帐户有权访问,您都可以作为凭据传递。 (适用于Windows和SQL身份验证)

        $SQLInstance = "Instance Name"
        $Database = "Database"
        $ID = "User ID" 
        $Password = "Password"



     function Invoke-Sqlcommand 
        { 
            [CmdletBinding()] 
            param( 
            [Parameter(Position=0, Mandatory=$true)] [string]$ServerInstance, 
            [Parameter(Position=1, Mandatory=$false)] [string]$Database, 
            [Parameter(Position=2, Mandatory=$false)] [string]$Query, 
            [Parameter(Position=3, Mandatory=$false)] [string]$Username, 
            [Parameter(Position=4, Mandatory=$false)] [string]$Password, 
            [Parameter(Position=5, Mandatory=$false)] [Int32]$QueryTimeout=600, 
            [Parameter(Position=6, Mandatory=$false)] [Int32]$ConnectionTimeout=15, 
            [Parameter(Position=7, Mandatory=$false)] [ValidateScript({test-path $_})] [string]$InputFile, 
            [Parameter(Position=8, Mandatory=$false)] [ValidateSet("DataSet", "DataTable", "DataRow")] [string]$As="DataRow" 
            ) 

            if ($InputFile) 
            { 
                $filePath = $(resolve-path $InputFile).path 
                $Query =  [System.IO.File]::ReadAllText("$filePath") 
            } 

            $conn=new-object System.Data.SqlClient.SQLConnection 

            if ($Username) 
            { $ConnectionString = "Server={0};Database={1};User ID={2};Password={3};Trusted_Connection=False;Connect Timeout={4}" -f $ServerInstance,$Database,$Username,$Password,$ConnectionTimeout } 
            else 
            { $ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerInstance,$Database,$ConnectionTimeout } 

            $conn.ConnectionString=$ConnectionString 

            #Following EventHandler is used for PRINT and RAISERROR T-SQL statements. Executed when -Verbose parameter specified by caller 
            if ($PSBoundParameters.Verbose) 
            { 
                $conn.FireInfoMessageEventOnUserErrors=$true 
                $handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {Write-Verbose "$($_)"} 
                $conn.add_InfoMessage($handler) 
            } 

            $conn.Open() 
            $cmd=new-object system.Data.SqlClient.SqlCommand($Query,$conn) 
            $cmd.CommandTimeout=$QueryTimeout 
            $ds=New-Object system.Data.DataSet 
            $da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd) 
            [void]$da.fill($ds) 
            $conn.Close() 
            switch ($As) 
            { 
                'DataSet'   { Write-Output ($ds) } 
                'DataTable' { Write-Output ($ds.Tables) } 
                'DataRow'   { Write-Output ($ds.Tables[0]) } 
            } 

        } 

Invoke-Sqlcommand -ServerInstance $SQLInstance -Database $Database -Query "Query Goes here" -Username $ID -Password $Password

希望它能够发挥作用。