2016-02-19 96 views
0

我有一個PowerShell腳本,用於遍歷SQL Server列表並從這些服務器中獲取擴展事件數據。它在我的SQL服務器的95%的偉大工程,但我的SQL Server的約5%,我得到這個錯誤:Powershell - 無效嘗試調用FieldCount - 讀取器已關閉?

Write-DataTable:System.Management.Automation.MethodInvocationException: Exception calling "WriteToServer" with "1" argument(s):

"Invalid attempt to call FieldCount when reader is closed." System.InvalidOperationException: Invalid attempt to call FieldCount when reader is closed.

at System.Data.SqlClient.SqlDataReader.get_FieldCount() at System.Data.SqlClient.SqlBulkCopy.WriteToServer(IDataReader reader) at CallSite.Target(Closure , CallSite , Object , Object) --- End of inner exception stack trace --- at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception) at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame).Message

我不明白爲什麼我的腳本適用於大多數SQL服務器,但不是全部。

我的PowerShell腳本:

#Create your SQL connection string to your central collection database 
$ServerAConnectionString = "Data Source=SourceServer;Initial Catalog=SourceDatabase;Integrated Security=True;" $ServerAConnection = new-object system.data.SqlClient.SqlConnection($ServerAConnectionString); 

#Create a Dataset to hold the DataTable from DBServers 
$dataSet = new-object "System.Data.DataSet" "DBServers" $query = "SET NOCOUNT ON;" $query = $query + " SELECT ServerName, FilePath " $query = $query 
     + " FROM dbo.SourceTable " $query = $query + " WHERE Domain = 'domain' " $query = $query + " AND XEventQueryEnabled = 1 " 
     #write-host $query; 

#Create a DataAdapter which youll use to populate the DataSet with the instances to collect from 
$dataAdapter = new-object "System.Data.SqlClient.SqlDataAdapter" ($query, $ServerAConnection) $dataAdapter.Fill($dataSet) #| Out-Null $ServerAConnection.Open() $sourceConnection = New-Object System.Data.SqlClient.SQLConnection($SourceConnectionString) 


$CollectionTime = date; foreach($a in $dataSet.Tables[0].Rows) { write-host "DBServer: " $a.ServerName;  # set connection string for the remote server 
    $SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true" # set connection string for the central collection server 
    $DestinationConnectionString = "Data Source=RepositoryServer;Initial Catalog=RepositoryDatabase;Integrated Security=True" 
    try 
    { 
    $sql = "  WITH cte (event_data) as " 
    $sql = $sql + " (SELECT CAST(event_data AS XML) AS event_data " 
    $sql = $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"MyXevents*.xel', NULL, NULL, NULL)) " 
    $sql = $sql + " SELECT @@SERVERNAME, * FROM cte " 
    $sql = $sql + " WHERE SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) > '2/1/16' " 
     try{ 
      write-host "Collecting XEvent XML Data from Remote SQL Server."; 
      $tableName = "RepositoryTable" 
      $sourceConnection.ConnectionString = $SourceConnectionString 
      $sourceConnection.open() 
      $commandSourceData = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection) 

      $reader = $commandSourceData.ExecuteReader() 

      $commandSourceData.CommandTimeout = '300' 
     } 
     Catch 
     { 
      $ex1 = $_.Exception.Message 

     } # end CATCH block for bad file/offset 
      write-host "Inserting XEvent XML Data to Repository."; 
      $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString 
      $bulkCopy.DestinationTableName = $tableName 
      $bulkCopy.BatchSize = 5000 
      $bulkCopy.BulkCopyTimeout = 0 
      $bulkCopy.WriteToServer($reader) 

     $reader.Close() } 
    catch 
    { 
     $ex = $_.Exception 
     Write-Host "Write-DataTable$($connectionName):$ex.Message" 
    } 
    finally 
    { 
     write-host "Finished Collecting XEvent XML Data."; 
     # $reader.close() 
    } 
    $sourceConnection.close() } 
#Close the connection as soon as you are done with it $ServerAConnection.Close() 
+1

如果異常是從內部try塊拋出這會發生。爲什麼不只是刪除內部的嘗試塊?你如何期望代碼仍然能夠繼續,如果它不能夠構建$讀者? –

+0

我刪除了內部的try塊,發現真正的問題是一個sqlcommand超時。我的錯誤是在executereader()命令之後放置sqlcommand超時。在我將execute屬性放在executereader()之前,現在一切正常。感謝您的幫助! –

回答

0

問題是SQL命令超時財產的執行讀卡器後指定。

前:

foreach($a in $dataSet.Tables[0].Rows) 
{ 
    write-host "DBServer: " $a.ServerName; 
    # set connection string for the remote server 
    $SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true" 
    # set connection string for the central collection server 
    $DestinationConnectionString = "Data Source=;Initial Catalog=;Integrated Security=True" 

    try 
    { 
    $sql = "  WITH cte (event_data) as " 
    $sql = $sql + " (SELECT CAST(event_data AS XML) AS event_data " 
    $sql = $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"*.xel', NULL, NULL, NULL)) " 
    $sql = $sql + " SELECT @@SERVERNAME, * FROM cte " 
    $sql = $sql + " WHERE SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) between '2/1/16' and '2/2/16' " 

     try{ 
      write-host "Collecting XEvent XML Data from Remote SQL Server."; 
      $tableName = "XEventXMLData" 
      $sourceConnection.ConnectionString = $SourceConnectionString 
      $sourceConnection.open() 
      $commandSourceData = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection) 

      $reader = $commandSourceData.ExecuteReader() 

      $commandSourceData.CommandTimeout = '300' 

     } 
     Catch 
     { 
      $ex1 = $_.Exception.Message 

     } # end CATCH block for bad file/offset 
      write-host "Inserting XEvent XML Data to Repository."; 
      $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString 
      $bulkCopy.DestinationTableName = $tableName 
      $bulkCopy.BatchSize = 5000 
      $bulkCopy.BulkCopyTimeout = 0 
      $bulkCopy.WriteToServer($reader) 

     $reader.Close() 
    } 
    catch 
    { 
     $ex = $_.Exception 
     Write-Host "Write-DataTable$($connectionName):$ex.Message" 
    } 
    finally 
    { 
     write-host "Finished Collecting XEvent XML Data."; 
     # $reader.close() 
    } 
    $sourceConnection.close() 

} 

後:

foreach($a in $dataSet.Tables[0].Rows) 
{ 
    write-host "DBServer: " $a.ServerName; 
    # set connection string for the remote server 
    $SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true" 
    # set connection string for the central collection server 
    $DestinationConnectionString = "Data Source=;Initial Catalog=;Integrated Security=True" 

    try 
    { 
    $sql = "  WITH cte (event_data) as " 
    $sql = $sql + " (SELECT CAST(event_data AS XML) AS event_data " 
    $sql = $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"*.xel', NULL, NULL, NULL)) " 
    $sql = $sql + " SELECT @@SERVERNAME, * FROM cte " 
    $sql = $sql + " WHERE SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) > '2/1/16' " 

    write-host "Collecting XEvent XML Data from Remote SQL Server."; 
    $sourceConnection.ConnectionString = $SourceConnectionString 
    $sourceConnection.open() 

    $commandSourceData = New-Object system.Data.SqlClient.SqlCommand 
    $commandSourceData.CommandText = $sql 
    $commandSourceData.Connection = $sourceConnection 
    $commandSourceData.CommandTimeout = 0 

    $reader = $commandSourceData.ExecuteReader() 

    write-host "Inserting XEvent XML Data to Repository."; 
    $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString 
    $bulkCopy.DestinationTableName = $tableName 
    $bulkCopy.BatchSize = 5000 
    $bulkCopy.BulkCopyTimeout = 0 
    $bulkCopy.WriteToServer($reader) 

    $reader.Close() 
    } 
    catch 
    { 
     $ex = $_.Exception 
     Write-Host "Write-DataTable$($connectionName):$ex.Message" 
    } 
    finally 
    { 
     write-host "Finished Collecting XEvent XML Data."; 
     # $reader.close() 
    } 
    $sourceConnection.close() 

} 
相關問題