添加 FileSystem::\\ 到文件路径从 SQL 导出空白 CSV
Adding FileSystem::\\ to file path exports a blank CSV from SQL
首先,这个脚本在我通过 Powershell 运行 时按原样工作。它与所有数据一起到达了目的地。
$adjustedDate = (Get-Date).AddDays(-1)
$dateString = Get-Date -Date $adjustedDate -UFormat "%m"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%d"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%y"
$query = "\Drive\Folder\Folder\Folder\Insurance Status.sql"
$instanceName = "SQL-SERVER"
$csvFilePath = "\Drive\Folder\Folder\Folder\Insurance Status "
$csvFilePath += $dateString
$csvFilePath += ".csv"
$results = Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
$results | Export-Csv $csvFilePath -NoTypeInformation
但是,当我 运行 它通过任务计划程序时,任务会成功完成,但导出文件从未到达映射驱动器文件夹中的目标位置。
为了让任务计划程序将 CSV 导出到映射的驱动器,我在我的路径名中添加了 "FileSystem:"。
$adjustedDate = (Get-Date).AddDays(-1)
$dateString = Get-Date -Date $adjustedDate -UFormat "%m"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%d"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%y"
$query = "FileSystem::\Drive\Folder\Folder\Folder\Insurance Status.sql"
$instanceName = "SQL-SERVER"
$csvFilePath = "FileSystem::\Drive\Folder\Folder\Folder\Insurance Status "
$csvFilePath += $dateString
$csvFilePath += ".csv"
$results = Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
$results | Export-Csv $csvFilePath -NoTypeInformation
现在,当我 运行 它通过调度程序时,CSV 使其进入映射的驱动器文件夹,但 CSV 是空白的。我错过了什么?
任务计划程序中 运行 脚本的上下文可以 change/have 影响使用 SQL 服务器模块 (sqlps/sqlserver)。您没有指定正在使用的模块,但两个模块中都存在 Invoke-Sqlcmd
。
在某些情况下,导入 sqlps 模块会将您的路径更改为 SQLSERVER 提供程序 (SQLSERVER:\
)。发生这种情况时,它会改变您访问本地文件系统的方式,它不再知道提供程序。这就是为什么它需要添加 FILESYSTEM::
以便它知道您希望与哪个提供商合作导出数据。
更新版本的 sqlserver
模块更改了提供程序的使用方式,因此它不再将 context/current 目录更改为 SQLSERVER:\ 提供程序。您可能会考虑使用该模块并将其显式导入您的脚本中。
我认为找到了问题的根源。
就您可以采取的措施而言,有多种选择:
- 加载SQL模块时提示符变为SQLSERVER:\驱动器;因此您可以在脚本的开头加载它,然后更改上下文。例如。以下。这可能就是您在调度程序中看到不同行为的原因;在您的交互式 PS 会话中您已经加载了模块,因此每次您 运行 脚本时它不会重新加载。在任务调度程序中,它每次 运行 都会获得一个新会话,因此每次都必须加载模块。
Import-Module SQLPS
Set-Location c:\ # or wherever; perhaps $PSScriptRoot if you're in a script; though that has no value if you're running code outside of a script file, so may be confusing if you're pasting code in the cmdline
- 或者您可以使用 pushd/popd 包围对模块的 cmdlet 的调用,以便在调用后重置当前路径
Push-Location c:\ # doesn't matter where, so long as it exists
Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
Pop-Location # moves you back to where you were before you called Push-Location
- 或者您可以使用不同的方法。我个人非常讨厌使用这个模块的不可预知的副作用,以至于我自己编写了代码:
<#
TOPIC
about_CCSqlServer
SHORT DESCRIPTION
Executes SQL code against an MS SQL database.
#>
function Invoke-CCSqlCommand {
[CmdletBinding(DefaultParameterSetName = 'ByQueryByConnection')]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnection')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnection')]
[System.Data.SqlClient.SqlConnection]$Connection
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnectionString')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnectionString')]
[string]$ConnectionString
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByProperties')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByProperties')]
[string]$DbInstance
,
[Parameter(Mandatory = $false, ParameterSetName = 'ByQueryByProperties')]
[Parameter(Mandatory = $false, ParameterSetName = 'ByPathByProperties')]
[string]$DbCatalog = 'master'
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnection')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnectionString')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByProperties')]
[string]$Query
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnection')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnectionString')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByProperties')]
[string]$Path
,
[Parameter(Mandatory = $false)]
[hashtable]$Params = @{}
,
[Parameter(Mandatory = $false)]
[int]$CommandTimeoutSeconds = 30
,
[Parameter(Mandatory = $false)]
[int]$ConnectionTimeoutSeconds = 15
,
[Parameter(Mandatory = $false, ParameterSetName = 'ByQueryByProperties')]
[Parameter(Mandatory = $false, ParameterSetName = 'ByPathByProperties')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential=[System.Management.Automation.PSCredential]::Empty
)
begin {
if (! $Connection) {
if ([System.String]::IsNullOrEmpty($ConnectionString)) {
$ConnectionString = New-CCSqlConnectionString -DbInstance $DbInstance -DbCatalog $DbCatalog -ConnectionTimeoutSeconds $ConnectionTimeoutSeconds -Credential $Credential -AsString
}
$Connection = New-CCSqlConnection -ConnectionString $ConnectionString
}
}
process {
[hashtable]$splat = @{
Connection = $Connection
Params = $Params
CommandTimeoutSeconds = $CommandTimeoutSeconds
}
[System.Data.SqlClient.SqlCommand]$cmd = if ($PSCmdlet.ParameterSetName -like 'ByQuery*') {
New-CCSqlCommand @splat -Query $Query
} else {
New-CCSqlCommand @splat -Path $Path
}
[System.Data.SqlClient.SqlDataReader]$reader = $cmd.ExecuteReader()
while (($reader) -and (-not ($reader.IsClosed))) { #improve: consider using as reader rather than data table for better memory consuption with large data sets...
[System.Data.DataTable]$table = new-object 'System.Data.DataTable'
$table.Load($reader)
#write-verbose "TableName: $($table.TableName)" #NB: table names aren't always available
$table | Select-Object -ExcludeProperty RowError, RowState, Table, ItemArray, HasErrors
}
}
end {
if ($PSCmdlet.ParameterSetName -notlike '*ByConnection') {
$connection.Close() #only close the connection if we own it; if it was passed to us, leave it open
}
}
}
function New-CCSqlCommand {
[CmdletBinding(DefaultParameterSetName = 'ByQuery')]
[OutputType('System.Data.SqlClient.SqlCommand')]
param (
[Parameter(Mandatory = $true)]
[System.Data.SqlClient.SqlConnection]$Connection # Since the standard use case for this will be within Invoke-CCSqlQuery, and that works best by reusing an existing connection, we're best off only providing the conneciton option (at least for now)
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQuery')]
[string]$Query
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByPath')]
[string]$Path
,
[Parameter(Mandatory = $false)]
[hashtable]$Params = @{}
,
[Parameter(Mandatory = $false)]
[int]$CommandTimeoutSeconds = 30 #30 is the default
)
$cmd = new-object -TypeName 'System.Data.SqlClient.SqlCommand'
$cmd.Connection = $connection
if ($PSBoundParameters.ContainsKey('CommandTimeoutSeconds')) {
$cmd.CommandTimeout = $CommandTimeoutSeconds #https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout(v=vs.110).aspx
}
#load in our query
switch ($PSCmdlet.ParameterSetName) {
'ByQuery' {$cmd.CommandText = $Query; break;}
'ByPath' {$cmd.CommandText = Get-Content -Path $Path -Raw; break;}
default {throw "ParameterSet $($PSCmdlet.ParameterSetName) not recognised by Invoke-SQLQuery"}
}
#assign parameters as required
#NB: these don't need declare statements in our query; so a query of 'select @demo myDemo' would be sufficient for us to pass in a parameter with name @demo and have it used
#we can also pass in parameters that don't exist; they're simply ignored (sometimes useful if writing generic code that has optional params)
$Params.Keys | ForEach-Object{$cmd.Parameters.AddWithValue("@$_", $Params[$_]) | out-null}
$cmd
}
function New-CCSqlConnection {
[OutputType('System.Data.SqlClient.SqlConnection')]
[CmdletBinding(DefaultParameterSetName = 'ByConnectionString')]
param (
[Parameter(ParameterSetName = 'ByConnectionString', Mandatory = $true)]
[string]$ConnectionString
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $true)]
[string]$DbInstance
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $false)]
[string]$DbCatalog = 'master'
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $false)]
[int]$ConnectionTimeoutSeconds = 15 #15 is the SQL default: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectiontimeout(v=vs.110).aspx
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $false)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
,
[Parameter(Mandatory = $false)]
[Switch]$SuppressAutoOpen
)
if ($PSCmdlet.ParameterSetName -eq 'ByProperties') {
$ConnectionString = New-CCSqlConnectionString -DbInstance $DbInstance -DbCatalog $DbCatalog -ConnectionTimeoutSeconds $ConnectionTimeoutSeconds -Credential $Credential -AsString
}
$connection = New-Object 'System.Data.SqlClient.SqlConnection'
$connection.ConnectionString = $connectionString
if (! $SuppressAutoOpen) {
$connection.Open()
}
$connection
}
function New-CCSqlConnectionString {
param (
[Parameter(Mandatory = $true)]
[string]$DbInstance
,
[Parameter(Mandatory = $false)]
[string]$DbCatalog = 'master'
,
[Parameter(Mandatory = $false)]
[int]$ConnectionTimeoutSeconds = 15 #15 is the SQL default: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectiontimeout(v=vs.110).aspx
,
[Parameter(Mandatory = $false)]
[System.Management.Automation.Credential()]
[System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty
,
[Parameter(Mandatory = $false)]
[Switch]$AsString
)
#Useful document on possible properties: https://www.connectionstrings.com/all-sql-server-connection-string-keywords/
$connectionString = ('Server={0};Database={1}' -f $DbInstance,$DbCatalog)
if ($Credential -eq [System.Management.Automation.PSCredential]::Empty) {
$connectionString = ('{0};Integrated Security=True' -f $connectionString)
} else {
$connectionString = ('{0};User Id={1};Password={2}' -f $connectionString, $Credential.UserName, $Credential.GetNetworkCredential().Password)
}
if ($PSBoundParameters.ContainsKey('ConnectionTimeoutSeconds')) {
$connectionString = '{0};Connection Timeout={1}' -f $connectionString, $ConnectionTimeoutSeconds
}
if ($AsString) {
$connectionString
} else {
[pscustomobject]@{ConnectionString=$connectionString}
}
}
Invoke-CCSqlCommand -DbInstance $instanceName -Path $query -CommandTimeoutSeconds 0
Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
感谢所有反馈。我想通了...
这最终是解决问题的代码:
$adjustedDate = (Get-Date).AddDays(-1)
$dateString = Get-Date -Date $adjustedDate -UFormat "%m"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%d"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%y"
$query = "\Drive\Folder\Folder\Folder\Insurance Status.sql"
$instanceName = "SQL-SERVER"
$csvFilePath = "FileSystem::\Drive\Folder\Folder\Folder\Insurance Status "
$csvFilePath += $dateString
$csvFilePath += ".csv"
$results = Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
$results | Export-Csv $csvFilePath -NoTypeInformation
我真正的问题非常明显。当我第一次 运行 遇到任务调度程序 运行 脚本的问题时,我将我的调度程序凭据更改为 "admin" 集,我最终意识到它没有正确的凭据来访问 SQL 服务器。在更改代码以包含完整的 "FileSystem::" 路径并将凭据切换回我的标准用户凭据后,一切正常。感谢您的帮助!
首先,这个脚本在我通过 Powershell 运行 时按原样工作。它与所有数据一起到达了目的地。
$adjustedDate = (Get-Date).AddDays(-1)
$dateString = Get-Date -Date $adjustedDate -UFormat "%m"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%d"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%y"
$query = "\Drive\Folder\Folder\Folder\Insurance Status.sql"
$instanceName = "SQL-SERVER"
$csvFilePath = "\Drive\Folder\Folder\Folder\Insurance Status "
$csvFilePath += $dateString
$csvFilePath += ".csv"
$results = Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
$results | Export-Csv $csvFilePath -NoTypeInformation
但是,当我 运行 它通过任务计划程序时,任务会成功完成,但导出文件从未到达映射驱动器文件夹中的目标位置。
为了让任务计划程序将 CSV 导出到映射的驱动器,我在我的路径名中添加了 "FileSystem:"。
$adjustedDate = (Get-Date).AddDays(-1)
$dateString = Get-Date -Date $adjustedDate -UFormat "%m"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%d"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%y"
$query = "FileSystem::\Drive\Folder\Folder\Folder\Insurance Status.sql"
$instanceName = "SQL-SERVER"
$csvFilePath = "FileSystem::\Drive\Folder\Folder\Folder\Insurance Status "
$csvFilePath += $dateString
$csvFilePath += ".csv"
$results = Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
$results | Export-Csv $csvFilePath -NoTypeInformation
现在,当我 运行 它通过调度程序时,CSV 使其进入映射的驱动器文件夹,但 CSV 是空白的。我错过了什么?
任务计划程序中 运行 脚本的上下文可以 change/have 影响使用 SQL 服务器模块 (sqlps/sqlserver)。您没有指定正在使用的模块,但两个模块中都存在 Invoke-Sqlcmd
。
在某些情况下,导入 sqlps 模块会将您的路径更改为 SQLSERVER 提供程序 (SQLSERVER:\
)。发生这种情况时,它会改变您访问本地文件系统的方式,它不再知道提供程序。这就是为什么它需要添加 FILESYSTEM::
以便它知道您希望与哪个提供商合作导出数据。
更新版本的 sqlserver
模块更改了提供程序的使用方式,因此它不再将 context/current 目录更改为 SQLSERVER:\ 提供程序。您可能会考虑使用该模块并将其显式导入您的脚本中。
我认为
就您可以采取的措施而言,有多种选择:
- 加载SQL模块时提示符变为SQLSERVER:\驱动器;因此您可以在脚本的开头加载它,然后更改上下文。例如。以下。这可能就是您在调度程序中看到不同行为的原因;在您的交互式 PS 会话中您已经加载了模块,因此每次您 运行 脚本时它不会重新加载。在任务调度程序中,它每次 运行 都会获得一个新会话,因此每次都必须加载模块。
Import-Module SQLPS
Set-Location c:\ # or wherever; perhaps $PSScriptRoot if you're in a script; though that has no value if you're running code outside of a script file, so may be confusing if you're pasting code in the cmdline
- 或者您可以使用 pushd/popd 包围对模块的 cmdlet 的调用,以便在调用后重置当前路径
Push-Location c:\ # doesn't matter where, so long as it exists
Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
Pop-Location # moves you back to where you were before you called Push-Location
- 或者您可以使用不同的方法。我个人非常讨厌使用这个模块的不可预知的副作用,以至于我自己编写了代码:
<#
TOPIC
about_CCSqlServer
SHORT DESCRIPTION
Executes SQL code against an MS SQL database.
#>
function Invoke-CCSqlCommand {
[CmdletBinding(DefaultParameterSetName = 'ByQueryByConnection')]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnection')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnection')]
[System.Data.SqlClient.SqlConnection]$Connection
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnectionString')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnectionString')]
[string]$ConnectionString
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByProperties')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByProperties')]
[string]$DbInstance
,
[Parameter(Mandatory = $false, ParameterSetName = 'ByQueryByProperties')]
[Parameter(Mandatory = $false, ParameterSetName = 'ByPathByProperties')]
[string]$DbCatalog = 'master'
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnection')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByConnectionString')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByQueryByProperties')]
[string]$Query
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnection')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByConnectionString')]
[Parameter(Mandatory = $true, ParameterSetName = 'ByPathByProperties')]
[string]$Path
,
[Parameter(Mandatory = $false)]
[hashtable]$Params = @{}
,
[Parameter(Mandatory = $false)]
[int]$CommandTimeoutSeconds = 30
,
[Parameter(Mandatory = $false)]
[int]$ConnectionTimeoutSeconds = 15
,
[Parameter(Mandatory = $false, ParameterSetName = 'ByQueryByProperties')]
[Parameter(Mandatory = $false, ParameterSetName = 'ByPathByProperties')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential=[System.Management.Automation.PSCredential]::Empty
)
begin {
if (! $Connection) {
if ([System.String]::IsNullOrEmpty($ConnectionString)) {
$ConnectionString = New-CCSqlConnectionString -DbInstance $DbInstance -DbCatalog $DbCatalog -ConnectionTimeoutSeconds $ConnectionTimeoutSeconds -Credential $Credential -AsString
}
$Connection = New-CCSqlConnection -ConnectionString $ConnectionString
}
}
process {
[hashtable]$splat = @{
Connection = $Connection
Params = $Params
CommandTimeoutSeconds = $CommandTimeoutSeconds
}
[System.Data.SqlClient.SqlCommand]$cmd = if ($PSCmdlet.ParameterSetName -like 'ByQuery*') {
New-CCSqlCommand @splat -Query $Query
} else {
New-CCSqlCommand @splat -Path $Path
}
[System.Data.SqlClient.SqlDataReader]$reader = $cmd.ExecuteReader()
while (($reader) -and (-not ($reader.IsClosed))) { #improve: consider using as reader rather than data table for better memory consuption with large data sets...
[System.Data.DataTable]$table = new-object 'System.Data.DataTable'
$table.Load($reader)
#write-verbose "TableName: $($table.TableName)" #NB: table names aren't always available
$table | Select-Object -ExcludeProperty RowError, RowState, Table, ItemArray, HasErrors
}
}
end {
if ($PSCmdlet.ParameterSetName -notlike '*ByConnection') {
$connection.Close() #only close the connection if we own it; if it was passed to us, leave it open
}
}
}
function New-CCSqlCommand {
[CmdletBinding(DefaultParameterSetName = 'ByQuery')]
[OutputType('System.Data.SqlClient.SqlCommand')]
param (
[Parameter(Mandatory = $true)]
[System.Data.SqlClient.SqlConnection]$Connection # Since the standard use case for this will be within Invoke-CCSqlQuery, and that works best by reusing an existing connection, we're best off only providing the conneciton option (at least for now)
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByQuery')]
[string]$Query
,
[Parameter(Mandatory = $true, ParameterSetName = 'ByPath')]
[string]$Path
,
[Parameter(Mandatory = $false)]
[hashtable]$Params = @{}
,
[Parameter(Mandatory = $false)]
[int]$CommandTimeoutSeconds = 30 #30 is the default
)
$cmd = new-object -TypeName 'System.Data.SqlClient.SqlCommand'
$cmd.Connection = $connection
if ($PSBoundParameters.ContainsKey('CommandTimeoutSeconds')) {
$cmd.CommandTimeout = $CommandTimeoutSeconds #https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout(v=vs.110).aspx
}
#load in our query
switch ($PSCmdlet.ParameterSetName) {
'ByQuery' {$cmd.CommandText = $Query; break;}
'ByPath' {$cmd.CommandText = Get-Content -Path $Path -Raw; break;}
default {throw "ParameterSet $($PSCmdlet.ParameterSetName) not recognised by Invoke-SQLQuery"}
}
#assign parameters as required
#NB: these don't need declare statements in our query; so a query of 'select @demo myDemo' would be sufficient for us to pass in a parameter with name @demo and have it used
#we can also pass in parameters that don't exist; they're simply ignored (sometimes useful if writing generic code that has optional params)
$Params.Keys | ForEach-Object{$cmd.Parameters.AddWithValue("@$_", $Params[$_]) | out-null}
$cmd
}
function New-CCSqlConnection {
[OutputType('System.Data.SqlClient.SqlConnection')]
[CmdletBinding(DefaultParameterSetName = 'ByConnectionString')]
param (
[Parameter(ParameterSetName = 'ByConnectionString', Mandatory = $true)]
[string]$ConnectionString
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $true)]
[string]$DbInstance
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $false)]
[string]$DbCatalog = 'master'
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $false)]
[int]$ConnectionTimeoutSeconds = 15 #15 is the SQL default: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectiontimeout(v=vs.110).aspx
,
[Parameter(ParameterSetName = 'ByProperties', Mandatory = $false)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
,
[Parameter(Mandatory = $false)]
[Switch]$SuppressAutoOpen
)
if ($PSCmdlet.ParameterSetName -eq 'ByProperties') {
$ConnectionString = New-CCSqlConnectionString -DbInstance $DbInstance -DbCatalog $DbCatalog -ConnectionTimeoutSeconds $ConnectionTimeoutSeconds -Credential $Credential -AsString
}
$connection = New-Object 'System.Data.SqlClient.SqlConnection'
$connection.ConnectionString = $connectionString
if (! $SuppressAutoOpen) {
$connection.Open()
}
$connection
}
function New-CCSqlConnectionString {
param (
[Parameter(Mandatory = $true)]
[string]$DbInstance
,
[Parameter(Mandatory = $false)]
[string]$DbCatalog = 'master'
,
[Parameter(Mandatory = $false)]
[int]$ConnectionTimeoutSeconds = 15 #15 is the SQL default: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectiontimeout(v=vs.110).aspx
,
[Parameter(Mandatory = $false)]
[System.Management.Automation.Credential()]
[System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty
,
[Parameter(Mandatory = $false)]
[Switch]$AsString
)
#Useful document on possible properties: https://www.connectionstrings.com/all-sql-server-connection-string-keywords/
$connectionString = ('Server={0};Database={1}' -f $DbInstance,$DbCatalog)
if ($Credential -eq [System.Management.Automation.PSCredential]::Empty) {
$connectionString = ('{0};Integrated Security=True' -f $connectionString)
} else {
$connectionString = ('{0};User Id={1};Password={2}' -f $connectionString, $Credential.UserName, $Credential.GetNetworkCredential().Password)
}
if ($PSBoundParameters.ContainsKey('ConnectionTimeoutSeconds')) {
$connectionString = '{0};Connection Timeout={1}' -f $connectionString, $ConnectionTimeoutSeconds
}
if ($AsString) {
$connectionString
} else {
[pscustomobject]@{ConnectionString=$connectionString}
}
}
Invoke-CCSqlCommand -DbInstance $instanceName -Path $query -CommandTimeoutSeconds 0
Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
感谢所有反馈。我想通了...
这最终是解决问题的代码:
$adjustedDate = (Get-Date).AddDays(-1)
$dateString = Get-Date -Date $adjustedDate -UFormat "%m"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%d"
$dateString += " "
$dateString += Get-Date -Date $adjustedDate -UFormat "%y"
$query = "\Drive\Folder\Folder\Folder\Insurance Status.sql"
$instanceName = "SQL-SERVER"
$csvFilePath = "FileSystem::\Drive\Folder\Folder\Folder\Insurance Status "
$csvFilePath += $dateString
$csvFilePath += ".csv"
$results = Invoke-Sqlcmd -InputFile $query -Querytimeout 0 -ServerInstance $instanceName
$results | Export-Csv $csvFilePath -NoTypeInformation
我真正的问题非常明显。当我第一次 运行 遇到任务调度程序 运行 脚本的问题时,我将我的调度程序凭据更改为 "admin" 集,我最终意识到它没有正确的凭据来访问 SQL 服务器。在更改代码以包含完整的 "FileSystem::" 路径并将凭据切换回我的标准用户凭据后,一切正常。感谢您的帮助!