2012-12-20 86 views
2

要求:將大量數據(OU內的所有用戶)從活動目錄中抽取到數據庫表中。SSIS腳本任務將數據從AD中抽取到數據庫中

方法:我的任務是使用SSIS來執行此操作,因爲還有其他項目需要作爲標準ETL事件的相同隔夜任務的一部分來完成,因此這只是流程流程中的另一個步驟。

代碼:

/* 
Microsoft SQL Server Integration Services Script Task 
Write scripts using Microsoft Visual C# 2008. 
The ScriptMain is the entry point class of the script. 
*/ 

using System; 
using System.Data; 
using System.Data.SqlClient; 
using System.DirectoryServices; 
using Microsoft.SqlServer.Dts.Runtime; 
using System.Windows.Forms; 

namespace ST_dc256a9b209442c7bc089d333507abeb.csproj 
{ 
    [System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")] 
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase 
    { 

     #region VSTA generated code 
     enum ScriptResults 
     { 
      Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success, 
      Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure 
     }; 
     #endregion 

     /* 
     The execution engine calls this method when the task executes. 
     To access the object model, use the Dts property. Connections, variables, events, 
     and logging features are available as members of the Dts property as shown in the following examples. 

     To reference a variable, call Dts.Variables["MyCaseSensitiveVariableName"].Value; 
     To post a log entry, call Dts.Log("This is my log text", 999, null); 
     To fire an event, call Dts.Events.FireInformation(99, "test", "hit the help message", "", 0, true); 

     To use the connections collection use something like the following: 
     ConnectionManager cm = Dts.Connections.Add("OLEDB"); 
     cm.ConnectionString = "Data Source=localhost;Initial Catalog=AdventureWorks;Provider=SQLNCLI10;Integrated Security=SSPI;Auto Translate=False;"; 

     Before returning from this method, set the value of Dts.TaskResult to indicate success or failure. 

     To open Help, press F1. 
    */ 

     public void Main() 
     { 
     //Set up the AD connection; 
     using (DirectorySearcher ds = new DirectorySearcher()) 
      { 
      //Edit the filter for your purposes; 
      ds.Filter = "(&(objectClass=user)(|(sAMAccountName=A*)(sAMAccountName=D0*)))"; 
      ds.SearchScope = SearchScope.Subtree; 
      ds.PageSize = 1000; 
      //This will page through the records 1000 at a time; 

      //Set up SQL Connection 
      string sSqlConn = Dts.Variables["SqlConn"].Value.ToString(); 
      SqlConnection sqlConnection1 = new SqlConnection(sSqlConn); 
      SqlCommand cmd = new SqlCommand(); 
      SqlDataReader reader; 
      cmd.CommandType = CommandType.Text; 
      cmd.Connection = sqlConnection1; 

      //Read all records in AD that meet the search criteria into a Collection 
      using (SearchResultCollection src = ds.FindAll()) 
       { 
       //For each record object in the Collection, insert a record into the SQL table 
       foreach (SearchResult results in src) 
        { 
        string sAMAccountName = results.Properties["sAMAccountName"][0].ToString(); 
        //string objectCategory = results.Properties["objectCategory"][0].ToString(); 
        string objectSid = results.Properties["objectSid"][0].ToString(); 
        string givenName = results.Properties["givenName"][0].ToString(); 
        string lastName = results.Properties["sn"][0].ToString(); 
        string employeeID = results.Properties["employeeID"][0].ToString(); 
        string email = results.Properties["mail"][0].ToString(); 

        //Replace any single quotes in the string with two single quotes for sql INSERT statement 
        objectSid = objectSid.Replace("'", "''"); 
        givenName = givenName.Replace("'", "''"); 
        lastName = lastName.Replace("'", "''"); 
        employeeID = employeeID.Replace("'", "''"); 
        email = email.Replace("'", "''"); 

        sqlConnection1.Open(); 
        cmd.CommandText = "INSERT INTO ADImport (userName, objectSid, firstName, lastName, employeeNo, email) VALUES ('" + sAMAccountName + "','" + objectSid + "','" + givenName + "','" + lastName + "','" + employeeID + "','" + email + "')"; 
        reader = cmd.ExecuteReader(); 

        string propertyName = "Description"; //or whichever multi-value field you are importing 
        ResultPropertyValueCollection valueCollection = results.Properties[propertyName]; 

        //Iterate thru the collection for the user and insert each value from the multi-value field into a table 
        foreach (String sMultiValueField in valueCollection) 
         { 
         string sValue = sMultiValueField.Replace("'","''"); //Replace any single quotes with double quotes 
         //sqlConnection1.Open(); 
         cmd.CommandText = "INSERT INTO ADImport_Description (userName, objectSid, objectDescription) VALUES ('" + sAMAccountName + "','" + objectSid + "','" + sValue + "')"; 
         reader = cmd.ExecuteReader(); 
         //sqlConnection1.Close(); 
         } 
        sqlConnection1.Close(); 
        } 
       } 
      } 
      Dts.TaskResult = (int)ScriptResults.Success; 
     } 
    } 
} 

我想到了很多,你會認識到這一點爲基本相同的代碼從這個帖子從數據女王:http://dataqueen.unlimitedviz.com/2012/09/get-around-active-directory-paging-on-ssis-import/我已經適應我的目的,因爲我跑與我自己編寫的代碼混淆了很多問題。

這一切都在一個腳本任務本身。是的,我已經在相關參考文獻中添加了,所以他們在那裏。

問題:當我運行在SSIS的腳本任務(自身,以避免干擾包的其它部分的任何機會),我得到:

Error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. 
Parameter name: index 
at System.Collections.ArrayList.get_Item(Int32 index) 
at System.DirectoryServices.ResultPropertyValueCollection.get_Item(Int32 index) 
at ST_dc256a9b209442c7bc089d333507abeb.csproj.ScriptMain.Main() 

請,任何人,任何想法? ?????

+3

我的猜測是失敗的行是'string employeeID = results.Properties [「employeeID」] [0] .ToString();'因爲您很可能會得到像Service帳戶那樣沒有定義employeeID的東西。將你的代碼複製到一個合適的.NET項目中(我喜歡控制檯),並通過deubgger找到行號。 – billinkc

+0

謝謝,會給它一個去 - 我有非常有限的工具,所以可能需要回家調試... :) – Elatesummer

+0

@billinkc謝謝 - 解決了一些問題,如果count> 0語句...如果你添加你的評論作爲答案我會將其標記爲已解決? – Elatesummer

回答

1

所有功勞歸於@billinkc(billinkc - 如果你添加一個答案,我會接受它而不是這一個,但我不喜歡留下沒有回答的問題,所以現在添加你的答案,因爲你沒有添加答案上週)

「我的猜測是不及格線串僱員= results.Properties [」僱員「] [0]的ToString();你很可能得到類似的東西,不會有服務帳戶定義了一個employeeID,將你的代碼複製到一個合適的.NET項目中(我喜歡控制檯),並通過deubgger逐步找到行號 - billinkc「

相關問題