Kỹ thuật lập trình c#

Chương 1 : Kiến trúc của C# và .NET Chương 2 : Căn bản C# Chương 3 : Hướng đối tượng trong C# Chương 4 : Những chủ đề tiến bộ trong C# Chương 5 : C# và các lớp cơ sở Chương 6 : Lập trình trong môi trường .NET Chương 7 : Windows Applications Chương 8 : Assemblies Chương 9 : Truy cập cơ sở dữ liệu với .NET Chương 10 : Viewing .NET Data Chương 11 : Thao tác XML Chương 12 : File and Registry Operations Chương 13 : Làm việc với Active Directory

doc216 trang | Chia sẻ: lvcdongnoi | Lượt xem: 3219 | Lượt tải: 2download
Bạn đang xem trước 20 trang tài liệu Kỹ thuật lập trình c#, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ác. Đầu tiên chúng ta tạo một thành phần sách mới: XmlElement newBook = doc.CreateElement("book"); Phương thức CreateElement() có ba quá tải cho phép bạn lựa chọn: element name name và không gian tên URI prefix, localname, and namespace Khi một thành phần được tạo ra chúng ta cần phải thêm các thuộc tính sau: newBook.SetAttribute("genre","Mystery"); newBook.SetAttribute("publicationdate","2001"); newBook.SetAttribute("ISBN","123456789"); Bây giờ chúng ta có các thuộc tính được tạo chúng ta cần thêm các thuộc tính khác của một cuốn sách: XmlElement newTitle = doc.CreateElement("title"); newTitle.InnerText = "The Case of the Missing Cookie"; newBook.AppendChild(newTitle); Trước tiên chúng ta tạo một đối tượng mới xuất phát từ XmlElement. Sau đó chúng ta gán thuộc tính InnerText của tựa sách như đã làm, và thêm vào như một thành phần con của book. Chúng ta lặp lại cho đên khi hết các thành phần. Chú ý răng chúng ta thêm thành phần name như một thành phần con của author. Nó cho chúng ta mối quan hệ thích hợp với các thành phần book khác. Cuối cùng, chúng ta gán thành phần newBook vào mục doc.DocumentElement. Nó cùng cấp với tất cả các thành phần book khác. Bây giờ chúng ta cập nhật một tài liệu có sẵn với một thành phần mới. Thao tác cuối cùng là ghi tài liệu mới lên đĩa. Trong ví dụ này chúng ta tạo một XmlTextWriter mới, và truyền nó cho phương thức WriteContentTo(). WriteContentTo() và WriteTo() cả hai đều tạo ra mọt XmlTextWriter như là một tham số. WriteContentTo() lưu nút hiện tại và tất cảc các nút con của nó vào XmlTextWriter, ngược lại WriteTo() chỉ lưu nút hiện tại. Bởi vì doc là một đối tượng xuất phát từ XmlDocument, nó mô tả toàn bộ tài liệu và nhưng gì nó đã lưu. Chúng ta cũng sử dụng phương thức Save(). Nó sẽ luôn lưu toàn bộ tài liệu. Save() có bốn quá tải. Bạn có thể chỉ ra một chuỗi với tên file và đường dẫn, một đối tượng xuất phát từ Stream, một đối tượng xuất phát từ TextWriter, một đối tượng xuất phát từ XmlWriter. Chúng ta cũng gọi phương thức Close() trên XmlTextWriter để đẩy vào vùng nhớ đệm nội và đóng file. Đây là những gì chúng ta sẽ cho khi chạy ví dụ này. Chú ý rằng mục đầu tiên nằm ở đáy của danh sách: Nếu muốn tạo một tài liệu từ chúng, chúng ta có thể dùng XmlTextWriter như đã thấy trong phần trên. Chúng ta cũng có thể dùng XmlDocument. Tại sao dùng một trong số chúng? Nếu bạn muốn chuyển dữ liệu thành XML là sẵn có và sẵn sàng để ghi, trong trường hợp này lớp XmlTextWriter là lựa chọn tốt nhất. Và khi bạn cần tạo tài liệu XML từng chút một, và chèn các nút vào những vị trí khác nhau, sau đó tạo tài liệu khi đó lớp XmlDocument có thể là lựa chọn tốt nhất. Chúng ta có thể hoàn tất nó bằng thay đổi dòng sau: doc.Load("..\\..\\..\\books.xml"); thành (mã này nằm trong ví dụ DOMSample4): //create the declaration section XmlDeclaration newDec = doc.CreateXmlDeclaration("1.0",null,null); doc.AppendChild(newDec); //create the new root element XmlElement newRoot = doc.CreateElement("newBookstore"); doc.AppendChild(newRoot); Trước tiên, chúng ta tạo một XmlDeclaration mới. Các tham số là phiên bản (hiện tại là 1.0), mã hóa, và cờ standalone. Tham số mã hoá có thể được gán bởi một chuỗi là thành phần của lớp System.Text.Encoding nếu null không được dùng . null mặc định là UTF-8. Cờ standalone có thể là yes, no, hoặc null. Nếu nó là null thì thuộc tính không được dùng và sẽ không được mô tả trong tài liệu. Bước kế tiếp tạo ra DocumentElement. Trong trường hợp này chúng ta gọi newBookstore vì vậy bạn có thể nhận thấy khác biệt. Mục đích của mã giống như ví dụ trước, và hoạt động theo cùng một cách. Đây là booksEdit.xml được tạo ra từ mã: The Case of the Missing Cookie C. Monster 9.95 Chúng ta sẽ không xem xét kĩ lớp XmlDocument, cũng như các lớp khác giúp tạo mô hình DOM trong .NET. Tuy nhiên, chúng ta đã xem xét khả năng và tính mềm dẻo mà thực thi DOM trong .NET hỗ trợ. Bạn sẽ muốn sử dụng lớp XmlDocument khi bạn muốn truy xuất ngẫu nhiên đến tài liệu, hoặc các lớp xuất phát từ XmlReader khi bạn muốn một mô hình kiểu stream thay thế. Nhớ rằng cái giá phải trả cho tính mềm dẻo của XmlNode-based XmlDocument đó là bộ nhớ yêu cầu cao và việc đọc tài liệu không tốt bằng XmlReader. Vì vậy hãy suy nghĩ kĩ phương thức trước khi chọn. Sử dụng XPath và XSLT trong .NET Trong phần này, chúng ta sẽ xem xét hỗ trợ cho XPath và XSL Transforms (XSLT) trong .NET Framework. XPath được hỗ trợ thông qua không gian tên System.Xml.XPath, và XSLT được hỗ trợ thông qua không gian tên System.Xml.Xsl. Lí do xem xét cả hai lớp trên là vì lớp XPathNavigator của không gian tên System.XPath cung cấp cách rất thực tế để thực thi các biến đổi XSL trong .NET. XPath là một ngôn ngữ truy vấn cho XML. Bạn sẽ dùng XPath để chọn một bộ con các các yếu tố giá trị văn bản hoặc các giá trị thuộc tính. XSLT được dụng để thay đổi một tài liệu gốc sang một tài liệu với một cấu trúc kiểu khác. Trước tiên chúng ta sẽ xem xét System.XPath và trình bày cách dùng các lớp System.Xml.Xsl. Không gian tên System.XPath Không gian tên System.XPath được xây dựng dựa trên yếu tố tốc độ. Nó cung cấp một thể hiện chỉ đọc cho tài liệu XML của bạn, vì vậy không có vấn đề soạn thảo ở đây. Các lớp trong không gian này được xây dựng đẻ thực thi lặp nhanh và lựa chon trên tài liệu XML trong một con trỏ. Đây là một bảng liệt kê các lớp trong System.XPath, và một giải thích ngắn vì hỗ trợ của mỗi lớp: Class Name Description XPathDocument Một view của tài liệu XML . Chỉ đọc. XPathNavigator Cung cấp khả năng điều hướng cho một XPathDocument. XPathNodeIterator Cung cấp khả năng truy xuất trực tiếp các nút. XPath trang bị một bộ nút trong Xpath. XPathExpression Một biên dịch phương thức XPath. Được dùng bởi SelectNodes, SelectSingleNodes, Evaluate, và Matches. XPathException XPath exception class. XPathDocument XPathDocument tương thích cho bất kì thao tác nào của lớp XmlDocument. Nếu bạn cần khả năng soạn thảo, XmlDocument được lựa chọn khi bạn sử dụng ADO.NET, XmlDataDocument (chúng ta sẽ xem xét ở phần sau của chương). Dĩ nhiên, khi cần thao tác nhanh bạn có thể sử dụng XPathDocument. Nó có bốn quá tải cho phép bạn một một tài liệu XML từ một file và một đường dẫn, một đối tượng TextReader, một đối tượng XmlReader hoặc một đối tượng Stream-based. XPathNavigator XPathNavigator chứa tât cả các phương thức di chuyển, lựa chọn mà bạn cần. Sau đây là một số phương thức được định nghĩa trong lớp: Method Name Description MoveTo() Cần một tham số XPathNavigator. Di chuyển vị trí hiện tại đến vị trí được truyền trong XPathNavigator. MoveToAttribute() Di chuyển tới thuộc tính được chọn. Cần một tên thuộc tính và không gian làm tham số. MoveToFirstAttribute() Di chuyển đến thuộc tính đầu tiên của mục hiện tại. Trả về giá trị true nếu thành công. MoveToNextAttribute() Di chuyển đến thuộc tính tiếp theo của mục hiện tại. Trả về true nếu thành công. MoveToFirst() Di chuyển đến mẫu đầu tiên cùng loại với mẫu hiện tại. Trả về true nếu thành công, ngược lại trả về false. MoveToLast() Di chuyển đến mẫu cuối cùng cùng loại với mẫu hiện tại. Trả về true nếu thành công. MoveToNext() Di chuyển đến mẫu tiếp theo cùng loại với mẫu hiện tại. Trả về true nếu thành công. MoveToPrevious() Di chuyển đến mẫu trước cùng loại với mẫu hiện tại. Trả về true nếu thành công. MoveToFirstChild() Di chuyển đến mẫu con đầu tiên của mẫu hiện tại. Trả về true nếu thành công. MoveToId() Di chuyển đếu mẫu có ID được truyền qua tham số. Nó cần một sơ đồ tài liệu, và một kiểu dữ liệu cho là kiểu của ID. MoveToParent() Di chuyển đến cha của mẫu hiện tại. Trả về true nếu thành công. MoveToRoot() Di chuyển nếu nút gốc của tài liệu. Có một vài phương thức Select() khác nhau hỗ trợchọn một tập các nút để làm việc. Tất cả các phương thức Select() trả về một đối tượng XPathNodeIterator. Ngoài ra có thể sử dụng các phương thức SelectAncestors() và SelectChildren(). Cả hai phương thức đều trả về một XPathNodeIterator. Trong khi Select() cần một tham số XPath, thì các phương thức này cần một tham số XPathNodeType. Bạn có thể dùng XPathNavigator để lưu trữ như là một file hệ thống hoặc Registry thay cho một XPathDocument. XPathNodeIterator XPathNodeIterator có thể coi là một trang bị NodeList hoặc một NodeSet trong XPath. Đối tượng này có ba thuộc tính và hai phương thức: Clone – Tạo một copy mới của chính nó Count – Số các nút trong đối tượng XPathNodeIterator Current – Trả về một XPathNavigator trỏ đến nút hiện tại CurrentPosition() – Trả về một số integer chứa vị trí hiện tại MoveNext() – Di chuyển đến nút tiếp theo thường thấy trong biểu thức XPath dùng để tạo một XpathNodeIterator Sử dụng các lớp trong không gian tên XPath Các tốt nhất để chỉ ra cách làm việc của các ví dụ này là thông qua ví dụ. Hãy load tài liệu books.xml xem qua chúng bạn sẽ thấy được định hướng của công việc. Trước tiên, chúng ta tạo một tham chiếu đến các không gian tên System.Xml.Xsl và System.Xml.XPath: using System.Xml.XPath; using System.Xml.Xsl; Trong ví dụ này chúng ta sử dụng file booksxpath.xml. Nó giống như books.xml mà chúng ta đã dùng, ngoại trừ có một hai quyến sách được thêm vào. Bạn có thể tìm thấy mã nguồn trong thư mục XPathXSLSample1: private void button1_Click(object sender, System.EventArgs e) { //modify to match your path structure XPathDocument doc=new XPathDocument("..\\..\\..\\booksxpath.xml"); //create the XPath navigator XPathNavigator nav=doc.CreateNavigator(); //create the XPathNodeIterator of book nodes // that have genre attribute value of novel XPathNodeIterator iter=nav.Select("/bookstore/book[@genre='novel']"); while(iter.MoveNext()) { LoadBook(iter.Current); } } private void LoadBook(XPathNavigator lstNav) { //We are passed an XPathNavigator of a particular book node //we will select all of the descendents and //load the list box with the names and values XPathNodeIterator iterBook=lstNav.SelectDescendants (XPathNodeType.Element,false); while(iterBook.MoveNext()) listBox1.Items.Add(iterBook.Current.Name + ": " + iterBook.Current.Value); } Đầu tiên trong phương thức button1_Click() chúng ta tạo một XPathDocument (gọi là doc), và truyền cho nó đường dẫn đến tài liệu mà bạn muốn mở. Trong dòng tiếp theo chúng ta tạo ra một XPathNavigator: XPathNavigator nav = doc.CreateNavigator(); Trong ví dụ này, chúng ta sử dụng phương thức Select() để lấy bộ các nút có thuộc tính loại là novel (tiểu thuyết). Sau đó chúng ta sử dụng phương thức MoveNext() để duyệt qua các tiểu thuyết trong danh mục sách. Để load dữ liệu vào một listbox, chúng ta sử dụng thuộc tính XPathNodeIterator.Current. Nó sẽ tạo ra một đối tượng XPathNavigator mới dựa trên nút mà XPathNodeIterator đang trỏ đến. Trong trường hợp này, chúng ta tạo một XPathNavigator cho một mục sách trong tài liệu. Phương thức LoadBook() nhận XPathNavigator này và tạo ra một XPathNodeIterator khác bằng cách phát ra một kiểu khác của phương thức select, phương thức SelectDescendants(). Nó sẽ cho chúng ta một XPathNodeIterator của các nút con và các nút con của các nút con này của mục sách mà chúng ta đã truyền cho phương thức LoadBook(). Sau đó chúng ta tạo một vòng lặp MoveNext() khác trên XPathNodeIterator và load các thành phần tên và giá trị vào listbox. Đây là màn hình sau khi chạy mã. Nhớ rằng ở đây chỉ có các tiểu thuyết mới được liệt kê: Nếu muốn thêm giá cho những quyển sách này thì phải làm sao? XPathNavigator cung cấp phương thức Evaluate() để hỗ trợ những thao tác kiểu như thế này. Evaluate() có ba quá tải. Phương thức thứ nhất chứa một chuỗi mà hàm XPath gọi. Phương thức thứ hai sử dụng một tham số đối tượng XPathExpression, phương thức thứ ba sử dụng các tham số XPathExpression XPathNodeIterator. Các thay đổi được in đậm (mã có thể được tìm thấy trong XPathXSLSample2): private void button1_Click(object sender, System.EventArgs e) { //modify to match your path structure XPathDocument doc = new XPathDocument("..\\..\\..\\booksxpath.XML"); //create the XPath navigator XPathNavigator nav = doc.CreateNavigator(); //create the XPathNodeIterator of book nodes // that have genre attribute value of novel XPathNodeIterator iter = nav.Select("/bookstore/book[@genre='novel']"); while(iter.MoveNext()) { LoadBook(iter.Current.Clone()); } //add a break line and calculate the sum listBox1.Items.Add("========================"); listBox1.Items.Add("Total Cost = " + nav.Evaluate("sum(/bookstore/book[@genre='novel']/price)")); } Bây giờ, trong listbox có giá các quyển sách: Không gian tên System.Xml.Xsl Không gian tên System.Xml.Xsl chứa các lớp được .NET Framework sử dụng để hỗ trợ các biến đổi XSL. Không gian được tham chiếu sẵn trong các lưu trữ có thực thi giao diện IXPathNavigable.Trong .NET Framework, sẵn chứa XmlDocument, XmlDataDocument, và XPathDocument. Một lần nữa XPath là cách lưu trữ khôn ngoan nhất. Nếu bạn muốn tạo một lưu trữ tùy chọn, như file hệ thống, và bạn muốn có thể thay đổi, hãy bảo đảm rằng lớp của bạn đã thực thi giao diện IXPathNavigable. XSLT dựa trên mô hình kéo. Bởi vậy, bạn có thể gọp các thay đổi khác nhau lại. Nếu muốn bạn có thể áp dụng một reader tùy chọn giữa các biến đổi. Nó cho tạo ra một khả năng mềm dẻo trong thiết kế. Biến đổi XML Ví dụ đầu tiên mà chúng ta xem xét lấy tài liệu books.xml và thể hiện dưới dạng HTML ví dụ sử dụng file XSLT: books.xsl. (mã có thể tìm thấy trong thư mục XPathXSLSample3.) Chúng ta phải thêm các dòng using sau: using System.IO; using System.Xml.Xsl; using System.Xml.XPath; Đây là mã thực thi: private void button1_Click(object sender, System.EventArgs e) { //create the new XPathDocument XPathDocument doc = new XPathDocument("..\\..\\..\\booksxpath.xml"); //create a new XslTransForm XslTransform transForm = new XslTransform(); transForm.Load("..\\..\\..\\books.xsl"); //this FileStream will be our output FileStream fs=new FileStream("..\\..\\..\\booklist.html", FileMode.Create); //Create the navigator XPathNavigator nav = doc.CreateNavigator(); //Do the transform. The output file is created here transForm.Transform(nav, null, fs); } Chúng ta tạo một đối tượng xuất phát từ XPathDocument và một đối tượng xuất phát từ XslTransform. Load file booksxpath.xml vào XPathDocument, và books.xsl vào XslTransform. Trong ví dụ này, chúng ta cũng tạo một đối tượng FileStream để ghi tài liệu HTML mới lên đĩa. Nếu đây là một ứng dụng ASP.NET, chúng ta có thể dùng một đối tượng TextWriter và truyền nó cho đối tượng HttpResponse. Nếu chúng ta đang thay đổi một tài liệu XML khác, chúng ta có thể dùng một đối tượng XmlWriter. Sau khi đã chuẩn bị các đối tượng XPathDocument và XslTransform, chúng ta tạo XPathNavigator trên XPathDocument, và truyền XPathNavigator và FileStream cho phương thức Transform() của đối tượng XslTransform. Transform() có một vài quá tải, truyền và kến nối các điều hướng, XsltArgumentList (trình bày sau), Và IO streams. Tham số đều hướng có thể là XPathNavigator, hoặc bất kì đối tượng nào thực thi giao diện IXPathNavigable. IO streams có thể là một TextWriter, Stream, hoặc một đối tượng XmlWriter. Tài liệu books.xsl giống như sau: <xsl:stylesheet version="1.0" xmlns:xsl=""> Price List Sử dụng XsltArgumentList Chúng ta đã sớm đề cập đến XsltArgumentList. Đây là cách bạn kết nối một đối tượng với các phương thức và một không gian tên. Khi hoàn tất, bạn có thẻ triệu gọi các phương thức trong quá trình biến đổi. Hãy xem ví dụ dưới đây và chỉ ra cách hoạt động của chúng (mã có thể tìm thấy trong XPathXSLSample4). private void button1_Click(object sender, System.EventArgs e) { //new XPathDocument XPathDocument doc=new XPathDocument("..\\..\\..\\booksxpath.xml"); //new XslTransform XslTransform transForm=new XslTransform(); transForm.Load("..\\..\\..\\booksarg.xsl"); //new XmlTextWriter since we are creating a new XML document XmlWriter xw=new XmlTextWriter("..\\..\\..\\argSample.xml",null); //create the XsltArgumentList and new BookUtils object XsltArgumentList argBook=new XsltArgumentList(); BookUtils bu=new BookUtils(); //this tells the argumentlist about BookUtils argBook.AddExtensionObject("urn:ProCSharp",bu); //new XPathNavigator XPathNavigator nav=doc.CreateNavigator(); //do the transform transForm.Transform(nav,argBook,xw); xw.Close(); } //simple test class public class BookUtils { public BookUtils(){} public string ShowText() { return "This came from the ShowText method!"; } } Đây là file đã biến đổi (argSample.xml): The Autobiography of Benjamin Franklin This came from the ShowText method! The Confidence Man This came from the ShowText method! The Gorgias This came from the ShowText method! The Great Cookie Caper This came from the ShowText method! A Really Great Book This came from the ShowText method! Trong ví dụ này, chúng ta định nghĩa một lớp mới, BookUtils. Trong lớp này chúng ta có một phương thức chỉ trả về chuỗi "This came from the ShowText method!". Trong sự kiện button1_Click(), chúng ta tạo ra XPathDocument và XslTransform như chúng ta đã từng làm với hai ngoại lệ. Trong lúc chúng ta tạo một tài liệu XML, vì thế chúng ta dùng XmlWriter thay cho FileStream mà chúng ta đã từng dùng. Các thay đổi khác: XsltArgumentList argBook=new XsltArgumentList(); BookUtils bu=new BookUtils(); argBook.AddExtensionObject("urn:ProCSharp",bu); Chúng ta tạo một XsltArgumentList. Chúng ta tạo một thể hiện của đối tượng BookUtils,và gọi phương thức AddExtensionObject(). Khi gọi Transform(), chúng ta truyền trong các đối tượng XsltArgumentList (argBook) với XPathNavigator và XmlWriter mà chúng ta đã tạo. Đây là tài liệu booksarg.xsl: <xsl:stylesheet version="1.0" xmlns:xsl="" xmlns:bookUtil="urn:ProCSharp"> Hai dòng quan trọng được in đậm. Đầu tiên chúng ta thêm không gian tên mà chúng ta đã tạo khi thêm đối tượng XsltArgumentList. Sau đó khi muốn gọi, chúng ta sử dụng không gian các kí hiệu chuẩn trong không gian tên XSLT . Chúng ta còn có một cách khác đó là sử dụng XSLT scripting. Bạn có thể nhúng mã C#, VB, và JavaScript trong một stylesheet. Không giống như thực thi phi .NET kịch bản sẽ được thực thi khi XslTransform.Load() được gọi; cách này thực thi các kịch bản đã được biên dịch, giống như cách mà ASP.NET làm. Hãy sửa đổi file XSLT trên theo cách này. Trước tiên chúng ta thêm kịch bản vào stylesheet. bạn có thể thấy các thay đổi trong booksscript.xsl dưới đây: <xsl:stylesheet version="1.0" xmlns:xsl="" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user=""> string ShowText() { return "This came from the ShowText method!"; } Chúng ta cài không gian tên scripting, và thêm mã (đã được biên dịch bởi Visual Studio .NET IDE), và tạo một lời gọi đến stylesheet. File xuất giống hệt ví dụ trên. Tóm lại, sử dụng XPathDocument nếu bạn muốn soạn thảo, XmlDataDocument nếu bạn muốn lấy dữ liệu từ ADO.NET, và XmlDocument nếu bạn muốn có thể thao tác dữ liệu. Tóm tắt Trong chương này chúng ta kham phát rát nhiều khía cạnh của không gian tên System.Xml namespace trong .NET Framework. Chúng ta đã xem xét cách đọc ghi các tài liệu XML sử dụng các lớp truy xuất nhanh XmlReader và XmlWriter. Chúng ta xem xét cách hoạt động của DOM trong .NET, và cách dùng cách khả năng của DOM. Chúng ta thấy rằng XML và ADO.NET có quan hệ rất gần. Một DataSet và một tài liệu XML chỉ là hai thể hiện khác nhau của cùng một công nghệ. Và dĩ nhiên chúng ta xem qua XPath và XSL Transforms. XML sẽ là một phần quan trong trong các ứng dụng trong một vài năm tới. .NET Framework có sẵn các công cụ mạnh mẽ hỗ trợ các thao tác trên XML. Để hiểu hơn về XML trong C#, hãy tìm đọc tác phẩm "Data-Centric .NET Programming with C#" (Wrox Press, ISBN 1-861005-92-x). Trong chương tới chúng ta sẽ xem xét cách quản một file và Registry bằng các lớp C#. Chương 12: File and Registry Operations Tổng quan Trong chương này chúng ta sẽ khảo sát làm thế nào để thực hiện các nhiệm vụ như đọc từ file và viết ra file và hệ thống đăng ký (Registry) trong C#. Cụ thể chúng ta sẽ được học. Cấu trúc thư mục, tìm kiếm file và folder hiện diện và kiểm tra thuộc tính của chúng. Di chuyển, sao chép, huỷ các file và folder Đọc và ghi văn bản trong các file Đọc và ghi các khoá trong Registry Microsoft cung cấp rất nhiều mô hình đối tượng trực giác mà chúng ta sẽ được khào sát trong chương này, chúng ta cũng biết cách sử dụng các lớp cơ bản của .NET để thực hiện các nhiệm vụ được đề cập ở trên. Di chuyển, Sao chép, Huỷ File Chúng ta vừa mới đế cập di chuyển và huỷ files hoặc folders bằng phương thức MoveTo() và Delete() của lớp FileInfo và DirectoryInfo. Các phương thức tương đương nhau trên các lớp File và Directory là Move() và Delete(). Lớp FileInfo và File cũng có cách thức thực hiện tương tự, CopyTo() and Copy(). Không có fương thức nào copy các folder, tuy nhiên bạn có thể copy từng file trong folder. Tất cả các phương thức này đều hoàn toàn trực giác, bạn có thể tìm kiếm chi tiết trong help MSDN. Trong phần này chúng ta sẽ học cách gọi các phương thức tỉnh Move(), Copy(), và Delete() trong lớp File.Để thực hiện chúng ta dùng bài học phần trước FileProperties làm ví dụ, FilePropertiesAndMovement. Ví dụ này ta sẽ thêm tính năng mỗi lần thuộc tính của một file được hiển thị, ứng dụng này sẽ cho ta chọn lựa thêm xoá file hoặc di chuyển hoặc sao chép nó đến vị trí khác Ví dụ: FilePropertiesAndMovement Ví dụ mới như sau: Từ hình trên chúng ta có thể thấy nó rất giống nhau trong lần xuất hiện ở ví dụ FileProperties, Ngoại trừ chúng có thêm một nhóm gồm ba nút button và một textbox tại phía dưới cửa xổ. Các điều khiển này chỉ hiện khi ví dụ hiển thị thuộc tính của một file- Lần khác chúng bị ẩn, Khi thuộc tính của file được hiển thị ,FilePropertiesAndMovement tự động đặt tên đầy đủ đường dẫn của file đó ở cuối của xổ trong textbox. User có thể nhấn bất kỳ buttons để thực hiện phép toán thích hợp. Khi chương trình chạy một message box tương ứng được hiển thị xác nhận hành động. Để mã hoá chúng ta cần thêm các điều khiển thích hợp, giống như thêm các sự kiện điều khiển cho ví dụ FileProperties . Chúng ta tạo các controls mới với tên buttonDelete, buttonCopyTo, buttonMoveTo, và textBoxNewPath. Chúng ta sẽ thấy sự kiện điều kiện nhận được khi user nhấn vào Delete button; protected void OnDeleteButtonClick(object sender, EventArgs e) { try { string filePath = Path.Combine(currentFolderPath, textBoxFileName.Text); string query = "Really delete the file\n" + filePath + "?"; if (MessageBox.Show(query, "Delete File?", MessageBoxButtons.YesNo) == DialogResult.Yes) { File.Delete(filePath); DisplayFolderList(currentFolderPath); } } catch(Exception ex) { MessageBox.Show("Unable to delete file. The following exception" + " occurred:\n" + ex.Message, "Failed"); } } Đoạn code thực hiện phương thức này sẽ có phần nắm bắt lỗi, thông báo sẽ lỗi không thể xoá được nếu file xoá đang thực hiện trên một tiến trình khác. Chúng ta xây dựng đường dẫn của file của file bị xoá từ trường CurrentParentPath , Nơi nó chứa dường dẫn thư mục cha, và tên file trong textBoxFileName textbox: Phương thức di chuyển và sao chép file được cấu trúc : protected void OnMoveButtonClick(object sender, EventArgs e) { try { string filePath = Path.Combine(currentFolderPath, textBoxFileName.Text); string query = "Really move the file\n" + filePath + "\nto " + textBoxNewPath.Text + "?"; if (MessageBox.Show(query, "Move File?", MessageBoxButtons.YesNo) == DialogResult.Yes) { File.Move(filePath, textBoxNewPath.Text); DisplayFolderList(currentFolderPath); } } catch(Exception ex) { MessageBox.Show("Unable to move file. The following exception" + " occurred:\n" + ex.Message, "Failed"); } } protected void OnCopyButtonClick(object sender, EventArgs e) { try { string filePath = Path.Combine(currentFolderPath, textBoxFileName.Text); string query = "Really copy the file\n" + filePath + "\nto " + textBoxNewPath.Text + "?"; if (MessageBox.Show(query, "Copy File?", MessageBoxButtons.YesNo) == DialogResult.Yes) { File.Copy(filePath, textBoxNewPath.Text); DisplayFolderList(currentFolderPath); } } catch(Exception ex) { MessageBox.Show("Unable to copy file. The following exception" + " occurred:\n" + ex.Message, "Failed"); } } Chúng ta cũng tạo buttons và textbox mới được đánh dấu enabled và disabled ở thời điểm thích hợp để enable chúng khi chúng ta hiển thị nội dung của file, chúng ta cần thêm đoạn code sau: protected void DisplayFileInfo(string fileFullName) { FileInfo theFile = new FileInfo(fileFullName); if (!theFile.Exists) throw new FileNotFoundException("File not found: " + fileFullName); textBoxFileName.Text = theFile.Name; textBoxCreationTime.Text = theFile.CreationTime.ToLongTimeString(); textBoxLastAccessTime.Text = theFile.LastAccessTime.ToLongDateString(); textBoxLastWriteTime.Text = theFile.LastWriteTime.ToLongDateString(); textBoxFileSize.Text = theFile.Length.ToString() + " bytes"; // enable move, copy, delete buttons textBoxNewPath.Text = theFile.FullName; textBoxNewPath.Enabled = true; buttonCopyTo.Enabled = true; buttonDelete.Enabled = true; buttonMoveTo.Enabled = true; } Chúng ta cũng cần thay đổi DisplayFolderList: protected void DisplayFolderList(string folderFullName) { DirectoryInfo theFolder = new DirectoryInfo(folderFullName); if (!theFolder.Exists) throw new DirectoryNotFoundException("Folder not found: " + folderFullName); ClearAllFields(); DisableMoveFeatures(); textBoxFolder.Text = theFolder.FullName; currentFolderPath = theFolder.FullName; // list all subfolders in folder foreach(DirectoryInfo nextFolder in theFolder.GetDirectories()) listBoxFolders.Items.Add(NextFolder.Name); // list all files in folder foreach(FileInfo nextFile in theFolder.GetFiles()) listBoxFiles.Items.Add(NextFile.Name); } DisableMoveFeatures là một hàm tiện ích nhỏ nó disables các controls mới: void DisableMoveFeatures() { textBoxNewPath.Text = ""; textBoxNewPath.Enabled = false; buttonCopyTo.Enabled = false; buttonDelete.Enabled = false; buttonMoveTo.Enabled = false; } Chúng ta cần thêm phương thức ClearAllFields() để xoá các textbox thêm vào: protected void ClearAllFields() { listBoxFolders.Items.Clear(); listBoxFiles.Items.Clear(); textBoxFolder.Text = ""; textBoxFileName.Text = ""; textBoxCreationTime.Text = ""; textBoxLastAccessTime.Text = ""; textBoxLastWriteTime.Text = ""; textBoxFileSize.Text = ""; textBoxNewPath.Text = ""; } Đến đây đoạn mã chúng ta đã hoàn thành.Bạn có thể tham khảo chương trình kèm theo sách download Đọc và viết vào File Đọc và viết vào files nói chung rất đơn giản; tuy nhiên , Điều này không phải bắt buộc biết các đối tượng DirectoryInfo hoặc FileInfo mà chúng ta vừa khảo sát.Thay vào đó chúng ta phải biết một số lớp trình bày nội dung chung gọi là stream, Điều này chúng ta sẽ khảo sát sau đây. Streams Đọc và viết dữ liệu sẽ được thực hiện thông qua lớp stream. Stream là dòng dữ liệu chảy đi. Đây là một thực thể (entity) có khả năng nhận được hoặc tạo ra một "nhúm" dữ liệu. System.IO.Stream là một lớp abstract định nghĩa một số thành viên chịu hỗ trợ việc đọc/viết đồng bộ (synchronus) hoặc không đồng bộ (asynchronous) đối với khối trữ tin (nghĩa là một tập tin trên đĩa hoặc tập tin trên ký ức). Vì Stream là một lớp abstract, nên bạn chỉ có thể làm việc với những lớp được dẫn xuất từ Stream. Các hậu duệ của Stream tượng trưng dữ liệu như là một dòng dữ liệu thô dạng bytes (thay vì dữ liệu dạng văn bản). Ngoài ra, các lớp được dẫn xuất từ Stream hỗ trợ việc truy tìm (seek) nghĩa là một tiến trình nhận lấy và điều chỉnh vị trí trên một dòng chảy. Trước khi tìm hiểu những chức năng mà lớp Stream cung cấp, bạn nên xem qua các thành viên của lớp Stream. Ý tưởng của stream đã có từ lâu. Một stream là một đối tượng dùng để chuyển dữ liệu. Dữ liệu có thể được truyền theo hai hướng: Nếu dữ liệu được truyền từ nguồn bên ngoài vào trong chương trình của bạn, ta gọi là đọc dữ liệu Nếu dữ liệu được truyền từ chương trình của bạn ra nguồn bên ngoài , ta gọi là viết dữ liệu Thường thì nguồn bên ngoài sẽ là một file, ngoài ra nó còn bao gồm cả trường hợp sau: Đọc hoặc ghi dữ liệu trên mạng dùng giao thức mạng Đọc hoặc ghi đến một đường ống chỉ định Đọc hoặc ghi đến một vùng của bộ nhớ Các lớp có mối liên hệ trong namespace System.IO như hình sau: Làm việc với Binary Files Reading and writing to binary files thường được làm việc với lớp FileStream . Làm việc với FileStream Lớp FileStream đem lại việc thi công cho những thành viên của lớp abstract Stream theo một thể thức thích hợp đối với các file-base streaming giống như các lớp DirectoryInfo và FileInfo, lớp FileStream cho phép mở những tập tin hiện hữu cũng như tạo mới file. Khi tạo tập tin , lớp FileStream thường dùng những enum FileMode, FileAccess và FileShare // tạo một tập tin mới trên thư mục làm việc FileStream myFStream = new FileStream("test.dat",FileMode.OpenOrCreate, FileAccess.ReadWrite); The FileStream Class FileStream được sử dụng đọc và viết dữ liệu vào hoặc từ một file. Để khởi tạo một FileStream, bạn cần 4 phần sau: file bạn muốn truy xuất . mode, cho biết bạn muốn mở file như thế nào. access, cho biết bạn muốn truy xuất file như thế nào – bạn định đọc hoặc viết file hoặc cả hai. share access – khả năng truy xuất file. Enumeration Values FileMode Append, Create, CreateNew, Open, OpenOrCreate, or Truncate FileAccess Read, ReadWrite, or Write FileShare Inheritable, None, Read, ReadWrite, or Write Làm việc với BufferedStream Khi bạn triệu gọi hàm Read() thì một công tác đọc dữ liệu cho đầy buffer từ đĩa được tiến hành. Tuy nhiên, để cho có hiệu năng, hệ điều hành thường phải đọc trong một lúc một khối lượng lớn dữ liệu tạm thời trữ trên bufer. Buffer hoạt động như mọt kho hàng. Một đối tượng Bufered stream cho phép hệ điều hành tạo buffer riêng cho mình dùng, rồi đọc dữ liệu vào hoặc viết dữ liệu lên ổ đĩa theo một khối lượng dữ liệu nào đó mà hệ điều hành thấy là có hiệu năng. Tuy nhiên, bạn xũng có thể ấn định chiều dài khối dữ liệu. Nhưng bạn nhớ cho là buffer sẽ chiêmd chỗ trong ký ức chứ không phải trên đĩa từ. Hiệu quả sử dụng đến buffer là ciệc xuất nhập dữ liệu chạy nhanh hơn. Một đối tượng BufferedStream được hình thành xung quanh một đối tượng Stream mà bạn đã tạo ra trước đó. Muốn sử dụng đến một BufferedStream bạn bắt đầu tạo một đối tượng Stream thông thường như trong thí dụ : stream inputstream = File.OpenRead(@"C;\test\source\folder3.cs "); stream outputstream = File.Openwrite(@"C:test\source\folder3.bak"); Một khi bạn đã có stream bình thường, bạn trao đối tượng này cho hàm constructor của buffere stream: BufferedStrream bufInput = new BufferedStream(inputstream); BufferedStream bufOutput =new BufferedStream(outputstream); Sau đó, bạn sử dụng BufferedStream như là một stream bình thường, bạn triệu gọi hàm Read() hoặc Write() như bạn đã làm trước kia. Hệ điều hành lo việc quản lý vùng đêm: while ((bytesRead = bufInput.Read(buffer, 0, SIZE_BUFF))>0) { bufOutput.Write(buffer, 0, bytesRead); } Chỉ có một khác biệt mà bạn phải nhớ cho là phải tuôn ghi (flush) nội dung của buffer khi bạn muốn bảo đảm là dữ liệu được ghi lên đĩa. bufOutput.Flush(); Lệnh trên bảo hệ điều hành lấy toàn bộ dữ liệu trên buffer cho tuôn ra ghi lên tập tin trên đĩa. Làm việc với những tập tin văn bản Nếu bạn biết file bạn đang làm việc (đọc/viết) thuộc loại văn bản nghĩa là dữ liệu kiểu string, thì bạn nên nghĩ đến việc sử dụng đến các lớp StreamReader và StreamWriter. Cả hai lớp theo mặc nhiên làm việc với ký tự Unicode. Tuy nhiên bạn có thể thay đổi điều này bằng cách cung cấp một đối tượng quy chiếu được cấu hình một cách thích hợp theo System.Text.Reference. Nói tóm lại hai lớp này được thiết kế để thao tác dễ dàng các tập tin loại văn bản. Lớp StreamReader được dẫn xuất từ một lớp abstract mang tên TextReader cũng giống như String Reader. Lớp cơ bản TextReader cung cấp một số chức năng hạn chế cho mỗi hậu duệ, đặc biệt khả năng đọc và "liếc nhìn" (peek) lên một dòng ký tự (character stream). Lớp StreamWriter và StringWriter cũng được dẫn xuất từ một lớp abstract mang tên TextWriter; lớp này định nghĩa những thành viên cho phép các lớp dẫn xuât viết những dữ liệu văn bản lên một dòng văn bản nào đó Các thành viên của lớp TextWriter Tên thành viên Ý nghĩa Close() Cho đóng lại các writer và giải phóng mọi nguồn lực chiếm dụng Flush() Cho xoá sạch tất cả các buffer đối với writer hiện hành NewLine Thuộc tính này dùng làm hằng sang hằng Write() Viết một hằng lên text stream không có newline constant WriteLine() Viết một hằng lên text stream có newline constant Ví dụ đọc, viết một tập tin văn bản: Ví dụ ReadWriteText trình bày cách sử dụng của lớp StreamReader và StreamWriter. Nó trình bày file được đọc vào và hiển thị Nó cũng có thể lưu file. Nó sẽ lưu bất kỳ file ở định dạng Unicode . Màn hình trình bày ReadWriteText được dùng hiển thị file CivNegotiations. Chúng ta có thể đọc được ở nhiều định dạng file khác. Chúng ta nhìn vào đoạn mã sau. Trước tiên ta thêm câu lệnh using , Từ đây bên cạnh System.IO, chúng ta sử dụng lớp StringBuilder từ System.Text namespace để xây dựng chuỗi trong textbox: using System.IO; using System.Text; Tiếp theo chúng ta thêm các trường cho lớp main form public class Form1 : System.Windows.Forms.Form { private OpenFileDialog chooseOpenFileDialog = new OpenFileDialog(); private string chosenFile; Chúng ta cũng cần thêm vài chuẩn mã Windows Forms để thực hiện điều khiển cho menu và hộp thoại: public Form1() { InitializeComponent(); menuFileOpen.Click += new EventHandler(OnFileOpen); chooseOpenFileDialog.FileOk += new CancelEventHandler(OnOpenFileDialogOK); } void OnFileOpen(object Sender, EventArgs e) { chooseOpenFileDialog.ShowDialog(); } void OnOpenFileDialogOK(object Sender, CancelEventArgs e) { chosenFile = chooseOpenFileDialog.FileName; this.Text = Path.GetFileName(chosenFile); DisplayFile(); } Từ đây chúng ta thấy mỗi khi người sử dụng nhấn OK để chọn một file trong hộp thoại, chúng ta gọi phương thức DisplayFile(), dùng để đọc file. void DisplayFile() { int nCols = 16; FileStream inStream = new FileStream(chosenFile, FileMode.Open, FileAccess.Read); long nBytesToRead = inStream.Length; if (nBytesToRead > 65536/4) nBytesToRead = 65536/4; int nLines = (int)(nBytesToRead/nCols) + 1; string [] lines = new string[nLines]; int nBytesRead = 0; for (int i=0 ; i<nLines ; i++) { StringBuilder nextLine = new StringBuilder(); nextLine.Capacity = 4*nCols; for (int j = 0 ; j<nCols ; j++) { int nextByte = inStream.ReadByte(); nBytesRead++; if (nextByte 65536) break; char nextChar = (char)nextByte; if (nextChar < 16) nextLine.Append(" x0" + string.Format("{0,1:X}", (int)nextChar)); else if (char.IsLetterOrDigit(nextChar) || char.IsPunctuation(nextChar)) nextLine.Append(" " + nextChar + " "); else nextLine.Append(" x" + string.Format("{0,2:X}", (int)nextChar)); } lines[i] = nextLine.ToString(); } inStream.Close(); this.textBoxContents.Lines = lines; } Như vậy chúng ta đã mở được file nhờ phương thức DisplayFile(). bây giờ chúng ta xử lý cách để lưu file chúng ta thêm đoạn mã SaveFile(). Bạn nhìn vào phương thức SaveFile() chúng ta viết mỗi dòng ra textbox, bằng stream StreamWriter void SaveFile() { StreamWriter sw = new StreamWriter(chosenFile, false, Encoding.Unicode); foreach (string line in textBoxContents.Lines) sw.WriteLine(line); sw.Close(); } Bây giờ ta xem xét làm thế nào file được đọc vào. Trong quá trình xử lý thực sự chúng ta không biết có bao nhiêu dòng sẽ được chứa (cũng có nghĩa là có bao nhiêu ký tự (char)13(char)10 tuần tự trong file đến khi nào kết thúc file) Chúng ta giải quyết vấn đề này bằng cách ban đầu đọc file vào trong lớp đại diện StringCollection, được nằm trong System.Collections.Specialized namespace. Lớp này được thiết kế để giữ một bộ của chuỗi có thể được mở rộng một cách linh hoạt. Nó thực thi hai phương thức : Add(), nó thêm một chuỗi vào bộ chọn lựa (collection) , và CopyTo(), nó sao chép string collection vào trong một mảng. Mỗi thành phần của đối tượng StringCollection object sẽ giữ 1 hàng của file. Bây giờ chúng ta sẽ xem xét phương thức ReadFileIntoStringCollection() . Chúng ta sử dụng StreamReader để đọc trong mỗi hàng. Khó khăn chính là cần đếm ký tự đọc để chắc chúng ta không vượt quá khả năng chứa đựng của textbox: StringCollection ReadFileIntoStringCollection() { const int MaxBytes = 65536; StreamReader sr = new StreamReader(chosenFile); StringCollection result = new StringCollection(); int nBytesRead = 0; string nextLine; while ( (nextLine = sr.ReadLine()) != null) { nBytesRead += nextLine.Length; if (nBytesRead > MaxBytes) break; result.Add(nextLine); } sr.Close(); return result; } Đến đây đoạn mã được hoàn thành. Bạn có thể tham khảo chương trình kèm theo sách ReadWriteText Tóm tắt Trong chương này đã khảo sát làm thế nào sử dụng các lớp cơ bản .NET để truy xuất Registry và file hệ thống từ mã C# . Chúng ta cũng thấy được trong cả hai trường hợp các lớp cơ bản trình bày đơn giản nhưng hiệu quả , mô hình đối tượng rất đơn giản để thực hiện hầu hết các hành động trong vùng của chúng. Đối với Registry, chúng ta tạo, chỉnh sửa, hoặc đọc các khoá, và đối với file hệ thống sao chép file, di chuyển, tạo, huỷ file và folder và đọc và viết file văn bản. Trong chương này chúng ta sẽ thử chạy đoạn code C# từ tài khoản có quyền hạn truy xuất đến bất kỳ đoạn code cần thực hiện. Tất nhiên vấn đề bảo mật là quan trọng nơi file truy xuất có liên quan. Và chúng ta sẽ khảo sát vùng bảo mật trong .NET Security. Chương 13: Làm việc với Active Directory Tổng quan 1 đặc tính chính ( có lẽ là quan trọng nhất ) được giới thiệu trong Win 2000 là Active Directory. Active Directory là 1 dịch vụ thư mục ( directory service), mà cung cấp cách lưu trữ thông tin của người dùng, tài nguyên mạng, các dịch vụ .. có cấu trúc,tập trung. Ví dụ ,Microsoft's Exchange Server 2000 dùng Active Directory lưu các thư mục chung và các mục khác Trước khi có Active Directory, Exchange Server sử dụng cách lưu trữ riêng các đối tượng của nó.Người quản trị hệ thống phải cấu hình 2 ID user cho một người dùng: 1 tài khoản user trong domain Window NT để có thể đăng nhập,và 1 user trong Exchange Directory.Điều này là cần thiết bởi vì thông tin thêm của người dùng được yêu cầu ( như địa chỉ e-mail, số điện thoại, ..) và thông tin người dùng trong domain Window NT không được mở rộng để ta đặt các thông tin đòi hỏi ở đó.Bây giờ người quản trị hệ thống chỉ cần cấu hình 1 user cho 1 người dùng trong Active Directory,thông tin của đối tượng người dùng có thể được mở rộng để phù hợp với các yêu cầu của Exchange Server.Ta cũng có thể mở rộng thông tin này. Trong chương này, ta sẽ tìm hiểu cách dùng .NET framework để truy xuất và thao tác dữ liệu trong 1 dịch vụ thư mục bằng cách dùng các lớp từ namespace System.DirectoryServices Để dùng các ví dụ trong chương này ta cần có Window 2000 Server đã cài Active Directory.Các lớp của namespace System.DirectoryServices cũng có thể được dùng trong các dịch vụ thư mục của Novell và Window NT 4 Trong chương này ta sẽ tìm hiểu các phần sau : Kiến trúc của Active Directory -các đặc tính và khái niệm cơ bản Một vài công cụ cho người quản trị Active Directory , và lợi ích của chúng trong lập trình Cách để đọc và cập nhật dữ liệu trong Active Directory Tìm kiếm các đối tượng trong Active Directory Sau khi thảo luận kiến trúc và cách lập trình trên Active Directory ta sẽ tạo 1 ứng dụng Window mà có thể đặc tả các thuộc tính và bộ lọc để tìm kiếm các đối tượng người dùng Các công cụ quản trị cho Active Directory Nhà quản trị hệ thống có nhiều công cụ để tạo dữ liệu mới ,cập nhật dữ liệu, và cấu hình Active directory: - Active Directory Users and Computers MMC snap-in dùng để tạo người dùng mới và cập nhật dữ liệu người dùng. - Active Directory Sites and Services MMC snap-in dùng để cấu hình các site trong domain và sao chép giữa các site - Active Directory Domains and Trusts MMC snap-in dùng để xây dựng các mối quan hệ tin cậy giữa các domain trong cây - ADSI Edit là trình biên tập của Active Directory, nơi đối tượng được xem và chỉnh sửa Máy tính và người dùng Active Directory - Active Directory Users and Computers snap-in là công cụ được sử dụng chính bởi nhà quản trị hệ thống để quản lý ngưòi dùng. chọn Start|Programs| AdministrativeTools| Active Directory Users and Computers: Với công cụ này ta có thể thêm người dùng mới, nhóm ,contact,máy in , thư mục chia sẻ, máy tính....hình kế tiếp ta có thể thấy các thuộc tính mà có thể được nhập cho đối tưọng user : office,số điện thoại,địa chỉ email,trang web thông tin tổ chức,... Active Directory Users and Computers cũng có thể được dùng trong các công ty lớn với hàng triệu đối tượng. không cần phải xem hết toàn bộ đối tượng ,vì ta có thể lọc để chỉ một số đối tượng được trình bày.ta cũng có thể truy vấn LDAP để tìm các đối tượng trong công ty. ADSI Edit ADSI Edit là trình biên tập của Active Directory.công cụ này không được cài tự động. trên CD Win2000 server ta tìm thư mục Supporting Tools. sau khi cài đặt ta vào Start | Programs | Windows 2000 Support Tools | Tools | ADSI Edit. ADSI Edit điều khiển tốt hơn Active Directory Users and Computers tool, với ADSI Edit mọi thứ đều có thể đuợc cấu hình, và ta cũng có thấy Schema và cấu hình . công cụ này dễ dàng sử dụng nhưng rất dễ nhập dữ liệu sai : Mở cửa sổ properties của đối tượng ta có thể xem và thay đổi mỗi thuộc tính của 1 đối tượng trong Active Directory.ta thấy các thuộc tính bắt buộc và tuỳ chọn với kiểu và giá trị: ADSI viewer Ta nên cài đặt Active Directory Browser , 1 phần của Microsoft Platform SDK.Microsoft Platform SDK không phải là 1 phần của Visual Studio .NET .ta có thể download nó từ MSDN web.sau khi cài đặt ta vào :Start | Programs | Microsoft Platform SDK | Tools | ADSI Viewer. ADSI viewer có hai mô hình . với File|New ta có thể bắt đầu 1 truy vấn hay sử dụng Object Viewer để trình bày mà cập nhật thuộc tính của đối tượng. sau khi bắt đầu Object Viewer ta có thể chỉ định 1 đường dẫn LDAP, cũng như username và password để mở đối tưọng.ví dụ : ta chỉ định : LDAP://OU=Wrox Press, DC=eichkogelstrasse, DC=local Nếu đối tượng ta chỉ định với đường dẫn và username và password đúng ta có màn hình Object Viewer nơi ta có thể xem và cập nhật thuộc tính của đối tượng và các đối tượng con của nó : Active Directory Service Interfaces ( ADSI) ADSI là 1 giao diện lập trình cho dịch vụ thư mục.ADSI định nghĩa vài giao diện COM được thực thi bởi provider ADSI. nghĩa là client có thể dùng các dịch vụ thư mục khác với cùng các giao diện lập trình . các lớp trong .NET frameWork trong namespace System.DirectoryServices tạo cách dùng các giao diện ADSI Trong hình sau ta thấy vài provider ADSI ( LDAP,WinNT,NDS) thi hành các giao diện COM như IADs và IUnknown. ASsembly System.DirectoryServices tạo cách dùng provider ADSI: Tìm kiếm các đối tượng người dùng Trong phần này ta sẽ xây dựng 1 Windows Form gọi là UserSearch.trong ứng dụng ta có thể nhập domain controller, uesrname ,password để truy nhập Active Directory. ta sẽ truy nhập vào schema của Active Directory để lấy các thuộc tính của đối tượng user. người dùng có thể nhập chuỗi tìm các đối tưọng user trong domain. ngoài ra ta cũng có thể thiết lập các thuộc tính của đối tượng user nên được trình bày. Giao diện người dùng Các bước sử dụng : 1. Nhập Username ,PasswordmDomain controller. tất cả đều tuỳ chọn . nếu không nhập domain controller thì kết nối làm việc với liên kết không server ( serverless binding).nếu không nhập username thì ngữ cảnh của người dùng hiện tại được lấy. 2. 1 nút nhấn cho phép tất cả các tên thuộc tính của đối tượng user được tải vào trong listbox listboxProperties 3. Sau khi tên thuộc tính được tải ta có thể lựa chọn các thuộc tính . selectioinmode của listbox được đặt là MultiSimple. 4. Nhập vào filter để giới hạn tìm kiếm. giá trị mặc định là (objectClass=user) 5. Bắt đầu tìm kiếm Ngữ cảnh tên Schema ( Schema Naming Context) Chương trình có 2 phương thức xử lý : đầu tiên là nút nhấn để tải các thuộc tính, thứ 2 là nút bắt đầu tìm kiếm trong domain.phần đầu ta đọc các thuộc tính trong schema để trình bày nó. Trong phương thức buttonLoActive DirectoryProperties_Click() ,SetLogonInformation() đọc username,password và hostname từ hộp thoại và lưu chúng trong các biến thành viên của lớp.sau đó phương thức SetNamingContext() đặt tên LDAP của Schema và tên LDAP của ngữ cảnh mặc định .tên Schema LDAP này được dùng để đặt các thuộc tính trong listbox : SetUserProperties(): private void buttonLoadProperties_Click(object sender, System.EventArgs e) { try { SetLogonInformation(); SetNamingContext(); SetUserProperties(schemaNamingContext); } catch (Exception ex) { MessageBox.Show("Check your inputs! " + ex.Message); } } protected void SetLogonInformation() { username = (textBoxUsername.Text == "" ? null : textBoxUsername.Text); password = (textBoxPassword.Text == "" ? null : textBoxPassword.Text); hostname = textBoxHostname.Text; if (hostname != "") hostname += "/"; }   Hổ trợ cho phương thức SetNamingContext(), ta dùng gốc của cây thư mục để lấy các thuộc tính của server, ta chỉ quan tâm đến giá trị 2 thuộc tính : schemaNamingContext và defaultNamingContext : protected string SetNamingContext() { using (DirectoryEntry de = new DirectoryEntry()) { string path = "LDAP://" + hostname + "rootDSE"; de.Username = username; de.Password = password; de.Path = path; schemaNamingContext = de.Properties["schemaNamingContext"][0].ToString(); defaultNamingContext = de.Properties["defaultNamingContext"][0].ToString(); } }   Lấy các tên thuộc tính của lớp User Ta có tên LDAP để truy nhập schema . ta có thể dùng tên này để truy nhập thư mục và đọc các thuộc tính. ta không chỉ quan tâm đến lớp user mà còn các lớp cơ sở khác như : Organizational-Person, Person, and Top. trong chương trình này tên của các lớp cơ sở là hard-coded ( mã chỉ định sẵn ) . nếu muốn đọc ta dùng thuộc tính subclassof .GetSchemaProperties() trả về 1 mảng chuỗi với tên tất cả thuộc tính của kiểu đối tượng đặc tả .tất cả tên thuộc tính được thu thập vào thuộc tính StringCollection : protected void SetUserProperties(string schemaNamingContext) { StringCollection properties = new StringCollection(); string[] data = GetSchemaProperties(schemaNamingContext, "User"); properties.AddRange(GetSchemaProperties(schemaNamingContext, "Organizational-Person")); properties.AddRange(GetSchemaProperties(schemaNamingContext, "Person")); properties.AddRange(GetSchemaProperties(schemaNamingContext, "Top")); listBoxProperties.Items.Clear(); foreach (string s in properties) { listBoxProperties.Items.Add(s); } }   Trong GetSchemaProperties() ta truy nhập Active Directory lại, lần này rootDSE không được dùng.thuộc tính SystemMayContain giữ 1 tập tất cả các thuộc tính mà được cho phép trong lớp objectType: protected string[] GetSchemaProperties(string schemaNamingContext, string objectType) { string[] data; using (DirectoryEntry de = new DirectoryEntry()) { de.Username = username; de.Password = password; de.Path = "LDAP://" + hostname + "CN=" + objectType + "," + schemaNamingContext; DS.PropertyCollection properties = de.Properties; DS.PropertyValueCollection values = properties["systemMayContain"]; data = new String[values.Count]; values.CopyTo(data, 0); } return data; }   Tìm kiếm các đối tượng user Nút tìm kiếm gọi pương thức FillReult(): private void buttonSearch_Click(object sender, System.EventArgs e) { try { FillResult(); } catch (Exception ex) { MessageBox.Show("Check your input: " + ex.Message); } } Ta thiết lập trong FillResult như sau : SearhcScope thiết đặt là subtree,Filter là chuỗi lấy từ textbox và các thuộc tính được tải vào cache được chọn dựa vào listbox: protected void FillResult() { using (DirectoryEntry root = new DirectoryEntry()) { root.Username = username; root.Password = password; root.Path = "LDAP://" + hostname + defaultNamingContext; using (DirectorySearcher searcher = new DirectorySearcher()) { searcher.SearchRoot = root; searcher.SearchScope = SearchScope.Subtree; searcher.Filter = textBoxFilter.Text; searcher.PropertiesToLoad.AddRange(GetProperties()); SearchResultCollection results = searcher.FindAll(); StringBuilder summary = new StringBuilder(); foreach (SearchResult result in results) { foreach (string propName in result.Properties.PropertyNames) { foreach (string s in result.Properties[propName]) { summary.Append(" " + propName + ": " + s + "\r\n"); } } summary.Append("\r\n"); } textBoxResults.Text = summary.ToString(); } } } Kết quả cho ta tất cả các đối tượng được lọc : Code for Download : UserSearch Tóm tắt Trong chương này ta đả xem xét kiến trúc của Active Directory: Các khái niệmquan trọng như domain,tree,forest.Ta có thể truy xuất thông tin trong các tổ chức hoàn chỉnh ( complete enterprise).Viết các ứng dụng mà truy xuất Active Directory,ta phải nhậ nthức rằng dữ liệu ta đọc không thể đưọc cập nhật bởi replication latency. Các lớp trong namespace System.DirectoryServices cho chúng ta các cách dễ dàng để truy xuất Active Directory bằng cách gói các provider ADSI. lớp DirecoryEntry có thể đọc và viết các đối tượng 1 cách trực tiếp vào nơi lưu trữ dữ liệu Với lớp DirectorySearcher ta có thi hành các tìm kiếm phức tạp và định nghĩa các bộ lọc,timeouts,thuộc tính để tải và phạm vi.Dùng Global Catalog ta có thể tăng tốc độ tìm kiếm các đối tượng trong các tổ chức hoàn chỉnh,bởi vì nó lưu các phiên bản chỉ đọc của tất cả các đối tượng trong forest

Các file đính kèm theo tài liệu này:

  • docKỹ thuật Lập trình C#.doc