I am a developer at Microsoft and work in the .NET Common Language Runtime (CLR) team. For the last 4 years I have been working on virtual machine technologies on a variety of form factors including desktops (Windows, Linux), tablets (Win8), gaming-consoles (Xbox 360), mobile devices (Windows Phone 7, Windows CE, Symbian).I have worked on various core pieces of the runtime including Garbage Collector, memory manager, platform abstraction layer, runtime-performance, etc.Before working on .NET I worked on Visual Studio Team Foundation Server, Visual Studio Team System, Adobe Framemaker, Adobe Acrobat, Texas Instrument's Code Composer Studio.
Frequently I feel the need for putting line numbers in source files which I put up in my blogs so that I can refer to them in the discussion that follows.
/* 1 */ using Output=System.Console; /* 2 */ /* 3 */ namespace AbhinabaNameSpace /* 4 */ { /* 5 */ class HelloWorldMainClass /* 6 */ { /* 7 */ public static void Main() /* 8 */ { /* 9 */ Output.WriteLine("Hello World"); /* 10 */ } /* 11 */ } /* 12 */ }
I am sure there are tools that already do this, but like most programers I couldn't resist writing a small script to do it. I guess programers have re-invented the wheel so many times that they come in all shapes these days, including square, rectangular and linear :) I chose Ruby simply because I am learning it right now. To run this you need to have ruby installed on you system. Run ruby linenum.rb (without any params) to find out the usage.
class LineNum def initialize(srcFile, destFile, startDelim, endDelim) raise ArgumentError.new("Source file #{srcFile} does not exist") unless File.exist?(srcFile) raise ArgumentError.new("Destination file #{destFile} already exist") if File.exist?(destFile) @srcFile = srcFile @destFile = destFile @startDelim = startDelim @endDelim = endDelim end def startCommenting() lineNum = 0 outFile = File.open(@destFile, "w") File.open(@srcFile, "r").each_line { |line| lineNum += 1 outFile.printf("%s %3d %s %s", @startDelim, lineNum, @endDelim, line) } outFile.close() puts("\nAdded line numbers to #{lineNum} lines") end end class Helper def Helper.showHelp puts "Usage: ruby lineNum <source file> <dest file> [<start delim> [<end delim>]]\n\n" puts "Example: ruby lineNum c:\\program.cs c:\\comment.cs\n" puts " ruby lineNum c:\\program.cs c:\\comment.cs /* */\n" end end if ARGV.length < 2 Helper.showHelp else begin startDelim = "/*" #default start delims endDelim = "*/" #default stop delims startDelim = ARGV[2] if ARGV.length > 2 endDelim = ARGV[3] if ARGV.length > 3 lineNum = LineNum.new(ARGV[0], ARGV[1], startDelim, endDelim) lineNum.startCommenting() rescue $stderr.printf("Error!!! %s\n", $!) end end
Yesterday night when we (me, Ankur and Hemant) were going out to dinner from office (Microsoft India Campus), we saw a meteor shooting past us in the sky. It was huge and almost looked like some firework except that it was coming downwards. I had never seen a larger shooting star and nither had the others. I was big enough and close enough for atleast the ashes to fall on earth. Unfortunately, there were no report of it in the news papers, I guess we should have reported it in the first place.
The worst part is that we figured out that we've been playing Halo a bit too much 'cause Ankur said that he thought it looked like a shot from the Rocket launcher.
Information applies to Beta3 and beyond releases and subject to change
Creation of build type is a two step process in which some files are generated and then checked-in to the source control. For a Build Type named MyBuildType for the Team Project MyTeamProject these files are checked-in at the server location $/MyTeamProject/TeamBuildTypes/MyBuildType.
The user interface and all the TeamBuild web methods provide policy validation to ensure that the Build Types remain secure. For example if you do not have Administer Build privilege then you will not be able to launch the Build Type Creation Wizard. Similarly to start a build through the Build form, command line or directly using the web method, security validations are made.
However, build types remain checked into source control at the location mentioned above. So an user can directly go to source control and modify them. Let's take a scenario. The system administrator who has all the required privileges creates a Build Type named Nightly and then schedules build so that automatically builds are fired daily at 8:00 p.m. An user ArthurDent who is not an admin but belongs to some group which has source control checkin permission checks out the file $/MyTeamProject/TeamBuildTypes/Nightly/TfsBuild.projand changes the drop location so that instead of the built bits getting dropped (copied) to the official location, gets copied to the users hard disk which he shared out as \\ArthurMachine\myshare.
Since all groups having checkin permissions will not essentially have Administer build, Start a build permissions. This can be considered as a privilege elevation risk.
The obvious question that comes to our mind is, does TeamBuild try to do something to put a check on these risks? The answer is yes. But a part of the responsibility does reside on the system administrator. Let's first see what TeamBuild does and then we can go into what the administrator can do to maintain security.
When a Build Type is created for the first time, TeamBuild creates the folder $/MyTeamProject/TeamBuildTypes. After creating this folder it applies some source control Access Control Locks (ACLs) so that only a subset of the users can modify files in this folder. The following permission changes are made on it.
All of the above ensure that the ACLs are in line with the Build security policy. However, once a Build Type has been created, the permissions (ACLs) are not changed on the TeamBuildTypes for subsequent build types. This gives the administrator chance to override or customize the ACLs.
Interesting points to note
The TFS Administrator has to ensure that once the Build Type is created the $/MyTeamProject/TeamBuildTypes is secure. He can try doing the following to plug any security hole
As I have said at the beginning, this blog entry is on code which are in development and can change at any time. I will try to keep this post updated in case we make any changes to security handling....
Recently there was an email-thread in the internal C# group on the usage of property vs. field.
The question raised was in case a class implements properties, is it still ok to go ahead and access the field directly from other methods of the same class. The thread also covered when it is ok to add properties.
This is a decision we take everyday when writing code. Some great people pitched in to give there opinion. The outcome is something like this
This is the my sixth post in the series of posts I am making on the new features of C#3.0. See the previous posts on var, extension method, lambda expressions, object-collection initializers and anonymous-types
I think the single biggest thing in C#3.0 is Language INtegrated Query or LINQ. On seeing all the other features of 3.0 (listed above) somehow I get a feel that they all came into the picture because Linq needs them to work well. This does not mean that these features do not find there usage elsewhere (they definitely do) but they look as if they are a part of the grand plan of Linq. CyrusN has some great blogs on Linq
I generally give strong opinions about whether I like a feature or not straightaway (no IMHO). But I am kind off divided on Linq. Lets first see what Linq is and how it works and then I'd go into why I like it and why I don't.
Using LINQ
Traditionally data has always been disjoint from code. A programming language would provide statements and expressions to work with data-types and each programmer would write specialized code in his own style to filter/manipulate data. Lets consider an array of Employees defined as below as our datasource. Note that the definition uses some of the new C#3.0 features including implicitly-types variables, anonymous-types, object-collection initializers and anonymous array declaratiom.
var employees = new []{ new { Name = "Arthur Dent", JobGrade = 3, JobTitle = "SDE", Salary = new { Base = 2000, Allowance = 1000 }}, new { Name = "Ford Prefect", JobGrade = 2, JobTitle = "SDE", Salary = new { Base = 5000, Allowance = 500 }}, new { Name = "Slartibartfast", JobGrade = 2, JobTitle = "SDET", Salary = new { Base = 3000, Allowance = 1000 }}, new { Name = "Zaphod Beeblebrox", JobGrade = 1, JobTitle = "SDE", Salary = new { Base = 6000, Allowance = 1000 }}, new { Name = "Trillian", JobGrade = 3, JobTitle = "SDET", Salary = new { Base = 12000, Allowance = 1000 }},};
var employees =
Salary =
};
In the old world you'd use custom functions to work on this array (data) to filter them based on some criteria. In C# 3.0 you can use extension method and lambda expressions to do this as
var highlyPaid = employees.Where(e => e.Salary.Base > 5000).Select(e => e.Name);
Effectively this returns the name of all employees whose base salary is over 5000. However in LINQ. You can convert this into query syntax which is similiar to SQL as in
// Query-1var highlyPaid = from e in employees where e.Salary.Base > 5000 select e.Name;
// Query-1
var
from e
where e.Salary.Base > 5000
select e.Name;
You can use other features like anonymous types to group data as well. In case you are interested to know the name of the person as well as his/her salary you'd write something like
// Query-2var highlyPaid = from e in employees where e.Salary.Base > 5000 select new { e.Name, e.Salary.Base };
// Query-2
var highlyPaid =
select new { e.Name, e.Salary.Base };
There is something interesting here. In classic anonymous type declaration the declaration of the type is of the form new { name = value }. However in the above case we have not specified the name and yet you can do
foreach(var v in highlyPaid) Console.WriteLine(v.Name);
foreach
Console.WriteLine(v.Name);
Here e.Name and e.Salary.Base is available as v.Name and v.Base. This works because the compiler knows the name of the fields in employee and generates the anonymous type to contain fields/properties matching the same name.
How LINQ works
C#3.0 does not put any restriction on the semantics of the query expressions. The language defines translation rules which maps each of the expressions into method invocation. So when the Linq expression Query-1 given above is compiled the compiler emits code to execute the following
The language defines that for Where clause the following will be called
delegate R Func<A,R>(A arg);class C<T> // This is the data type on which the query is run{ public C<T> Where(Func<T,bool> predicate); ....}
delegate
class
{
....}
Since this call is made by syntactic mapping the type on which the query is run is free to implement Where as a instance method, extension method or use the implementation of where in System.Query. If you open the assembly with some tool like reflector to see the generated code, you'll see that the whole query is just syntactic sugar to generate calls to these methods.
The formal translation rules and the recomended shape of a generic type that supports the query pattern is documented in the C#3.0 spec.
Why I like it
There are a lot of reasons to like LINQ.
Why I do not like it
This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous posts on var, extension method, lambda expressions and object-collection initializers
Before getting into why I do not like (actually hate) anonymous types in C#. Let's see what is this anonymous types and whats so special with this anonymity.
Anonymous types
Anonymous type is syntactic sugar to reduce typing. Let's say I need to create a structure or class to contain some data regarding customers. This is how you do it in C# 1.0
class Customer{ private string name; public string Name { get { return name; } set { name = value; }} private string address; public string Address { get { return address; } set { address = value; } }} Customer cust = new Customer();cust.Name = "Abhinaba Basu";cust.Address = "Hyderabad, India";
public string Name { get { return name; } set { name = value; }}
private string address;
public string Address { get { return address; } set { address = value; } }
}
Customer cust = new Customer();
cust.Name = "Abhinaba Basu";
cust.Address = "Hyderabad, India";
Or using the new Object initialization syntax of C#3.0 as
var cust = new Customer{Name = "Abhinaba Basu", Address = "Hyderabad, India"};
var cust =
This is a very repitative code pattern of creating data only containers (class or struct) for the related data types. This is can be done with the Anonymous method syntax as
var cust1 = new { Name = "Abhinaba Basu", Address = "Hyderabad, India" };
var cust1 =
Note that in this statement I have not named a type and hence the compiler emits code to generate a new class definition whose name is not know to us and hence is a Anonymous type. The following code is generated.
public sealed class <Projection>f__0{ // Methods public <Projection>f__0(); public override bool Equals(object); public override int GetHashCode(); public override string ToString(); // Properties public string Address { get; set; } public string Name { get; set; } // Fields private string _Address; private string _Name;}
public
Here <Projection>f__0 is the generated class' name. For each member a private field and the corresponding property is generated. The class also generates proper implementation to override Equals, GetHashCode and ToString methods based on each of the fields. The rest of the code is same as that used for Object initialization.
If we have two such declaration that match in the field types then the same class will be used for both of them.
var cust1 = new { Name = "Abhinaba", Address = "Hyderabad" };var cust2 = new { Name = "Ankur", Address = "Noida"};if (cust1.GetType() == cust2.GetType()) Console.WriteLine("Cust1 and Cust2 are of the same type {0}", cust2.GetType().ToString());// output:// Cust1 and Cust2 are of the same type // AnonymousTypes.Program+<Projection>f__0
var cust2 =
cust2.GetType().ToString());// output:
// Cust1 and Cust2 are of the same type // AnonymousTypes.Program+<Projection>f__0
There are couple of interesting point here
You can also use nested declaration as in
var cust = new { Name = "Abhinaba Basu", Address = "Hyderabad, India", Phone = new { AreaCode = 33, Number = 444444}};
Phone =
Why I do not like anonymous types
Again due to my upbringing in C/C++ I did not like implicit types when I saw it. This is taking the same idea to an extreme. Now not only are we letting the compiler choose the type for me I am also letting it generate new types!!!
Even without my pre-disposition I think that this construct address some special programming cases and should not have been included in the language. It'll just add to the surface area and learning curve and mainly go unused. The unusability comes from the following reasons
This is the my fourth post in the series of posts I am making on C#3.0. See the previous posts here, here and here
Object and collection initializers are new features in C#3.0 which is syntactic sugar over how you allocate and initialize objects and collections.
Object Initializers
Lets consider a class
class Customer{ public string name; public string address; int age; public int Age { get { return age; } set { age = value; } }}
if I wanted to create a object of the type customer and fill up the public variables and properties then in C#2.0 I need to do something like
Customer customer = new Customer();customer.name = "Abhinaba Basu";customer.address = "1835 73rd Ave NE, Medina, WA 98039";customer.Age = 99;
Customer
customer.name =
customer.address =
customer.Age = 99;
With the new object initializer syntax it possible to do all of the above in one statement as in
var cust = new Customer{name = "Abhinaba Basu", address = "1835 73rd Ave NE, Medina, WA 98039", Age = 99 };
This not only reduces lines of code but increases flexibility a lot. So no more being forced to write 5 overloads of a contructor that just accepts these variables and assigns them to fields.This syntax works for both public fields and properties.
In case the class contains other classes as fields then the same statement can also initialize the contained class (see code below in bold).
class Phone{ public int countryCode; public int areaCode; public int number;}class Customer{ public string name; public string address; public Phone phone;}static void Main(string[] args){ var cust = new Customer{name = "Abhinaba Basu", address = "1835 73rd Ave NE, Medina, WA 98039", phone = new Phone {countryCode = 1, areaCode = 425, number = 9999999}};}
phone =
This piece of code is equivalent to the following C#2.0 code
Customer customer = new Customer();customer.name = "Abhinaba Basu";customer.address = "1835 73rd Ave NE, Medina, WA 98039";Phone __phone = new Phone();__phone.countryCode = 1;__phone.areaCode = 425;__phone.number = 9999999;customer.phone = __phone;
__phone.countryCode = 1;
__phone.areaCode = 425;
__phone.number = 9999999;
customer.phone = __phone;
Collection Initializers
Collection initializer is a natural extension to object initializer. It consists of a list of initilializer for each of the elements in a collection seperated by comma and encosed in {}. For a simple List<int> it is as follows
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List
For the Customer and Phone number class discussed above the collection initializer will look like
List<Customer> custList = new List<Customer> { new Customer { name = "Samrat", address = "NJ, USA", phone = new Phone {countryCode = 91, areaCode = 999, number = 8888888} }, new Customer { name = "Kaushik", address = "Behala, Kolkata", phone = new Phone {countryCode = 91, areaCode = 33, number = 3333333} }, new Customer { name = "Rahul", address = "Kerala", phone = new Phone {countryCode = 91, areaCode = 00, number = 4444} }};
name =
},
Just trying to write the above piece of code in C#2.0 syntax shows how cool this new feature is.
Why I love this
This feature reduce typing a lot and will go a long way in helping reduce carpal tunnel syndrome :^)
Moreover, it is very intuitive, so much so that people will start using this even without figuring out that this was not present before and they were required to allocate the collection and then individually allocate and add each item to the collection. Just after using it for a couple of days I am badly missing it in C#2.0. I just can't figure out why this was not considered for 2.0. I can guess why but I'll still complain :)
This is the my third post on the series of post I am making on C#3.0 after it got declared on PDC. See the previous two here and here.
It's not that I do not like lambda expression, I just don't like that its being supported in C#. Lets first see what its like and then I'll clarify on why I do not like it. If you are just interested on why I do not like it, go to the end of this post.
What is Lambda Expression
In C#2.0 anonymous methods were introduced ( :( I'm already using past tense on a product that is still not formally released). It required a little cumbersome syntax to create in-line function block like the ones supported by many functional languages. Lambda expressions in C# along with type inference give a cleaner (????) way of declaring and using anonymous methods.
Lambda expressions are based on lambda calculus. Many functional languages like Lisp use lambda notations to define functions. Typical lambda expressions in C# can contain both expressions and or statement blocks.
x => 2 * x // this is a expressiony => {return 2*x; } // this is a statement block
Here the => is the lambda operator.
The following delegate and lambda expression are equivalent and the lambda expression here is automatically converted into a corresponding delegate.
For the lambda expression the type can be explicitly specified or it can be implicit and the complier can figure it out. So the above expression could be written as
Func
Lambda with Extension methods
Writing predicate functions for the extension methods becomes real easy with lambda expressions. The System.Query namespace comes with nifty extension methods which use predicates. The following using the Where extension method prints out all the integers in the array which is less than 3
int
Type Inference and Lambda Expression
When a generic method is called without explicitly giving its type then the compiler can infer the type. In the following case both calls to GenericFunc is equivalent and will print System.Int32
static void GenericFunc<T>(T t){ Console.WriteLine(t.GetType().ToString());} GenericFunc(5); // Type is inferredGenericFunc<int>(5);
static
GenericFunc(5); // Type is inferredGenericFunc<int>(5);
Just like any other expression when a lambda expression is passed as a parameter to a generic function it is used to infer the type. Lets take the following example which is a modified version of the one used in the C# 3.0 spec
delegate R Func<A, R>(A a);// the generic functionstatic Z FuncInfer<X, Y, Z>(X value, Func<X, Y> f1, Func<Y, Z> f2){ return f2(f1(value));} var size = FuncInfer(@"c:\vcvars32.bat", s => new FileInfo(s), t => t.Length);
Lets see how the type inference happens here.
Why I don't like lambda expression in C#
C# has originally developed from C++ /Java and is (was :^) ) a strongly typed object-oriented language. The new features being introduced like closure, continuation (yes, yes very limited continuation) in C#2.0 and now type inference, lambda expressions are de-generating the language. Even though there are people go gaga about continuation and lexical closures these are fundamentally functional language features and should be left to that. Introduction of bits and pieces of functional language features are not going to add value to C# and at the same time the surface area of C# is growing beyond what most developer can grasp.
Every language has a domain of application and an audience. Most people who work in C# developing web-services and web-based applications today are not necessary computer science grads. For them these concepts are a huge variation from the way C# used to behave. Functional programming is for the academia and not from the industry and should be left as such.
If I am asked, whether I'll use these language features, my answer will be maybe, and that is because the code written by me will be reviewed and maintained by people in MS who are fairly conversant with these. However, I think these features add burden to the learning curve of people who are not super interested in C# and should be avoided in favor of easier language constructs’ that might take couple of lines of code more, but would be more readable and maintainable.
These are just my opinions and I'm sure the designers of C# had given a lot of thought before adding them, but I strongly feel that these features are just adding more surface area to the language and will mostly go unused by the masses.
After the declaration of C# 3.0 I went ahead and installed the PDC bits. After reading through the language spec. I was very very very unhappy. I mean we were just getting excited over C#2.0 supporting generics, anonymous mehtods, Nullable types and then suddenly someone ruins all the fun by showing us C#3.0. C#2.0 already appears stale. Some great blogs on this are from Cyrus and Matt Warren
The good part is that since I work in Microsoft, soon (after VS 2005 release I guess) we'd move to C#3.0 to dogfood it. So that means I'll not be required to wait for the super enhancements in C# for long!!!!
I thought I'd try out the features of C#3.0 and write some stuff on it. Here goes the second one (the first is already there)
Extension Methods
With extension methods you can attach additional functionalities to an existing type even if you do not have access to it. For example I can write an extension method Print() which prints each element of any collection on a different line and then invoke it on any collection such as
List<string> first = new List<string>();first.AddRange (new string[] {"Hello", "how"});first.Print();
first.AddRange (
first.Print();
Importantly note is that even though Print() is not a member of List<> but is still called as if its a method. There are a couple of restrictions in defining the extension method Print. All of which are marked in bold in the example below
public static class Extensions{ public static void Print<T>(this ICollection<T> col) { foreach(T t in col) Console.WriteLine(t); }}static void Main(string[] args){ List<string> first = new List<string>(); first.AddRange (new string[] {"Hello", "how"}); first.Print();}
Console.WriteLine(t);
The method has to be a static method in a static class. The first parameter to the method has to be qualified using this and this first parameter indicates the types on which this extension method can be applied. Its important to note that this is just syntactic sugar and both the following calls are equivalent and legal.
first.Print();Extensions.Print(first);
Extensions.Print(first);
So whats the benefit? I think this makes code more elegant and this can be used very much like C++ STL algorithms. Lets say I write a merge algorithm that merges two collections and then I'd be able to call this merge algorithm on any collection in a very elegant way. Following is the implementation of a merge algorithm
using
Moreover the class libarary already ships with some standard extension methods (like standard algorithms of STL) and you can directly use them. Consider the following
int[] a = new int[] {1, 2, 2, 4, 3};Console.WriteLine(a.Distinct().Count());
Here two of the methods Distinct and Count are used and the combined result is that we get the number of distinct elements in the array and that is 4. This is really really cool.
As a real life sample I wrote a pretty print extension method that prints the directory listing is a pretty fashion.
The C# 3.0 spec clearly calls out that since this is not a very discoverable feature and is somewhat misleading (very much like operator overloading) and so should be used sparingly. I think that this'll be more and more used by class libraries to implement STL like algorithms that can be run on containers.
Due to my upbringing in C/C++ somehow I feel uneasy whenever I see some like
var a = 5;
I guess this is ok in scripting languages. So when I heard that C# 3.0 is going to support implicit types for local variables that made me feel uneasy. I installed the PDC C# 3.0 bits (from the link mentioned before) and tried the following
var a = 5;var s = "hello";Console.WriteLine(a.GetType());Console.WriteLine(s.GetType());
var s =
The output was as expected a was System.Int32 and s System.String. However C# 3.0 is supporting implicit types and not the variant data type that many non-typed languages support. So the following will not compile
var a = 5;a = "hello";
a =
Since C# is a strongly typed language once the implicit type has been inferred during compilation it does not change.
While I do agree for things like LINQ implicit type is absolutely required but elsewhere as in the examples above vars make code more unreadable for me. Wherever I'll see a line of code with var I scroll up-down to figure out what type it exactly is. Specially in some situation the type of variable has a lot to do with performance so if I see some thing like
var al = Func1();........for (i = 0; i < 10000000; i++) foreach (int el in al) total += el;
I'd right click on al and say goto definition and see its a var. At this point its super important for me to figure out what's its type. If its an ArrayList and not a List<> then I have a huge perf degradation. Check out Rico Mariani's blog to find out why.
<edited some stuff like the example above to add clarity based on the comments>< Fixed some syntax errors >
Even before C#2.0 is out (RTM) we already have some sneek preview of the C#3.0 features. Check out Cyrus's blog on this. Some time back I had said to some folks here that with some powerful functional programming fans :) in MS we are surely going to see some functional programming features creep into C#. Anonymous methods (lexical closure), continuation (yes I know in very limited format) got into 2.0 and now we have lambda expressions in 3.0.
However I had expected more features from Spec# like contract verification and checked exception to have been introduced. Maybe they will be.
Q.What does a bunch of disgruntled programmers do after work in MS IDC? A. They kill each other and shout with Joy when they see blood splatter all around.
If you do not believe me drop into the 3rd floor lobby at IDC.
Over the last couple of months Halo mania has taken over the IDC Burton (Team System) and DPM (Data Protection Manager) team. We all fight it out on the XBox on the third floor lobby. With the departure of our beloved Froddo who'd prove to be a far better assassin than a programmer, DPM is beating us hands down. However, some of the people in our team are not that far behind and we soon hope to frag DPM guys. The way Neeraj is ramping up on his core competency of shooting people with the hand gun, we soon hope to get our first win against DPM.
Today was an auspicious day. The ladies in our group till now refrained from joining into the blood bath. But today two of them did. The sight of Neeti clapping with joy after killing me really shook me up. I never knew she'd get back to me like this for troubling her with weird bugs (she tests the features I work on :) ).
Application running from the system tray is very common these days. Mostly these applications show an icon in the system tray (beside the clock) and almost always have a pop-up context menu.
Adding additional features like showing text in the tray or show animations is also possible with little code. In this post I have discussed a class I wrote to accomplish this. If you are interested in using this enhanced SysTray class and do not care much about how it works jump to the last section Using SysTray.
First things first: How do you show an icon in the system tray
With .NET doing this is pretty simple and there is no need to play around with NOTIFYICONDATA and Shell_NotifyIcon of the Win32 world.
You just need to create a instance of System.Windows.Forms.NotifyIcon and fill out the relevant fields as in
private NotifyIcon m_notifyIcon;
m_notifyIcon = new NotifyIcon();
m_notifyIcon.Text = text; // tooltip text show over tray icon
m_notifyIcon.Visible = true;
m_notifyIcon.Icon = icon; // icon in the tray
m_notifyIcon.ContextMenu = menu; // context menu
That’s it and the icon appear in the system tray and on right clicking on it the menu is popped up.
Extending the NotifyIcon
NotifyIcon is sealed so you cannot extend by inheritance. So I created a class SysTray which extends NotifyIcon by creating an instance of it in a field. The constructor takes in the tooltip text, the default Icon and the context menu.
This class also adds other methods to show animation and text as explained below.
Showing Text
An application can only put in an icon in the tray. So the workaround is (there’s always one) to convert the text into an icon. ShowText API of the SysTray class just does this.
public void ShowText(string text, Font font, Color col)
Brush brush = new SolidBrush(col);
// Create a bitmap and draw text on it
Bitmap bitmap = new Bitmap(16, 16);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.DrawString(text, m_font, brush, 0, 0);
// Convert the bitmap with text to an Icon
IntPtr hIcon = bitmap.GetHicon();
Icon icon = Icon.FromHandle(hIcon);
m_notifyIcon.Icon = icon;
What we are doing here is creating a bitmap, drawing the text to be shown on it and then converting it to an icon. Since NotifyIcon can show an Icon in the tray it’ll show the textual icon just fine.
Showing Animation
Showing animation in the tray is equally easy by making an array of icons each of which represent an animation frame and then switching the icons in the tray on timer events. SysTray accepts the image frame in different formats
public void SetAnimationClip (Icon [] icons)Here icon needs to be an array of 16x16 icon each for a framepublic void SetAnimationClip (Bitmap [] bitmap) Here bitmap needs to be an array of 16x16 bitmap each for a framepublic void SetAnimationClip (Bitmap bitmapStrip) bitmapStrip is a bitmap strip of size n16x16. Where n is the number of frames. SysTray class extracts the individual frames from this strip and converts it to icons and uses it for the animation.
The last method is the easiest to use. For this you need to prepare an animation strip image. The image needs to have each frame of animation side by side. Each frame is 16x16 pixels and the color to render transparent is the common background of all the frames. Let’s take The caller prepares this image by making it transparent and then calling SetAnimationClip
private void button1_Click(object sender, System.EventArgs e)
m_sysTray.StopAnimation();
Bitmap bmp = new Bitmap("tick.bmp");
// the color from the left bottom pixel will be made transparent
bmp.MakeTransparent();
m_sysTray.SetAnimationClip(bmp);
m_sysTray.StartAnimation(150, 5);
SetAnimationClip uses the following code to create the animation frame
public void SetAnimationClip (Bitmap bitmapStrip)
m_animationIcons = new Icon[bitmapStrip.Width / 16];
for (int i = 0; i < m_animationIcons.Length; i++)
Rectangle rect = new Rectangle(i*16, 0, 16, 16);
Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat);
m_animationIcons[i] = Icon.FromHandle(bmp.GetHicon());
To animate the frame StartAnimation starts a timer and in the timer the icons are changed to animate the whole sequence.
public void StartAnimation(int interval, int loopCount)
if(m_animationIcons == null)
throw new ApplicationException("Animation clip not set with
SetAnimationClip");
m_loopCount = loopCount;
m_timer.Interval = interval;
m_timer.Start();
private void m_timer_Tick(object sender, EventArgs e)
if(m_currIndex < m_animationIcons.Length)
m_notifyIcon.Icon = m_animationIcons[m_currIndex];
m_currIndex++;
....
Using SysTray
This is how you use the class
m_menu.MenuItems.Add(0, new MenuItem("Show",new
System.EventHandler(Show_Click)));
Get an icon you want to show statically in the tray.
Bitmap bmp = new Bitmap("tick.bmp"); // the color from the left bottom pixel will be made transparent
Sources - SysTray Implementation: SysTray.cs
using System;
using System.Windows.Forms;
using System.Drawing;
namespace Abhinaba.SysTray
/// <summary>
/// SysTray class that can be used to display animated icons or text in the system tray
/// </summary>
public class SysTray : IDisposable
#region Constructor
/// The constructor
/// <param name="text">The toolip text</param>
/// <param name="icon">The icon that will be shown by default, can be null</param>
/// <param name="menu">The context menu to be opened on right clicking on the
/// icon in the tray. This can be null.</param>
public SysTray(string text, Icon icon, ContextMenu menu)
m_DefaultIcon = icon;
m_font = new Font("Helvetica", 8);
m_timer = new Timer();
m_timer.Interval = 100;
m_timer.Tick += new System.EventHandler(this.m_timer_Tick);
#endregion // Constructor
#region Public APIs
/// Shows text instead of icon in the tray
/// <param name="text">The text to be displayed on the tray.
/// Make this only 1 or 2 characters. E.g. "23"</param>
public void ShowText(string text)
ShowText(text, m_font, m_col);
/// <param name="text">Same as above</param>
/// <param name="col">Color to be used to display the text in the tray</param>
public void ShowText(string text, Color col)
ShowText(text, m_font, col);
/// <param name="font">The default color will be used but in user given font</param>
public void ShowText(string text, Font font)
ShowText(text, font, m_col);
/// <param name="text">the text to be displayed</param>
/// <param name="font">The font to be used</param>
/// <param name="col">The color to be used</param>
Bitmap bitmap = new Bitmap(16, 16);//, System.Drawing.Imaging.PixelFormat.Max);
/// Sets the animation clip that will be displayed in the system tray
/// <param name="icons">The array of icons which forms each frame of the animation
/// This'll work by showing one icon after another in the array.
/// Each of the icons must be 16x16 pixels </param>
public void SetAnimationClip(Icon[] icons)
m_animationIcons = icons;
/// <param name="icons">The array of bitmaps which forms each frame of the animation
/// This'll work by showing one bitmap after another in the array.
/// Each of the bitmaps must be 16x16 pixels </param>
public void SetAnimationClip(Bitmap[] bitmap)
m_animationIcons = new Icon[bitmap.Length];
for (int i = 0; i < bitmap.Length; i++)
m_animationIcons[i] = Icon.FromHandle(bitmap[i].GetHicon());
/// <param name="icons">The bitmap strip that contains the frames of animation.
/// This can be created by creating a image of size 16*n by 16 pixels
/// Where n is the number of frames. Then in the first 16x16 pixel put
/// first image and then from 16 to 32 pixel put the second image and so on</param>
public void SetAnimationClip(Bitmap bitmapStrip)
Rectangle rect = new Rectangle(i * 16, 0, 16, 16);
/// Start showing the animation. This needs to be called after
/// setting the clip using any of the above methods
/// <param name="loop">whether to loop infinitely or stop after one iteration</param>
/// <param name="interval">Interval in millisecond in between each frame. Typicall 100</param>
if (m_animationIcons == null)
throw new ApplicationException("Animation clip not set with SetAnimationClip");
/// Stop animation started with StartAnimation with loop = true
public void StopAnimation()
m_timer.Stop();
#endregion // Public APIs
#region Dispose
public void Dispose()
m_notifyIcon.Dispose();
if (m_font != null)
m_font.Dispose();
#endregion
#region Event handlers
if (m_currIndex < m_animationIcons.Length)
else
m_currIndex = 0;
if (m_loopCount <= 0)
m_notifyIcon.Icon = m_DefaultIcon;
--m_loopCount;
#endregion // Event handlers
#region private variables
private Font m_font;
private Color m_col = Color.Black;
private Icon[] m_animationIcons;
private Timer m_timer;
private int m_currIndex = 0;
private int m_loopCount = 0;
private Icon m_DefaultIcon;
#endregion // private variables
Sources - SysTray Usage: Form1.cs
using System.Collections;
using System.ComponentModel;
using System.Data;