Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

Choosing the right design pattern for your ASP.NET Web application can help you achieve the separation of concerns between your presentation layer and the layers beneath it.

Dino Esposito

MSDN Magazine December 2008

...

Read more!

Here we introduce Microsoft Code Name “Geneva,” the new framework for building claims-based applications and services, and federated security scenarios.

Michele Leroux Bustamante

MSDN Magazine December 2008

...

Read more!

John Papa tackles questions about calling services from Silverlight 2 applications.

John Papa

MSDN Magazine November 2008

...

Read more!

Understanding the ACLs that govern permissions and rights before an operation is allowed to proceed is critical to enhancing security.

John R. Michener

MSDN Magazine November 2008

...

Read more!

Bryan Sullivan discusses the new SDL for Web applications and Agile projects with more compressed release cycles.

Bryan Sullivan

MSDN Magazine November 2008

...

Read more!

Also by this Author

This month Inbar Gazit shows readers how to get the most out of the System.Collections namespace.

Inbar Gazit

MSDN Magazine August 2007

...

Read more!

Strong name signatures (and signing in general) are a key facet of Microsoft® . NET Framework security. But regardless of how well designed . NET signatures may be, they won’t offer the maximum benefit if you don’t know how to use them properly.

Mike Downen

MSDN Magazine July 2006

...

Read more!

Unlike role-based security measures, code access security is not based on user identity. Instead, it is based on the identity of the code that is running, including information such as where the code came from. Here Mike Downen discusses the role of code access security (CAS) in .NET and outlines some key new features and changes in CAS for the .NET Framework 2.0.

Mike Downen

MSDN Magazine November 2005

...

Read more!

You can sign any kind of data using XML Signature, including part of an XML document, other XML documents, or other data of any format. However, in practice, XML signatures are most frequently used to sign other data represented in XML. In this article, the authors discuss the new standard and how you can benefit from it in your apps.

Mike Downen and Shawn Farkas

MSDN Magazine November 2004

...

Read more!

Popular Articles

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

When incorporating the ASP.NET DataGrid control into your Web apps, common operations such as paging, sorting, editing, and deleting data require more effort than you might like to expend. But all that is about to change. The GridView control--the successor to the DataGrid-- extends the DataGrid's functionality it in a number of ways. First, it fully supports data source components and can automatically handle data operations, such as paging, sorting, and editing, as long as its bound data source object supports these capabilities. In addition, ...

Read more!

The MVP pattern helps you separate your logic and keep your UI layer free of clutter. This month learn how.

Jean-Paul Boodhoo

MSDN Magazine August 2006

...

Read more!

Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

Josh Smith

MSDN Magazine July 2008

...

Read more!

A Sidebar gadget is a powerful little too that's surprisingly easy to create. Get in on the fun with Donavon West.

Donavon West

MSDN Magazine August 2007

...

Read more!

Our Blog

We're currently in the process of stepping back and taking a critical look at our Web site to see how you all are using it - and how we can redesign parts of it (big or small) to make that experience better.  We are continuously receiving your feedback on existing frustrations and we are working hard to remedy those (as a general fyi, most of the frustrations have to do with navigation).  However, in order to get a sense of whether we need to look at some of the more fundamental ...

Read more!

C# developers can use the Visual Studio Tools for the Office System (VSTO) Power Tools Office interop API extensions to streamline Office application development. The extensions provide a thin, strongly typed layer over the loosely typed Office object models.

In the December 2008 issue of MSDN Magazine, Andrew Whitechapel, Phillip Hoff, and Vladimir Morozov walk you through developing ...

Read more!

Earlier this year MSDN Magazine embarked on a collaborative project with Behind the Code, an interview program airing on MSDN Channel 9. In this program, Robert Hess interviews prominent developers at Microsoft, and those developers also write a column for { End Bracket } in MSDN Magazine. In the newest interview, Richard Ward talks about working on the core infrastructure components of future versions of Windows, as well as ...

Read more!

A team project is simply a bucket that stores and partitions all of the artifacts you track and use within a Team Foundation Server (TFS) project.

In the December 2008 issue of MSDN Magazine, Brian A. Randell explains how you can use and customize the MSF Agile and MFS CMMI process templates to get the most out of them for your ...

Read more!

Silverlight and SharePoint provide a simple, yet powerful, infrastructure for building intranet and extranet applications with sophisticated user interface designs and interactions.

In the November 2008 issue of MSDN Magazine, Steve Fox and Paul Stubbs demonstrate how to build a SharePoint Web Part as a wrapper for a Silverlight application.

...

Read more!

CLR Inside Out
New Library Classes in "Orcas"
Mike Downen and Inbar Gazit and Justin Van Patten

For the next version of the Microsoft .NET Framework (which will ship with the next release of Visual Studio® currently code-named "Orcas"), its assemblies have been divided into two groups, internally referred to as "red bits" and "green bits." The red bits include all the libraries that shipped before as part of the .NET Framework 2.0 and 3.0 (such as mscorlib.dll and system.dll). To maintain a high assurance of backward compatibility for Visual Studio "Orcas," changes in the red bits have been greatly limited.
The green bits assemblies are the brand new libraries with additional classes that work on top of the red bits assemblies. Most of the classes listed in this column are in the green bits assemblies (such as system.core.dll), with a few involving limited changes in the red bits assemblies. For more background information, check out Soma Somasegar's blog and Jason Zander's blog.
The classes described in this column are available as part of the January 2007 Visual Studio "Orcas" Community Technology Preview (CTP). The CLR's contributions to the new libraries include:
  • A new add-in hosting model, which was discussed in the last two editions of CLR Inside Out
  • Support for the Suite B set of cryptographic algorithms, as specified by the National Security Agency (NSA)
  • Support for big integers
  • A high-performance set collection
  • Support for anonymous and named pipes
  • Improved time zone support
  • Lightweight reader/writer lock classes
  • Better integration with Event Tracing for Windows® (ETW), including ETW provider and ETW trace listener APIs
In this column, we'll discuss the new Suite B cryptography features, big integer support, the set class, and the pipes capabilities.

Suite B Support
One of our major goals for Visual Studio "Orcas" was to add support for the Suite B set of cryptographic algorithms. In order to support Suite B, a platform has to support:
  • The Advanced Encryption Standard (AES) with key sizes of 128 and 256 bits for encryption
  • The Secure Hash Algorithm (SHA-256 and SHA-384) for hashing
  • The Elliptic Curve Digital Signature Algorithm (ECDSA) using curves of 256-bit and 384-bit prime moduli for signing
  • Elliptic Curve Diffie-Hellman (ECDH) using curves of 256 and 384-bit prime moduli for key exchange/secret agreement
More information about Suite B is available in the overview published by the NSA at www.nsa.gov/ia/industry/crypto_suite_b.cfm.
In addition to these criteria, we also wanted to support Federal Information Processing Standard (FIPS) certified implementations of these algorithms. We've had support for AES (via our RijndaelManaged class) and SHA-256 and SHA-384 (using our SHA256Managed and SHA384Managed classes) since version 1.0 of the .NET Framework, but our implementations were not FIPS-certified.
As a first step, we added managed code wrappers for the FIPS-certified AES, SHA-256, and SHA-384 implementations in Windows. In Visual Studio "Orcas," these appear as the new AesCryptoServiceProvider, SHA256CryptoServiceProvider, and SHA384CryptoServiceProvider classes. All of these are located in the System.Security.Cryptography namespace.
These algorithms are available on all platforms on which the underlying Windows Crypto Service Providers are available-Windows XP and later for AES, and Windows Server® 2003 and later for the SHA algorithms. They generally work exactly like their managed equivalents, so developers should typically be able to swap them in without noticing any changes in behavior. The one difference is that, per the AES specification, AesCryptoServiceProvider only supports a fixed block size of 128 bits.
The CngKey Class
To support our new CNG-based managed cryptography classes, we've added a CngKey class to abstract the storage and usage of CNG keys. CNG keys work similarly to key containers in today's Crypto API (CAPI)—they allow you to store a key pair or a public key securely and refer to it using a simple string name. You can use CngKey objects when working with the ECDsaCng and ECDiffieHellmanCng classes.
You can also use the CngKey class directly to perform many operations, including opening, creating, deleting, and exporting keys. If we don't have a managed API for the operation you want, you can get to the underlying key handle to use when calling Win32® APIs directly.


Elliptic Curve Cryptography
Then we added classes for ECDSA and ECDH. These classes wrap the new Crypto Next Generation (CNG) implementations of these algorithms in Windows Vista™. (For more details on how we support CNG classes, see the sidebar "The CngKey Class.") Elliptic curve cryptography is asymmetric, meaning it uses a public and private key pair for operations, similar to RSA. But elliptic curve algorithms are generally more efficient computationally than traditional public key cryptography algorithms, especially as key sizes grow larger. In fact, the NSA recommends an RSA key size of 15,360 bits to protect a symmetric key of 256 bits, whereas it recommends just a 521-bit elliptic curve key to protect the same 256-bit symmetric key.
More information on the benefits of elliptic curve cryptography is available in the NSA's article "The Case for Elliptic Key Cryptography".

ECDSA
ECDSA works like most signing algorithms: you sign with a private key and verify with a public key. The new ECDsaCng class contains our implementation of ECDSA and follows the same pattern as other managed cryptography classes. Say you want to sign some data, assuming your key pair is stored in a CNG key named MyKey:
// Returns the signature
byte[] SignMyData (byte[] data)
{
   ECDsaCng signingAlg = new ECDsaCng(CngKey.Open("MyKey"));
   return signingAlg.SignData(data);
}
Now, say you want to verify a signature from Jane and her public key is stored in a CNG key named JanesKey. You would do the following:
// Returns whether or not the signature could be verified
bool VerifyJanesSignature(byte[] data, byte[] signature)
{
   ECDsaCng signingAlg = new ECDsaCng(CngKey.Open("JanesKey"));
   return signingAlg.VerifyData(data, signature);
}
The ECDsaCng class also lets you set different options when signing or verifying, mostly through properties on the class. For example, by default the ECDsaCng class uses the SHA-256 hashing algorithm during signing and verification. If you want to use a different algorithm, you simply change the HashAlgorithm property before signing. Let's say you choose to use SHA-512. The signing example for MyKey would now look like this:
// Returns the signature
byte[] SignMyData (byte[] data)
{
   ECDsaCng signingAlg = new ECDsaCng(CngKey.Open("MyKey"));
   signingAlg.HashAlgorithm = CngAlgorithm.Sha512;
   return signingAlg.SignData(data);
}
And the verification example for JanesKey would be this:
// Returns whether or not the signature could be verified
bool VerifyJanesSignature(byte[] data, byte[] signature)
{
   ECDsaCng signingAlg = new ECDsaCng(CngKey.Open("JanesKey"));
   signingAlg.HashAlgorithm = CngAlgorithm.Sha512;
   return signingAlg.VerifyData(data, signature);
}

ECDH
ECDH is a key exchange algorithm, sometimes referred to as a secret agreement algorithm. This algorithm is used to derive a secret key-often used for encryption or decryption with a symmetric algorithm-by exchanging a public key with another party. For example, say two users, Alice and Bob, want to derive a secret key. They both already have an elliptic curve key pair (both public and private keys). In order to derive a secret key using ECDH, they would perform the following steps:
  1. Alice sends her public key to Bob. He must be sure he's really getting the key from Alice and that the key has not been modified, but the key does not have to be sent confidentially.
  2. Bob sends his public key to Alice. Likewise, Alice must be absolutely sure that she's really getting the key from Bob and that the key has not been modified, but again the key does not have to be sent confidentially.
  3. Alice and Bob can now generate the same secret value, given that they each have the other party's public key and their own key pair. This secret value can then be used to generate a secret key for a symmetric algorithm.
The code for this is pretty simple. The following example generates a 256-bit key for Alice, assuming that her key pair is stored in a CNG key named MyKey:
// Returns a 256 bit secret key that is shared with the other party
bool Generate256BitKey(string otherParty)
{
   ECDiffieHellmanCng keyExchAlg =
      new ECDiffieHellmanCng(CngKey.Open("MyKey"));
   byte [] myPublicKey = keyExchAlg.PublicKey.ToByteArray();
   ... // send myPublicKey to other party
   byte[] otherPartysPublicKeyBytes = ...; // get other party's key
   ECDiffieHellmanCngPublicKey otherPartysPublicKey =
      ECDiffieHellmanCngPublicKey.FromByteArray(
         otherPartysPublicKeyBytes, CngKeyBlobFormat.EccPublicBlob);
   return keyExchAlg.DeriveKeyMaterial(otherPartysPublicKey);
}
Alice now has a 256-bit symmetric key that can be used with the other party (Bob) to encrypt and communicate confidential data. I'll stress again, however, that it's important to make sure you're really getting the genuine public key from the other party in a situation like the example above, not from an imposter. This typically requires some form of authentication.
Like the ECDsaCng class, the ECDiffieHellmanCng class used here can be customized through properties. For example, you can use different key derivation functions specifying all of the parameters for the key derivation functions using these properties.

Big Integer Support
Support for integers that can represent very large numbers is another customer request that we have implemented in the next version of the .NET Framework. Have you ever needed a really huge number, one that is so big that it just couldn't fit into any other base-type in the .NET Framework? Now you can use the new BigInteger type, which allows you to use integers of any arbitrary size, up to the limits of available memory. To begin, let's take a look at some scenarios in which you might need to use a really big number.
Astronomical calculations that involve distances in space require the ability to calculate extremely large numbers. Astronomers often calculate the distance in light-years in order to avoid using really big numbers. That's because a light-year is about 5,878,625,373,183.61 miles (or 9,460,730,472,580.8 kilometers) and so the actual number of miles between stars (not to mention feet or inches) is larger than what can be represented with 64 bits.
Big integers are also used in statistics and number theory. While not all mathematicians are necessarily working with integers of this size, consider the Law of Truly Large Numbers (which states that with a sample size large enough, any outrageous thing is likely to happen) and some of the writings by John Edensor Littlewood.
Furthermore, many cryptographic algorithms require the use of very large prime numbers. These numbers are much larger than can be represented by base types today.
The new BigInteger class is in the new System.Numeric namespace. It supports most of the operators you'd expect of a standard numeric type, such as addition (+), subtraction (-), and multiplication (*). The sample code in Figure 1 shows how to do a factorial computation using the BigInteger class. Figure 2 shows an example of the output if you enter 1000.
402387260077093773543702433923003985719374864210714632543799910
429938512398629020592044208486969404800479988610197196058631666
872994808558901323829669944590997424504087073759918823627727188
732519779505950995276120874975462497043601418278094646496291056
393887437886487337119181045825783647849977012476632889835955735
432513185323958463075557409114262417474349347553428646576611667
797396668820291207379143853719588249808126867838374559731746136
085379534524221586593201928090878297308431392844403281231558611
036976801357304216168747609675871348312025478589320767169132448
426236131412508780208000261683151027341827977704784635868170164
365024153691398281264810213092761244896359928705114964975419909
342221566832572080821333186116811553615836546984046708975602900
950537616475847728421889679646244945160765353408198901385442487
984959953319101723355556602139450399736280750137837615307127761
926849034352625200015888535147331611702103968175921510907788019
393178114194545257223865541461062892187960223838971476088506276
862967146674697562911234082439208160153780889893964518263243671
616762179168909779911903754031274622289988005195444414282012187
361745992642956581746628302955570299024324153181617210465832036
786906117260158783520751516284225540265170483304226143974286933
061690897968482590125458327168226458066526769958652682272807075
781391858178889652208164348344825993266043367660176999612831860
788386150279465955131156552036093988180612138558600301435694527
224206344631797460594682573103790084024432438465657245014402821
885252470935190620929023136493273497565513958720559654228749774
011413346962715422845862377387538230483865688976461927383814900
140767310446640259899490222221765904339901886018566526485061799
702356193897017860040811889729918311021171229845901641921068884
387121855646124960798722908519296819372388642614839657382291123
125024186649353143970137428531926649875337218940694281434118520
158014123344828015051399694290153483077644569099073152433278288
269864602789864321139083506217095002597389863554277196742822248
757586765752344220207573630569498825087968928162753848863396909
959826280956121450994871701244516461260379029309120889086942028
510640182154399457156805941872748998094254742173582401063677404
595741785160829230135358081840096996372524230560855903700624271
243416909004153690105933983835777939410970027753472000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000


using System.Numeric;

static BigInteger Factorial(BigInteger x)
{
    BigInteger result = 1;
    for (BigInteger i = 2; i <= x; i++)
        result *= i;
    return result;
}

static void Main(string[] args)
{
   BigInteger x = BigInteger.Parse(Console.ReadLine());
   Console.WriteLine(Factorial(x).ToString());
}

BigInteger supports many other mathematical operations through static methods on the class. These include:
  • Abs (returns the absolute value for a given BigInteger)
  • Compare (compares two BigIntegers)
  • Divide (returns the quotient of two BigIntegers)
  • DivRem (returns both the quotient and the remainder of two BigIntegers)
  • Equals (returns true if two BigIntegers have the same value)
  • GreatestCommonDivisor (returns the maximum number that is a divisor of both BigIntegers)
  • ModPow (returns one BigInteger raised to the power of another BigInteger modulo a third; the exponent cannot be negative)
  • Pow (returns one BigInteger raised to the power of another; the exponent cannot be negative)
  • Remainder (returns the remainder of dividing one BigInteger by another)
We will be posting more information on using and extending the BigInteger class on the BCL Team's blog at blogs.msdn.com/bclteam.
We should note that there are currently some design trade-offs in BigInteger. It was very important to get this new numeric type into the .NET Framework for Visual Studio "Orcas." Moreover, it was important that this new base-type be available early enough for other green bits features to make use of it. So we decided for this release not to fully support all the printing, formatting, and parsing that the other numeric types support. Thus, only the decimal (D), general (G), and hexadecimal (X) formats are supported.
The BigInteger class is an example of a new base type that we expect many other library types to consume for specialized applications. The next type we'll cover is a new collection that we added due to popular demand: a set class.

High-Performance Sets
The new HashSet class is a high-performance generic collection in the System.Collections.Generic namespace. It is an unordered collection that contains unique elements. HashSet implements all the standard collection methods (such as Add, Remove, and Contains) and provides several set operations (including union, intersection, and symmetric difference).
The following sample code demonstrates the use of HashSet with integers:
HashSet<int> set1 = new 
    HashSet<int>();
set1.Add(1);
set1.Add(3);
set1.Add(5);
set1.Add(3); // set1 already contains 3; it isn't added twice
// set1 contains 1,3,5

HashSet<int> set2 = new HashSet<int>(new int[] { 2, 4, 6 });
// set2 contains 2,4,6

set2.UnionWith(set1);
// set2 contains 1,2,3,4,5,6
Notice how after adding four items (1, 3, 5, and 3), set1 ends up containing only three elements (1, 3, and 5). This behavior is by design. HashSet contains only unique elements. Once an item has been added to the set, subsequent attempts to add the same item will not succeed. The Add method actually returns a Boolean value indicating whether or not the item was successfully added to the set. The example above could have been rewritten as follows:
HashSet<int> set1 = new HashSet<int>();
bool added = set1.Add(1); // added is true
added = set1.Add(3); // added is true
added = set1.Add(5); // added is true
added = set1.Add(3); // added is false
// set1 contains 1,3,5
In the first example, set2 is initialized by passing in an array of ints ({ 2, 4, 6}) to the HashSet constructor, which takes a generic IEnumerable as a parameter. If there are duplicate elements in the IEnumerable, they are ignored when initializing the HashSet. For example, if set2 had been initialized with an array containing 2, 4, 2, and 6, the set would still end up containing only three elements (2, 4, and 6) since duplicates are ignored.
The set operations provided by HashSet (UnionWith, IntersectWith, ExceptWith, and SymmetricExceptWith) don't just take another HashSet object as a parameter-they actually take a generic IEnumerable. This means that the set operations can be used with any other collection. Figure 3 shows how the set operations can work with any collection that implements the generic IEnumerable interface. As with the constructor overload that takes an IEnumerable, duplicates are ignored. (The behavior of UnionWith, IntersectWith, ExceptWith, and SymmetricExceptWith is outlined in Figure 4.)

Set Operation Description Example
UnionWith(IEnumerable<T> other); Modifies the HashSet to contain all the elements contained by both the HashSet or other. // set1 contains 1,2,3,4 // set2 contains 3,4,5,6 set1.UnionWith(set2); // set1 contains 1,2,3,4,5,6
IntersectWith(IEnumerable<T> other); Modifies the HashSet to contain all the elements contained by both the HashSet and other. // set1 contains 1,2,3,4 // set2 contains 3,4,5,6 set1.IntersectWith(set2); // set1 contains 3,4
ExceptWith(IEnumerable<T> other); Removes all elements contained by the HashSet that are contained by other. // set1 contains 1,2,3,4 // set2 contains 3,4,5,6 set1.ExceptWith(set2); // set1 contains 1,2
SymmetricExceptWith(IEnumerable<T> other); Modifies the HashSet to contain all elements contained by either the HashSet or other, but not both. // set1 contains 1,2,3,4 // set2 contains 3,4,5,6 set1.SymmetricExceptWith(set2); // set1 contains 1,2,5,6
List<int> oddNumbers = new List<int>();
oddNumbers.Add(1);
oddNumbers.Add(3);
oddNumbers.Add(5);

HashSet<int> numberSet = new HashSet<int>();
numberSet.UnionWith(oddNumbers);
// numberSet contains 1,3,5

int[] evenNumbers = { 2, 4, 6, 2, 6, 4, 2, 4, 6, 2 };
numberSet.UnionWith(evenNumbers); // duplicates are ignored
// numberSet contains 1,2,3,4,5,6

numberSet.ExceptWith(oddNumbers);
// numberSet contains 2,4,6
HashSet provides more operations than just the methods noted in the table. These include IsSubsetOf, IsProperSubsetOf, IsSupersetOf, and IsProperSupersetOf. With these, HashSet supports most of the mathematical operations that can typically be performed on sets.
As you can see, getting started using this new collection is quite simple. HashSet fits in nicely with our other generic collections and fills one of the last remaining holes in our collection APIs.

Pipes
The last classes we're going to look at in this column are the pipe classes. For Visual Studio "Orcas," we've added support for both anonymous and named pipes to the .NET Framework. Pipes are used to achieve interprocess communication (IPC) between two or more processes on the same machine or over a network. The new types, which can be found in the System.IO.Pipes namespace, expose nearly all the pipe functionality provided by Windows.
Anonymous pipes are used for communication between a parent process and a child process. These one-way pipes are unnamed and must be used locally on the same machine. Figure 5 shows the code for sending a string from a parent process to a child process.

Parent Process
 

using (Process process = new Process())
{
    process.StartInfo.FileName = "child.exe";
    using (AnonymousPipeServerStream pipeStream = 
        new AnonymousPipeServerStream(PipeDirection.Out,
            HandleInheritability.Inheritable)) 
   {
        process.StartInfo.Arguments =
            pipeStream.GetClientHandleAsString();
        process.StartInfo.UseShellExecute = false;
        process.Start();

        pipeStream.DisposeLocalCopyOfClientHandle();
        using (StreamWriter sw = new StreamWriter(pipeStream)) 
        {
            sw.AutoFlush = true;
            sw.WriteLine(Console.ReadLine());
        }
    }
    process.WaitForExit();
}


Child Process
 

using (PipeStream pipeStream =
    new AnonymousPipeClientStream(PipeDirection.In, args[0])) 
{    
    using (StreamReader sr = new StreamReader(pipeStream)) 
    {
        string temp;
        while ((temp = sr.ReadLine()) != null) 
        {
            Console.WriteLine(temp);
        }
    }
}
Named pipes provide much more functionality than anonymous pipes. For starters, they are full duplex and can be used over a network. Named pipes support multiple server instances of a single name, message-based communication, asynchronous I/O, and impersonation. Figure 6 shows how to send two strings from one process to another process using a named pipe.

Server Process
 
using (NamedPipeServerStream pipeStream =
    new NamedPipeServerStream("mypipe")) 
{
    pipeStream.WaitForConnection();
    using (StreamWriter sw = new StreamWriter(pipeStream)) 
    {
        sw.AutoFlush = true;
        sw.WriteLine(Console.ReadLine());
        sw.WriteLine(Console.ReadLine());
    }
}

Client Process
 
using (NamedPipeClientStream pipeStream =
    new NamedPipeClientStream("mypipe")) 
{
    pipeStream.Connect();
    using (StreamReader sr = new StreamReader(pipeStream)) 
    {
        string temp;
        while ((temp = sr.ReadLine()) != null) {
            Console.WriteLine(temp);
        }
    }
}
Named pipes also support message-based communication (demonstrated in Figure 7). This allows a reading process to read varying-length messages sent by the writing process. In Figure 7, two string messages are sent from a server process to a client process. The example includes two helper classes-MessageWriter and MessageReader-that do the actual work of writing and reading string messages to and from the underlying named pipe streams.

Helper Classes
 
class MessageWriter 
{
    NamedPipeServerStream m_pipeStream;
    Encoding m_encoding;
    public MessageWriter(NamedPipeServerStream pipeStream,
        Encoding encoding) 
    {
        m_pipeStream = pipeStream;
        m_encoding = encoding;
    }
    public void WriteMessage(string message) 
    {
        Byte[] buffer;
        buffer = m_encoding.GetBytes(message);
        m_pipeStream.Write(buffer, 0, buffer.Length);
    }
}
class MessageReader 
{
    NamedPipeClientStream m_pipeStream;
    Decoder m_decoder;
    Byte[] m_buffer = new Byte[10];
    Char[] m_charBuffer = new Char[10];
    StringBuilder m_stringBuilder = new StringBuilder();
    public MessageReader(NamedPipeClientStream pipeStream,
        Encoding encoding) 
    {
        m_pipeStream = pipeStream;
        m_decoder = encoding.GetDecoder();
    }
    public string ReadMessage() 
    {
        // Clear the StringBuilder
        m_stringBuilder.Length = 0;
        // Read the message
        int bytesRead;
        do {
            bytesRead = m_pipeStream.Read(m_buffer, 0, m_buffer.Length);
            int numChars = m_decoder.GetChars(m_buffer, 0, bytesRead,
                m_charBuffer, 0);
            m_stringBuilder.Append(m_charBuffer, 0, numChars);
        } while (!m_pipeStream.IsMessageComplete);
        // Return the message or null if the pipe has been closed
        if (bytesRead != 0) {
            m_decoder.Reset();
            return m_stringBuilder.ToString();
        }
        else return null;
    }
}

Server Process
 
using (NamedPipeServerStream pipeStream =
    new NamedPipeServerStream("messagepipe",
    PipeDirection.InOut, 1, PipeTransmissionMode.Message)) 
{
    pipeStream.WaitForConnection();
    MessageWriter mw = new MessageWriter(pipeStream, Encoding.UTF8);
    mw.WriteMessage("Hello World!");
    mw.WriteMessage("Named Pipes Are Cool!");
}

Client Process
 
using (NamedPipeClientStream pipeStream =
    new NamedPipeClientStream("messagepipe")) 
{
    pipeStream.Connect();
    pipeStream.ReadMode = PipeTransmissionMode.Message;
    MessageReader mr = new MessageReader(pipeStream, Encoding.UTF8);
    string message;
    while ((message = mr.ReadMessage()) != null) 
    {
        Console.WriteLine(message);
    }
}
As you can see, the new pipe types are first-class managed citizens, making it easy to achieve IPC from within managed code. Anyone familiar with streams should have no trouble getting started using pipes.

Conclusion
The classes discussed in this column are a sampling of the new green bits functionality available in Visual Studio "Orcas." Download the latest CTP at msdn2.microsoft.com/en-us/vstudio/aa700831.aspx to give these types a test drive. And stop by the BCL Team's blog to let us know what you think.

Send your questions and comments to  clrinout@microsoft.com.


Mike Downen is a Program Manager focusing on security and deployment on the CLR team. He can be reached via his blog at blogs.msdn.com/CLRSecurity.

Inbar Gazit is a Program Manger focusing on the base class libraries for the CLR team. He can be reached via e-mail at inbar@microsoft.com.

Justin Van Patten is a Program Manager for the base class libraries within the CLR team. He can be reached via the BCL team blog at blogs.msdn.com/bclteam.

Page view tracker