You are on page 1of 8

The full version number is comprised of these four parts, making up an 8-byte num-

ber representing the file’s version number.


The CompareFileVersions method first compares the FileMajorPart version informa-
tion of the two files. If these are equal, the FileMinorPart version information of the
two files is compared. This continues through the FileBuildPart and finally the
FilePrivatePart version information values. If all four parts are equal, the files are
considered to have the same version number. If either file is found to have a higher
number than the other file, it is considered to be the latest version.

See Also
The “FileVersionInfo Class” topic in the MSDN documentation.

12.14 Querying Information for All Drives on a System


Problem
Your application needs to know if a drive (HDD, CD drive, DVD drive, etc.) is avail-
able and ready to be written to and/or read from. Additionally, it would be nice to
know if you have enough available free space on the drive to write information to.

Solution
Use the various properties in the DriveInfo class as shown here:
public static void DisplayAllDriveInfo( )
{
foreach (DriveInfo drive in DriveInfo.GetDrives( ))
{
if (drive.IsReady)
{
Console.WriteLine("Drive " + drive.Name + " is ready.");
Console.WriteLine("AvailableFreeSpace: " + drive.AvailableFreeSpace);
Console.WriteLine("DriveFormat: " + drive.DriveFormat);
Console.WriteLine("DriveType: " + drive.DriveType);
Console.WriteLine("Name: " + drive.Name);
Console.WriteLine("RootDirectory.FullName: " +
drive.RootDirectory.FullName);
Console.WriteLine("TotalFreeSpace: " + drive.TotalFreeSpace);
Console.WriteLine("TotalSize: " + drive.TotalSize);
Console.WriteLine("VolumeLabel: " + drive.VolumeLabel);
}
else
{
Console.WriteLine("Drive " + drive.Name + " is not ready.");
}
}
}

Querying Information for All Drives on a System | 479


rijndael.KeySize = 256;
rijndael.GenerateKey( );
rijndael.GenerateIV( );
// Save off the key and IV for later decryption.
byte[] key = rijndael.Key;
byte[] IV = rijndael.IV;

// Create encryptor and stream objects.


using (ICryptoTransform transform =
rijndael.CreateEncryptor(rijndael.Key, rijndael.IV))
{
using (CryptoStream cryptoStream = new
CryptoStream(memStream, transform,
CryptoStreamMode.Write))
{
// Write encrypted data to the MemoryStream.
cryptoStream.Write(originalStrAsBytes, 0,
originalStrAsBytes.Length);
cryptoStream.FlushFinalBlock( );
}
}
}
}
}

Discussion
To make sure your data is safe, you need to close the MemoryStream and CryptoStream
objects as soon as possible, as well as calling Dispose on the ICryptoTransform imple-
mentation to clear out any resources used in this encryption. The using statement
makes this process much easier, makes your code easier to read, and leads to fewer
programming mistakes.

See Also
The “SymmetricAlgorithm.Clear Method” and “AsymmetricAlgorithm.Clear
Method” topics in the MSDN documentation.

17.5 Verifying That a String Remains Uncorrupted


Following Transmission
Problem
You have some text that will be sent across a network to another machine for pro-
cessing. You need to verify that this message has not been modified in transit.

672 | Chapter 17: Security


Chapter 11, Data Structures and Algorithms
This chapter ventures a bit outside of what is provided for you in the .NET
Framework Class Library and implements certain data structures and algo-
rithms that are not in the FCL, or possibly are not in existence exactly the way
you would like to use them, but are ones that you have used to solve problems
before. Items such as queues, maps, trees, and hashes are examined.
Chapter 12, Filesystem I/O
This chapter deals with file system interactions in four distinct ways. The first
way is to look at typical file interactions; the second way looks at directory- or
folder-based interactions; the third way deals with paths and temporary files;
and the fourth way deals with advanced file system I/O topics.
Chapter 13, Reflection
This chapter shows ways to use the built-in assembly inspection system pro-
vided by the .NET Framework to determine what types, interfaces, and meth-
ods are implemented within an assembly and how to access them in a late-
bound fashion.
Chapter 14, Web
This chapter covers accessing a web site and its content as well as programmati-
cally determining web site configuration. Among the recipes in this chapter are
using the web browser control and setting up caching triggers to refresh cached
data when a database table changes.
Chapter 15, XML
If you use .NET, it is likely that you will be dealing with XML to one degree or
another; in this chapter, we explore some of the uses for XML and how to
program against it using LINQ to XML, the XmlReader/XmlWriter, and Xml-
Document. There are examples using both XPath and XSLT, and topics such as
the validation of XML and transformation of XML to HTML are shown.
Chapter 16, Networking
This chapter explores the connectivity options provided by the .NET Frame-
work and how to programmatically access network resources. Recipes for using
TCP/IP directly, named pipes for communication, building your own port scan-
ner, and more are covered here.
Chapter 17, Security
There are many ways to write secure code and protect data using the .NET
Framework, and in this chapter, we explore areas such as controlling access to
types, encryption and decryption, securely storing data, and using program-
matic and declarative security.
Chapter 18, Threading and Synchronization
This chapter addresses the subject of using multiple threads of execution in a .NET
program and issues such as how to implement threading in your application, pro-
tecting resources from and allowing safe concurrent access, storing per-thread data,
and how to use the synchronization primitives in .NET to write thread-safe code.

Preface | xxi

This is the Title of the Book, eMatter Edition


Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
The CompressionType enumeration is defined as follows:
public enum CompressionType
{
Deflate,
GZip
}

Discussion
The CompressFile method accepts a path to the source file to compress, a path to the
destination of the compressed file, and a CompressionType enumeration value indicat-
ing which type of compression algorithm to use (Deflate or GZip). This method pro-
duces a file containing the compressed data.
The DecompressFile method accepts a path to the source compressed file to decom-
press, a path to the destination of the decompressed file, and a CompressionType enu-
meration value indicating which type of decompression algorithm to use (Deflate or
GZip).
The TestCompressNewFile method shown in Example 12-6 exercises the CompressFile
and DecompressFile methods defined in the Solution section of this recipe.

Example 12-6. Using the CompressFile and DecompressFile methods


public static void TestCompressNewFile( )
{
byte[] data = new byte[10000000];
for (int i = 0; i < 10000000; i++)
data[i] = (byte)i;

FileStream fs =
new FileStream(@"C:\NewNormalFile.txt",
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
using(fs)
{
fs.Write(data,0,data.Length);
}

CompressFile(@"C:\NewNormalFile.txt", @"C:\NewCompressedFile.txt",
CompressionType.Deflate);

DecompressFile(@"C:\NewCompressedFile.txt", @"C:\NewDecompressedFile.txt",
CompressionType.Deflate);

CompressFile(@"C:\NewNormalFile.txt", @"C:\NewGZCompressedFile.txt",
CompressionType.GZip);

DecompressFile(@"C:\NewGZCompressedFile.txt", @"C:\NewGZDecompressedFile.txt",
CompressionType.GZip);

486 | Chapter 12: Filesystem I/O


Example 4-2. FixedSizeCollection<T>: a generic .NET type (continued)
#endregion // Properties

/// <summary>
/// ToString override to provide class detail
/// </summary>
/// <returns>formatted string with class details</returns>
public override string ToString( )
{
return "There are " + FixedSizeCollection<T>.InstanceCount.ToString( ) +
" instances of " + this.GetType( ).ToString( ) +
" and this instance contains " + this.ItemCount + " items...";
}
}

Things start to get a little different with FixedSizeCollection<T> when you look at
the Items array property implementation. The Items array is declared as:
private T[] Items { get; set; }

instead of:
private object[] Items { get; set; }

The Items array property uses the type parameter of the generic class (<T>) to deter-
mine what type of items are allowed. FixedSizeCollection uses object for the Items
array property type, which allows any type to be stored in the array of items (since all
types are convertible to object), while FixedSizeCollection<T> provides type safety
by allowing the type parameter to dictate what types of objects are permitted. Notice
also that the properties have no associated private backing field declared for storing
the array. This is an example of using the new Automatically Implemented Proper-
ties in C# 3.0. Under the covers, the C# compiler is creating a storage element of the
type of the property, but you don’t have to write the code for the property storage
anymore if you don’t have specific code that has to execute when accessing the prop-
erties. To make the property read-only, simply mark the set; declaration private.
The next difference is visible in the method declarations of AddItem and GetItem.
AddItem now takes a parameter of type T, whereas in FixedSizeCollection, it took a
parameter of type object. GetItem now returns a value of type T, whereas in
FixedSizeCollection, it returned a value of type object. These changes allow the
methods in FixedSizeCollection<T> to use the instantiated type to store and retrieve
the items in the array, instead of having to allow any object to be stored as in
FixedSizeCollection:
/// <summary>
/// Add an item to the class whose type
/// is determined by the instantiating type
/// </summary>
/// <param name="item">item to add</param>
/// <returns>the zero-based index of the item added</returns>
public int AddItem(T item)

142 | Chapter 4: Generics


Discussion
The CDATA node allows you to represent the items in the text section as character
data, not as escaped XML, for ease of entry. Normally, these characters would need
to be in their escaped format (&lt; for < and so on), but the CDATA section allows you
to enter them as regular text.
When the CDATA tag is used in conjunction with the InnerXml property of the
XmlElement class, you can submit characters that would normally need to be escaped
first. The XmlElement class also has an InnerText property that will automatically
escape any markup found in the string assigned. This allows you to add these charac-
ters without having to worry about them.

See Also
The “XElement Class,” “XCData Class,” “XmlDocument Class,” “XmlWriter Class,”
“XmlElement Class,” and “CDATA Sections” topics in the MSDN documentation.

15.8 Transforming XML


Problem
You have a raw XML document that you need to convert into a more readable for-
mat. For example, you have personnel data that is stored as an XML document, and
you need to display it on a web page or place it in a comma-delimited text file for leg-
acy system integration. Unfortunately, not everyone wants to sort through reams of
XML all day; they would rather read the data as a formatted list or within a grid with
defined columns and rows. You need a method of transforming the XML data into a
more readable form as well as into the comma-delimited format.

Solution
The solution for this is to use LINQ to XML to perform a transformation in C#. In
the example code, you transform some personnel data from a fictitious business
stored in Personnel.xml. The data is first transformed into HTML, and then into
comma-delimited format:
// LINQ way
XElement personnelData = XElement.Load(@"..\..\Personnel.xml");
// Create HTML
XElement personnelHtml =
new XElement("html",
new XElement("head"),
new XElement("body",
new XAttribute("title","Personnel"),
new XElement("p",
new XElement("table",
new XAttribute("border","1"),

572 | Chapter 15: XML


Console.WriteLine("Convert.ToInt32(base10, 10) = " +
Convert.ToInt32(base10, 10));

Console.WriteLine("Convert.ToInt32(base16, 16) = " +


Convert.ToInt32(base16, 16));

This code produces the following output:


Convert.ToInt32(base2, 2) = 3
Convert.ToInt32(base8, 8) = 15
Convert.ToInt32(base10, 10) = 110
Convert.ToInt32(base16, 16) = 4607

Discussion
The static Convert.ToInt32 method has an overload that takes a string containing a
number and an integer defining the base of this number. This method then converts
the numeric string into an integer, Console.WriteLine, and then converts the num-
ber to base10 and displays it.
The other static methods of the Convert class, such as ToByte, ToInt64, and ToInt16,
also have this same overload, which accepts a number as a string and the base in
which this number is expressed. Unfortunately, these methods convert from a string
value expressed in base2, base8, base10, and base16 only. They do not allow for con-
verting a value to a string expressed in any other base types than base10. However,
the ToString methods on the various numeric types do allow for this conversion.

See Also
The “Convert Class” and “Converting with System.Convert” topics in the MSDN
documentation.

20.4 Determining Whether a String Is a Valid Number


Problem
You have a string that possibly contains a numeric value. You need to know whether
this string contains a valid number.

Solution
Use the static TryParse method of any of the numeric types. For example, to deter-
mine whether a string contains a double, use the following method:
string str = "12.5";
double result = 0;
if(double.TryParse(str,
System.Globalization.NumberStyles.Float,
System.Globalization.NumberFormatInfo.CurrentInfo,
out result))

798 | Chapter 20: Numbers and Enumerations


System.Net.TcpClient and connects to the server by calling the TcpClient.Connect
method. Connect targets the server using an IPEndPoint built from the address and
port that you passed to the MyTcpClient constructor.
MyTcpClient.ConnectToServer then gets the bytes for the string using the Encoding.
ASCII.GetBytes method. Once it has the bytes to send, it gets the NetworkStream from
the underlying System.Net.TcpClient by calling its GetStream method and then sends
the message using the TcpClient.Write method.
In order to receive the response from the server, the blocking TcpClient.Read method
is called. Once Read returns, the bytes are decoded to get the string that contains the
response from the server. The connections are then closed and the client ends.

See Also
The “TcpClient Class,” “NetworkStream Class,” and “Encoding.ASCII Property”
topics in the MSDN documentation.

16.3 Simulating Form Execution


Problem
You need to send a collection of name-value pairs to simulate a form being executed
on a browser to a location identified by a URL.

Solution
Use the System.Net.WebClient class to send a set of name-value pairs to the web
server using the UploadValues method. This class enables you to masquerade as the
browser executing a form by setting up the name-value pairs with the input data.
The input field ID is the name, and the value to use in the field is the value:
using System;
using System.Net;
using System.Text;
using System.Collections.Specialized;

// In order to use this, you need to run the CSCBWeb project first.
Uri uri = new Uri("http://localhost:7472/CSCBWeb/WebForm1.aspx");
WebClient client = new WebClient( );

// Create a series of name/value pairs to send


// Add necessary parameter/value pairs to the name/value container.
NameValueCollection collection = new NameValueCollection( )
{ {"Item", "WebParts"},
{"Identity", "foo@bar.com"},
{"Quantity", "5"} };

Simulating Form Execution | 615

You might also like