Max Number of Threads Per Windows Process

Developers usually thinks that Windows has a default value for the max number of threads a process can hold. while in fact the limitation is due to the amount of address space each thread have can have.

I was working lately on some mass facility simulation applications to test some complex RFID based system. I needed to have a different thread for each person in the facility to simulate parallel and different movement of people at the same time .. and that’s when the fun started Smile.with the simulation running more than 3000 individuals at the same time, it wasn’t too log before I got the OutOfMemory Unfriendly Exception.

When you create new thread, it has some memory in the kernel mode, some memory in the user mode, plus its stack, the limiting factor is usually the stack size. The secret behind that is the default stack size is 1MB and the user-mode address space assigned to the windows process under 32 bit Windows OS is about 2 GB. that allow around 2000 thread per process (2000 * 1MB = 2GB).

Hit The Limit!

imageRunning the following code on my virtual machine with the specs in the image runs around ~ 1400 Threads, the available memory on the machine also takes place in deciding the Max number of threads can be allocated to your process.

Now running the same application multiple times on different machines with different configs will give a close or similar results.

using System;
using System.Collections.Generic;
using System.Threading;

namespace MaxNumberOfThreadsDemo
{
    public class Program
    {
        private static List<Thread> _threads = new List<Thread>();

        public static void Main(string[] args)
        {
            Console.WriteLine("Creating Threads ...");
            try
            {
                CreateThreadsWithDefaultStackSize();
                //CreateThreadsWithSmallerStackSize();
                //CreateThreadsWithSmallerThanMinStackSize();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            Console.ReadLine();
            Console.WriteLine("Cleanning up Threads ...");
            Cleanup();

            Console.WriteLine("Done");
        }


        public static void CreateThreadsWithDefaultStackSize()
        {
            for(int i=0; i< 10000; i++)
            {
                Thread t = new Thread(DoWork);
                _threads.Add(t);
                t.Name = "Thread_" + i;
                t.Start();
                Console.WriteLine(string.Format("{0} started!",t.Name));
            }
            
        }
        private static  void Cleanup()
        {
            foreach (var thread in _threads)
                thread.Abort();
            _threads.Clear();
            _threads = null;
        }

        private static void DoWork()
        {
            Thread.Sleep(Int32.MaxValue-1);
        }
    }
}

image

How Can you extend the Limit?

Well, There are several ways to get around that limit, one way is by setting IMAGE_FILE_LARGE_ADDRESS_AWARE variable that will extend the user mode address space assigned to each process to be 3GB on 32x windows or 4GB on 64x.

Another way is by reducing the stack size of the created thread which will in return increases the maximum number of threads you can create. You can do that in C# by using the overload constructor when creating a new thread and provide maxStackSize.

Thread t = new Thread(DoWork,256);

Beginning with the .NET Framework version 4, only fully trusted code can set maxStackSize to a value that is greater than the default stack size (1 megabyte). If a larger value is specified for maxStackSize when code is running with partial trust, maxStackSize is ignored and the default stack size is used. No exception is thrown. Code at any trust level can set maxStackSize to a value that is less than the default stack size.

Running the following same code after setting the maxStackSize of the created threads to 256KB will increase the number of max threads created per process.

image

Now If maxStackSize is less than the minimum stack size, the minimum stack size is used. If maxStackSize is not a multiple of the page size, it is rounded to the next larger multiple of the page size. For example, if you are using the .NET Framework version 2.0 on Microsoft Windows Vista, 256KB (262144 bytes) is the minimum stack size, and the page size is 64KB (65536 bytes). according to MSDN.

In closing, resources aren’t free, and working with multiple threads can be really challenging in terms of reliability, stability, and extensibility of your application. but definitely hitting the max number of threads is something you want to think about carefully and consider maybe only in lab or simulation scenarios.

More Information

Hope this Helps,

Ahmed

CLR 4.0: Code Contracts

Note: This blog post transferred from my OLD BLOG and was originally posted in 2008.

As part of making the .Net framework fully support Design by Contract approaches, the BCL team along with the CLR team had integrated very powerful project from Microsoft Research (MSR) named Code Contracts, and what code contracts do for you as giving you declarative, integrated, and easy way to express all the facts you already know about your program by design to make it work better.

Before you used to do that using Assert statements or even using some comments on top of your API telling people what’s the rules they should follow in order to perfectly use your Methods, one major thing about those methods that it wasn’t a Must to Follow, on the contrary Code Contracts is enforcing and checked statically at compile time and dynamically at runtime.

Note: At this CTP build of Visual Studio and .Net Framework, the Static Analysis tools is not supported yet, but the dynamic runtime checking is supported

Microsoft decided to provide Code Contracts as Library Solution instead of Language Solution that’s to make them widely used by all the languages using .Net framework, So new in .Net Framework 4.0 BCL under System.Diagnostics.Contracts you will find the code contracts library.

All Code contracts grouped under CodeContract static Class as Static Methods that return void, each Contract Methods has 2 overloads; One takes a Boolean expression that must be true in order for contract to be valid and another overload that take expression and a message to display in case of contract violation, things you should know about contracts:

  • Declarative
  • Come at the beginning of the function
  • Think about them as part of the method signature.
  • Your contracts can have only Boolean Expressions.
  • You can but methods calls inside your contracts but this method must be marked as Pure.
image

How to use Contracts

Defining contracts is fairly easy as adding couple of checking lines at the start of the method, check the following sample calculator class to understand how you can use contracts inside your classes:

 1: public class Calculator
 2: {
 3:     /// <summary>
 4:     /// Adds 2 numbers
 5:     /// </summary>
 6:     /// <param name="x">First number can't be zero</param>
 7:     /// <param name="y">Second number can't be zero</param>
 8:     /// <returns>Sum of the 2 numbers</returns>
 9:     public int Add(int x, int y)
 10:     {
 11:         CodeContract.Requires(x > 0 && y > 0);
 12:
 13:         return x + y;
 14:     }
 15:
 16:     /// <summary>
 17:     /// Subtract 2 positive numbers
 18:     /// </summary>
 19:     /// <param name="x">First Number must be larger than the second</param>
 20:     /// <param name="y">Second number</param>
 21:     /// <returns>Result of subtraction, can't be negative</returns>
 22:     public int Sub(int x, int y)
 23:     {
 24:         CodeContract.Requires(x > y);
 25:         CodeContract.Ensures(CodeContract.Result<int>() > -1);
 26:
 27:         return x - y;
 28:     }
 29: }

Types of Contracts

CodeContracts has 3 main types:

1. Preconditions

Use them to validate your method parameters, they must be true at method entry for successful execution of the method.  It’s the responsibility of the caller to make sure these conditions are met.

    • CodeContract.Requires(x>= 0);
    • CodeContract.RequiresAlways(x>= 0);

The difference between Requires and RequiresAlways is the last one always included even in release builds, so you can use it for contracts that you want to include in your release.

2. Postconditions

They are declared at the beginning of a method, just like preconditions.  The tools take care of checking them at the right times.their jobs is to ensure that methods has successful closure.

    • CodeContract.Ensures(z != null); // must be true if method closes successfully
    • CodeContract.EnsuresOnThrow<IOException>(z != null); // Grantuee some variable status in case of specific exceptions.

Also it is very often necessary to refer to certain values in postconditions, such as the result of the method, or the value of a variable at method entry.  CodeContract class allow this using some special referral methods; they are valid only in a postcondition.

    • CodeContract.Ensures(CodeContract.Result<Int32>() >= 0); //represents the value results from a method
    • CodeContract.Ensures(x > CodeContract.OldValue(x)); // represents the value as it was at the start of the method or property.  It captures the pre-call value in a shallow copy.

3. Object Invariants

They are contracts that must be true at all public methods exists in an object. They are contained in a separate method that is marked with the ContractInvariantMethodAttribute.  The method must be parameter-less and return void.  That method contains some number of calls to the CodeContract.Invariant method.

   [ContractInvariantMethod]
void ObjectInvariant() {
CodeContract.Invariant(someData >= 0);
}

What do you ship?

image The final question that matters is what I’ll deliver the customer, in reality Code contracts has a very intelligent way of generating its own contract assemblies, so you have your old normal .net assemblies without contract that you can release to your customers and don’t worry about the performance hit, and another assembly contains the contracts only without any code; you can deliver those assemblies to your customer that you want them have the same code checking experience you have during compile time.

More Information:

  1. Microsoft Research’s code contracts website.
  2. PDC 2008: PC49, Microsoft .NET Framework – CLR Futures (Video|PPTX).
  3. PBC 2008: TL51 Research: Contract Checking and Automated Test Generation with Pex (Video|PPTX).
  4. Introduction to Code Contracts [Melitta Andersen].

Related Articles:

  1. CLR 4.0: Type Embedding.
  2. CLR 4.0: New Enhancements in the Garbage Collection
  3. CLR 4.0: Corrupted State Exceptions

Hope this Helps,

Ahmed

CLR 4.0: Dynamic Languages Support

Note: This blog post transferred from my OLD BLOG and was originally posted in 2008.

As more and more dynamic languages start to show up in the .net world like IronPython, IronRuby, and F# the need for some changes in the CLR and the BCL to natively support those languages become important. But what’s really beautiful about CLR is it’s well designed framework, and eventually Microsoft discovered that the changes they need to make is not that much, Jim Hugunin built a Full Dynamic Language Runtime (DLR) on top of the CLR and he didn’t ask them for a lot of changes.

Some of the Changes in CLR 4.0 in order to support Functional and Dynamic Languages are:

    1. BigIntegers
    2. Tuples

BigIntegers

Jim Hugunin asked Anders Hejlsberg What is the sum of 2 billion and 2 billion; Anders answered – 2 billion :D, this joke was the primer in a lot of the last PDC sessions! And the fact that C# compiler simulate the nature of 8 bytes numbers in the current microprocessor architecture is not something the C# community to be ashamed of, because this is the what the microprocessor designed to do and you don’t want to have different behaviors. But the the fact that still in normal numeric processing you have the normal behavior of adding 2 large numbers like 2 billion should give you the result of 4 billion, and it make all the sense.

So, if you’ve try to execute this operation (2000000000 + 2000000000) on the current C# compiler you should get the following result, and of course the compiler is smart enough to detect that you are doing an operation that will cause an arithmetic overflow, so you have to use the uncheck key work to stop the compiler check on arithmetic overflow exception (for more details review my post: Silent Overflow in CLR).
image
image New in CLR 4.0 and BCL 4.0, you will find a new type BigInteger under System.Numerics namespace, the CLR team cooperated with the Optima team “Microsoft Solver Foundation” to provide reliable, optimum, and fast BigInteger Type in .Net base class library. supporting this new type as library solution means all languages can benefit of this functionality no matter it’s dynamic or not. so C# will have BigIntegers as IronPython too.

Tuples

The Tuple is a mathematical term and it simply means an ordered list of values, those values are the internal items of this tuple and you can access those items by referencing them directly with their position in the sequence. To be more specific the Tuple is kind of On Fly Struct, you don’t have to define names for its internal items to access, you just access them by index!

Tuple requested to be supported by F# team and IronPython team, and they are supported natively in this languages. The CLR team have worked hardly with all the language teams and come up with final implementation for a Tuple library that everyone is happy with.

So new in .Net 4.0 under the system namespace you will find a generic type called Tupletakes up to 7 generic types although hi didn’t saw tuples takes that much items on fly! with library solution support the other languages like C# will not natively need to support tuples, so there will be no keyword for tuple in C#.here is an example on how to use tuples:

var tuple1 = Tuple.Create(4, ‘ahmed’);
var item1 = tuple1 .Item1;
var item2 = tuple1 .Item2;


image

A typical usage for Tuple is as a return type for a method need to return multiple values instead of using out parameters you can use a tuple because it’s easy to create on fly, for instance in this quick example i’ve built a function adds a new item into a collection the logic of this function is to search first if the item exist already in the collection; and if item founded, function return a Boolean value of false determining failure of adding the item and also the index of the already existed item, you could use out parameter of course for doing the same job which i still prefer!

 1: public static

Tuple

<bool,int> AddItem(string item)
 2: {
 3:

var

 result;
 4:
 5:     //if item exists in the collection, return A tuple with 
 6:    // false, and the index of the existed item in the collection.
 7:     if (collection.Contains(item))
 8:     {
 9:         result =

Tuple

.Create(false, collection.IndexOf(item));
 10:     }
 11:     // if item doesn't exist in the collection, add the item and return 
 12:    // a tuple with true and the index of the inserted item.
 13:     else
 14:     {
 15:         collection.Add(item);
 16:         result =

Tuple

.Create(true, collection.Count - 1);
 17:     }
 18:
 19:     return result;
 20: }

Last advise about Tuples, don’t use them in public APIs and methods, it will makes your code harder to understand although it’s easier to create Tuples but the internal data structure of the Tuple must be documented very well and known by the user of your function in order to use it right, on the contrary of out parameters the user of your method just need to read your parameter name to understand its job!

More Information:

  1. PDC 2008: PC49, Microsoft .NET Framework – CLR Futures (Video|PPTX).
  2. PBC 2008: TL10 Deep Dive, Dynamic Languages in Microsoft .NET(Video|PPTX).
  3. Wikipedia: Tuple

Related Articles:

  1. CLR 4.0: Type Embedding.
  2. CLR 4.0: New Enhancements in the Garbage Collection.
  3. CLR 4.0: Corrupted State Exceptions.
  4. CLR 4.0: Code Contracts.

Hope this Helps,

Ahmed

CLR 4.0: Corrupted State Exceptions

Note: This blog post transferred from my OLD BLOG and was originally posted in 2008.

image image

Thread Created by the CLR

Thread Created outside the CLR

Threads that can run managed code can be classified into two types.

  1. There are threads that are created by the CLR, and for such threads, the CLR controls the base (the starting frame) of the thread.
  2. There are also threads that are created outside the CLR but enter it at some later point to execute managed code; for such threads, the CLR does not control the thread base.
The CLR uses the following algorithm to trigger and handle thrown exceptions within the CLR Created Threads. After the CLR walks up the exception call stack, if the CLR can’t find a managed exception handler in Main, the exception will reach the native frame within the CLR where the thread started. In this frame, the CLR has established an exception filter that will apply the policy to swallow (blind catch) exceptions, if applicable. If the policy indicates not to swallow the exception ( default in .NET Framework 2.0 and later), the filter triggers the CLR’s unhandled exception processing.The Unhandled Exception Processing History in .Net

In the .NET Framework 1.0 and 1.1, unhandled exceptions on threads that were created within the CLR were swallowed at the thread base (the native function at which the thread started in the CLR).
Which is, the behavior we don’t want, since the CLR has no clue about the reason the exception was raised in the first place. Thus, swallowing such an exception, is a mistake since the extent of application or process state corruption cannot be determined. What if the exception was the kind that would indicate a corrupted process state such as Access Violation, for instance?

In the .NET Framework 2.0, this behavior was changed. Unhandled exceptions on threads created by the CLR are no longer swallowed. If the exception is not handled by any managed frame on the stack, the CLR will let it go unhandled to the OS after triggering the unhandled exception process. The unhandled exception, then, will result in an application crash.

And for backward compatibility with legacy application that built on top of CLR 1.0, CLR 2.0 provided a flag was that could be set in the application configuration file’s runtime section to have the old behavior of swallowing the unhandled exceptions:

 1: <configuration>
 2:   <runtime>
 3:     <legacyUnhandledExceptionPolicy enabled="true"/>
 4:   </runtime>
 5: </configuration>
image

Super Exceptions (New in CLR 4.0)

CLR 4.0 will not allow you anymore to catch exceptions that may corrupt the state of the current running process, the CLR 4.0 introduced this new concept of Corrupted State Exceptions (i like to think of those as Super Exceptions), those exceptions that could corrupt the state of the process and causing losing user data or weird application behaviors like:

  • Access Violation Exception
  • Invalid Memory Exception
  • etc ..

Those kind of exceptions is dangerous and the best scenario most of the time is to stop processing as quick as you can before you lose user important data or cause the application to behave in unexpected ways.

A sample scenario of when those exception could happen like the following scenario, if you try to run this sample code while you another process accessing “file.txt” you will got Access Violation Exception. In .Net 2.0 you can catch and swallow this kind of exceptions as in this code snippet; But this will not be the case anymore, which means that the catch statements will not be able anymore to see this Corrupted State Exceptions, and no matter what they will popup and stop the process of continuing its work.

 1: class Program
 2: {
 3:     static void Main(string[] args)
 4:     {
 5:         SaveFile("file.txt");
 6:         Console.ReadLine();
 7:     }
 8:
 9:     public static void SaveFile(string fileName)
 10:     {
 11:         try
 12:         {
 13:             FileStream fs = new FileStream(fileName, FileMode.Create);
 14:         }
 15:         catch (Exception ex)
 16:         {
 17:             Console.WriteLine("File open error");
 18:             throw new IOException();
 19:         }
 20:     }
 21: }

The CLR team knew that there are some rear circumstances that you will need to handle those Corrupted State ExceptionThe Super-Exception “, may be for doing some log routine but not to continue processing. So CLR 4.0 provide a new attribute called HandleProcessCorruptedStateExceptions, you can use to decorate the methods you want to use in doing some log routines or whatever notification scenarios about those super exceptions.

 1: [HandleProcessCorruptedStateExceptions]
 2: public static void HandleCorruptedStateException()
 3: {
 4:     // Write your Super-Exception Notification code here
 5:     // log, or Send Mail etc ..
 6: }
Also for backward compatibility purposes CLR 4.0 provides a new process wide compact switch you can easily set to have the old behavior of catching those Corrupted State Exceptions as in previous versions of CLR.
 1: <configuration>
 2:   <runtime>
 3:     <legacyCorruptedStateExceptionsPolicy enabled="true"/>
 4:   </runtime>
 5: </configuration>

Related Stuff:

  1. PDC 2008: PC49, Microsoft .NET Framework – CLR Futures (Video|PPTX).
  2. Unhandled Exception Processing In The CLR (Gaurav Khanna)
  3. CLR 4.0: Type Embedding
  4. CLR 4.0: New Enhancements in the Garbage Collection

Hope this Helps,

Ahmed

CLR 4.0: New Enhancements in the Garbage Collection

Note: This blog post transferred from my OLD BLOG and was originally posted in 2008.

image

The current Garbage Collection does pretty good job in reclaiming the memory of Gen 0 and Gen 1, those Generation’s objects live in ephemeral segments which is very small and GC reclaims their memory very fast, on the contrary most of Gen 2 objects live in other large segments which make Gen 2 large objects collection slower than other collections.

The GC team actually made great improvements in collection algorithms on both the server and the workstation to make it faster and reduce latency.

Enhancements in Server Garbage Collection

The current server GC is very efficient in terms of maximizing the overall throughput; this because GC’s Gen 2 actually pauses all the current running managed code on the server while it runs. And It turns out that this makes the GC as fast as all of us need “BUT” the cost is generating those long pauses on the server managed code execution, and increasing the latency of course!

What the CLR team did in v4.0 is they allow you to be notified before Gen 2 collection (LOH collection or Large Object Heap Collection) happens. You might ask how this could help me in reducing those latency on my server? And in fact there are good news and bad news; the good news is yes this will help you to reduce the latency and reduce the long pauses on your server, and the bad news is this will not help everyone in reality it will help you if you only uses some Load Balancing techniques.

What now CLR offering is a notification model you can use to know when GC starts Gen 2 collection on the current server, so you can switch the user traffic through your load balancer to another application server and then start Gen 2 collection for the old traffic on the first application server; your user will not feel that same latency and long pauses as before.

 

I’m gona walk you through sample code to learn you how to benefit from this new enhancement in your server applications. 

image
   1: public class Program
   2: {
   3:     public static void Main(string[] args)
   4:     {
   5:         try
   6:         {
   7:             // Register on the FullGCNotification service
   8:             // Set the Maximum generation Threashold and 
   9:             // the large object heap threshold
  10:             GC.RegisterForFullGCNotification(10, 10);
  11:  
  12:             // wait for the notification to happen on a new thread
  13:             Thread fullGCThread = new Thread(new ThreadStart(WaitForFullGC));
  14:             fullGCThread.Start();
  15:         }
  16:         catch (InvalidOperationException ex)
  17:         {
  18:             Console.WriteLine(ex.Message); 
  19:         }
  20:     }
  21:     public static void WaitForFullGC()
  22:     {
  23:         while (true)
  24:         {
  25:             // This is a blocking call, once it returns with succeed
  26:             // status, this means that Gen 2 collection is about to happen
  27:             GCNotificationStatus status = GC.WaitForFullGCApproach();
  28:  
  29:             if (status == GCNotificationStatus.Succeeded)
  30:             {
  31:                 // now you call your custom procedure to switch
  32:                 // the trafic to another server
  33:                 OnFullGCApproachNotify();
  34:             }
  35:  
  36:             // Now you are waiting for  GC to complete Gen 2 collection
  37:             status = GC.WaitForFullGCComplete();
  38:             // once it finish you call your custom procedure to switch back
  39:             // the traffic to your first server
  40:             if (status == GCNotificationStatus.Succeeded)
  41:             {
  42:                 OnFullGCCompleteNotify();
  43:             }
  44:  
  45:         }
  46:     }
  47:  
  48:     private static void OnFullGCApproachNotify()
  49:     {
  50:         // 1. Direct the new traffic away from this server
  51:         // 2. Wait for the old traffic to finish
  52:         // 3. Call GC.Collect, and this is the interesting part because
  53:         // Microsoft always tells you not to call GC.Collect yourself.
  54:         // but here you will need to do that because there are no more traffic
  55:         // redirected to this server, so you might wait forever before the GC starts
  56:         // so you need to start the GC.Collect() yourself
  57:         GC.Collect();
  58:     }
  59: }
 
Enhancements in Workstation Garbage Collection
 
Today’s CLR have a Concurrent Collection algorithm for workstation’s GC, this algorithm can do most of Gen 2 objects collection without pausing the running managed code too much at least not as much as on GC’s Server algorithms.
So the problem occur when ephemeral segments fills up during GC is busy making Gen 2 collection on other segments then a new objects allocated from ephemeral segments that’s when the pauses happen on the workstation and the user feels the latency; Concurrent Collection Algorithm can’t run Gen 0 and Gen 1 at the same time as Gen 2 is occurring.
 
New in CLR 4.0 a new collection algorithm used for Workstation’s GC collection instead of the Concurrent Collection Algorithm, this new algorithm is called Background Collection Algorithm, one key thing about this new Background Algorithm is it can do Gen 0 and Gen 1 at the same time Gen 2 is occurring; and in that way you will not see long pauses in your client application as before only in very unusual circumstances.
image
In the upper chart you can see a statistical comparison between the Old Concurrent Algorithm and the Background Algorithm performance. As you ca see at the start of the application in both of the algorithms there is one pause but it takes half the time in the Background algorithm, one the application continue working in the case of Concurrent GC  there are multiple long pauses, on the contrary in the Background GC you se far a few longer pauses as before.
 
With new GC Notification Algorithm on server managed applications and new Background Collection Algorithm on Workstation managed applications; the CLR team leverage a new performance experiences with fewer long pauses and great latency.
 
Related Stuff:
  1. PDC 2008: PC49, Microsoft .NET Framework – CLR Futures (Video|PPTX).
  2. Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework (Jeffrey Richter).
Hope this Helps,
Ahmed

CLR 4.0: Type Embedding

Note: This Post transfered from my OLD Blog and was originally posted in 2008.

 

As new enhancement in CLR version 4.0 (will be released in 2010) is the concept of Type Embedding. The actual motivation for this new concept was the miserable story of deploying application that uses Primary Interop Assemblies (PIA).

In previous versions of CLR you’ve needed to deploy your managed assembly plus the PIA to the client machine, in some scenarios like developing against the MS Office’s PIAs, you need to deploy the whole Office PIA Redist which is about 6.3 MB to make your little application works!!

and the problem getting worth if you try to target a machine that have different version of MS Office’s PIAs

This was a very bad experience if you have been through it before.

image

So the Scenario was trying to develop against PIAs leads to:

  • Complex deployment scenarios
  • Targeting multiple hosting environment.
  • Tight type coupling.

MS started a new project code-name NOPIA as part of the next version of CLR 4, its target was to eliminate runtime dependency on Interop Assemblies at compile time easily, So you can do that with just flipping a switch in the visual studio assembly reference properties window or just by compiling your code with /link switch.

What’s NOPIA

Using this new capability you are actually telling the CLR to embed all the necessary information to call the com object embedded into the managed assembly itself, so you don’t need the PIA assembly to be deployed with your application anymore.

The embedded information represented as “Local Types” which is a partial copies of the types exist in the PIA.

As an example we will develop this sample Hello Buddy console Application simply takes a name and interact with Word PIA ( Microsoft.Office.Word.dll ) from Office PIA Redist, to create new word document and Write “Hello name” statement.

image

I’m using Visual Studio 2010, .Net 4.0, and CLR v4.0 CTP to develop this application, you can download this CTP here.

  • Create new C# console application.
  • Add reference for Microsoft.Office.Interop.Word.dll
  • Add this class to your applicaion.
 1: using System;
 2: using Word = Microsoft.Office.Interop.Word;
 3:
 4: namespace HelloBuddy
 5: {
 6:     public class Program
 7:     {
 8:         static void Main(string[] args)
 9:         {
 10:             SayHi("Ahmed");
 11:             Console.ReadLine();
 12:         }
 13:
 14:         public static void SayHi(string name)
 15:         {
 16:             Word.Application wordApp = new Word.Application();
 17:
 18:             wordApp.Visible = true;
 19:             wordApp.Activate();
 20:
 21:             object falseValue = false;
 22:             object trueValue = true;
 23:             object missing = Type.Missing;
 24:
 25:             Word.Document doc = wordApp.Documents.Add(ref missing, ref missing, ref missing, ref missing);
 26:
 27:             object start1 = 0;
 28:             object end1 = 0;
 29:
 30:             Word.Range rng = doc.Range(ref start1, ref missing);
 31:             rng.Font.Name = "Tahoma";
 32:             rng.InsertAfter("Hello " + name);
 33:
 34:         }
 35:
 36:     }
 37: }
  • Compile and run
  • You should be apple to see MS Word window open with “Hello Ahmed” statement.Check the compiled assemblies in your bin directory, you’ll find:
    1. HelloBuddy.exe
    2. Microsoft.Office.Interop.Word.dll.

    Attach “HelloBudy.exe” to your VS Debugger, and check the loaded modules, you will find the Office PIA assembly is loaded, and this is the one we are trying to get rid of

image

loadedModules1NOPIA Mode

Now let’s switch to NOPIA Mode, and embed those PIA used types into our console assembly, to do that:

  • Select the PIA assembly reference and choose properties
  • In Properties window, change property “Embed Interop Types” to True
  • Recompile your application.

If you check the Bin directory you will find only the application assembly ”HelloBuddy.exe ”, there is no PIA assembly. The Only difference is application assembly becoming little bit bigger because it now embed the partial type info from the original PIA, but still smaller than deploying the whole PIA file.

Attach “HelloBudy.exe” to your VS Debugger, and check the loaded modules, you will find only your application assembly, no more PIA.

Behind the Scene

If you are interested to know what actually CLR do behind the scenes, open your application assembly with Reflector and check the types inside it, you will find that CLR has injected Microsoft.Office.interop.Word namespace into your application’s assembly.

embed
In this namespace you can find only the set of types “local types” that you have used from the PIA into your application. Types like  Application, Document, Range, Font.
In fact the CLR rips only the types necessary to complete the calls you have made from your application, More than that if you check the emitted code for those types, for instance the Application type. CLR extracted only the functions you have called and replaced all the other functions and Type members with the magic _VblGap calls. Those _VtblGap pseudo methods are emitted in place of unused methods to maintain vtable compatibility.
embedIL0

NOPIA Limitations

Ofcourse there is nothing without limitations. NOPIA has some limitation of what you can embed into your assemblies:

  1. Can’t Embed IL (no classes or static methods)
  2. Only metadata is locally embedded (interfaces, delegates, enums, structs )
  3. Only types from Interop Assemblies can be embedded. Compilers check for these attributesa. [assembly:Guid(…)]b. [assembly:ImportedFromTypeLib(…)]

As you can see how the MS Future CLR v4.0 provides an easy way to develop application against COM interop assemblies, along with very friendly, powerful deployment scenario.

Related stuff

Hope this helps,

Ahmed