#Google Analytic Tracker

Pages

Dec 12, 2008

C# Casting using Extension Method and VS2008 Debugger Issue

 

Since the creation of extension method in C# 3.0, my college and I have been happily writing extension methods which make our code look a lot nicer.

Then, I was surprised by my college when he took leverage of this by create an extension method for casting. Why not using the normal C# casting syntax?

   1:  public static TTargetType To<TTargetType>(this object oObject)
   2:  {
   3:      return (TTargetType)oObject;
   4:  }

Initially, I didn't like this idea too much, because it does have disadvantages when using a method to do casting:

The advantage of this method is that it makes typecasts way cleaner. The disadvantages are that you'll have to go one level down the stack trace to debug properly, and some erroneous casts might not get caught by the compiler.

However, after using the extension method for cast a couple of times, I really like use it. It does make the code a lot cleaner to read. In fact, whenever I notice my assignment is incorrect as I type, I can immediately hit the dot key to casting instead of moving my cursor back to the being of variable and type out the C# cast syntax:

   1:  private bool ApplyUnsplitWorkWorker(object[] oArgs)
   2:  {
   3:        sch_WorkData oUnsplitWork = oArgs[0].To<sch_WorkData>();
   4:        sch_WorkItemData[] aUnsplitWorkItems = oArgs[1].To<sch_WorkItemData[]>();
   5:        sch_WorkItemData oDeletedWorkItem = oArgs[2].To<sch_WorkItemData>();
   6:        sch_WorkData oDeletedWork = oArgs[3].To<sch_WorkData>();
   7:   
   8:  //...
   9:  }

Check out the bottom two examples , see which one you like more:

private string SomeMethod(DataRow oRow)
{
    //Extension cast
    return oRow.To<EmployeeRow>().Department.To<MathDepartment>().MathRoomCount.ToString();
}

private string SomeMethod2(DataRow oRow)
{
    //C# Cast
    return ((MathDepartment)((EmployeeRow)oRow).Department)).MathRoomCount.ToString();
}

In addition, there is as a extension method for casting that return a null if object is null or default value (such as DateTime), and an extension method for "as" syntax.

Yesterday, I encountered an exception when I was running a project. When I try to debug the issue, to my surprise one of the objects can't be analysis by the debugger, neither can it be display in the Watch Windows or the Immediate Windows. For testing, I create an extra variable call "l_oWorkItemRow2" using .C# casting, so that I can compare with "l_oWorkItemRow1"

Before:

 

Once I continue hit next line in the debugger, a null reference exception occurs:

What's going on? Why am seeing the variable properties saying "threw an exception of type 'System.NullReferenceException'"...

In fact, occasionally the debugger failed to analysis the property value in certain stack. If I move the debugger back to one stack where I pass the value, that I could than see the value.

The question is why the debugger was able to analysis the regular casting, and not the extension method cast. Is it just a current limitation to the debugger, or it is actually a bug? For example, do you know that only certain cases you can do "Edit and Continue" in the debugger.

Anyhow, if I find out more about this strange behaviour, I will definitely write another post!

Dec 9, 2008

Funny Articles

Man... it has been awhile since I put a new article. Originally I was going to talk about my experience on using Model-View-Presenter in a number of my project. Sadly I don't have the heart to write anything about it right now, mostly due to the amount of programming I have to do at work. I have rather focus on reading funny articles, like the followings:

http://www.murphys-laws.com/murphy/murphy-computer.html

http://en.wikipedia.org/wiki/Unusual_software_bug

http://www.workjoke.com/programmers-jokes.html

http://www.laughitout.com/2007/10/10-programming-quotations.html

26 Ways To Know Your Software Development Project Is Doomed
http://www.cio.com/article/print/470103

Anyways, that's all...

Jul 1, 2008

Interesting License

Typically, when you read a particular software license, it usually says you have a 30-day trial period and you are required to purchase the software afterward.  Recently, I read an article on the 10 Great Software Program You Can Get Gratis on TechNewsWord, and I was interested installing WordWeb 5.1.

Occasionally, I read the software license before I install it, or at least skim through it.

Here is the first paragraph of the license for WordWeb 5.1:

WordWeb free version may be used indefinitely only by people who take at most two commercial flights (not more than one return flight) in any 12 month period. People who fly more than this need to purchase the Pro version if they wish to continue to use it after a 30-day trial period.

The first time I read it, I asked myself did I click the correct hyperlink. After reading on the license, it turns out that the person who wrote this license concerns about the environment. He/she wants you be aware of how much greenhouse gas you produce each time you take the flight.  I don't know how many user will take this seriously, but at least it get the message out.

May 21, 2008

Customizing a Base Class Static Members thought its Derived Class

In my programming experience, it usually doesn't make sense to customize a static member. In short, implementing a static member is not part of the object orientated programing technique.

In C#, at least as far as I know, you cannot override a static member. For example:

   public class MyClass
   {
        //Compiling error: Overridable method cannot be static
        public static virtual void Do(){// Do something}
   }
   public class DerivedClass : MyClass
   {
        public override void Do(){// Do something else}
   }

A static method is like a global method that can be called anywhere in your code without instantiate an object. Therefore, it doesn't make sense you can override a base static method.

A Situation when Customizing a Static Method is Needed.

Last year, I needed to create a brunch of data access classes. A data access class's primary purpose is to retrieve and transfer data between an application and a database. In design, you would expect you to see something like this:

MyVehicleData vehicle = new MyVehicleData();
//...
//... Do something with vehicle object
//...

//Save to database
vehicle.Save();
However, what if you want to write Select()? Does it make sense that you need to instantiate an object and then call the Select()?
MyVehicleData vehicle = new MyVehicleData(); 
vehicle.SelectByKey("somekey");
Instead, you probably want to do something like:
MyVehicleData vehicle = MyVehicleData.SelectBykey("somekey");

The above SelectByKey() method is a static method. In the code, most likely you can hardcode your select SQL.

What if you want to 100 data access classes?

As a smart lazy programmer, you don't want to hardcode your SQL statements for every business objects. You want to write a base class to save you time from repetitive coding. Even better, you can write a code generator to create your data access class. However, code generation is outside of my discussion.

This is what we would like:

// We want to do something like this:
// NOTE: This is just an idea, you will get compiling error
public abstract class BaseDataAccess<TDataAccess>{
    protected static string selectSQL;

    // Returns an instance of Data Access object of type TDataAccess
    public static TDataAccess SelectByKey(string key)
    {
        // note: RunSQL get column data based on the select SQL and the parameter
        string[] retrievedData = RunSQL(selectSQL, key);
        
        T result = TDataAccess.CreateData(retrievedData);
        return result;
    }
    
    // Creates a new instance of TDataAccess based on database values
    // Note: Compiling error: you can't have static method in with abstract declaration
    public abstract static TDataAccess CreateData(string[] values);
}

Solution

In the above example, it won't compile because abstract static is not allowed.  From the start, it doesn't make sense you can decorate the base class though its derived classes. This is time when Generic come into rescue. The solution is to create an instance of the derived class within the generic base class static constructor.  Please take a look at the following example:

// Don't get confused by the following declaration. What it said is that when you deriving // from this base class, you have to pass in a type that is also a // based from BaseDataAccess<TDataAccess>.public abstract class BaseDataAccess<TDataAccess> : where TDataAccess : BaseDataAccess<TDataAccess>, new()
{
    protected static string selectSQL;
    protected static BaseDataAccess<T> instance;
    
    // This is a static, it only run once!
    static BaseDataAccess()
    {
        instance = new T();
        selectSQL = instance.GetSelectSQL(); // virtual method call
    }

    // Return a instance of TDataAcess from database
    public static TDataAccess SelectByKey(string key)
    {
        // note: DataManager.RunSQL get data based on the select SQL and the parameter
        string[] retrievedData = DataManager.RunSQL(selectSQL, key);
        
        T result = instance.CreateData(retrievedData);
        return result;
    }
    
    // Create a new instance of TDataAccess based on database values
    // Note: Compiling error: you can't have static method in with abstract declaration
    protected abstract TDataAccess CreateData(string[] values);
    
    protected abstract string GetSelectSQL();
}

public class DerivedDataAccess : BaseDataAccess<DerivedDataAccess>
{
    // Parameterless constructor, this allow the base class to create an instance of its derived class.
    public DerivedDataAccess()
    {
    }
    
    public DerivedDataAccess(string[] values)
    {
        //Initialize your object;
    }
    
    // override the CreateData, this is how you customize the behaviour of your base class
    protected override DerivedDataAccess CreateData(string[] values)
    {
        DerivedDataAccess result = new DerivedDataAccess(values);
        return result;
    }
    
    protected override GetSelecteSQL()
    {
        // This virtual method will be called by base constructor, it should only use constant data
        return "select x, y, z from someTable";
    }
}

By using generic, the compiler create many type of base class for you. In addition, you instantiate a derived object so that you can get the information from the derided class.

Note that your base class static constructor only execute once, it won't re-initialize the base static constructor when you call "instance = new T()", hence, there is no infinite loop.

Also, you need to specify the where TDataAccess : BaseDataAccess<TDataAccess>, new() so that you can call the base class method. By specifying the generic type to be the BaseDataAccess, you can call the derived class virtual methods.  Just a side note, be careful when you call a virtual method in the constructor, because your object is not initialized, therefore any dynamic data will not be setup for your implemented virtual method to use.  The new() tells the compiler that your class support parameter-less constructor. Therefore you can instantiate a generic type though new T();

As a result, you can no do the following:

DerviedDataAccess myDataAccess = DerviedDataAccess.SelectByKey("someKey");

Final Thought

When I did this program, I was still using C# 2.0. However, in C# 3.0, the above idea can also be achieve by partial method.  In any case, it is still a neat technique.


 

May 9, 2008

Python Design Patterns

Design Patterns, one of the must known tool set for software developer, there is a very good video that talks about design pattern.

http://www.catonmat.net/blog/learning-python-design-patterns-through-video-lectures/

Even though the example is presented in Python, but the concept is the same, and it applies to other OO programming languages.

Also, for those who want a introduction of Design Pattern.  I recommend you get the First Head Design Patterns.  This is a very good introductory book for design pattern. Don't get scared if you don't know Java, it is very easy to understand.  I used it whenever I need ideas for solving architecture problem, or it is simply something to discuss with your colleges when you are bored at work! :)

May 8, 2008

No files were found to look in. use Ctrl+Scroll Lock!

 

Credit goes to: http://blogs.ugidotnet.org/franny/archive/2005/12/08/31303.aspx

Today, one of my colleges ran into a problem. He click on "Ctrl + Shift + F" to open the Find and Replace dialogue, and he tried to find a string in his solution.

image 

The text that he wants to search is right in front of his eyes, yet clicking on the Find All button only returns: "No files were found to look in.Find was stopped in progress."

He thought that he must be tired today.  Double check his spelling, his cap lock, and all other options. There it goes his 1/2 hr of work.  So, he came over to me to make sure that ensure that he is not hallucinating.  I said no, surely something is wrong with VS.

Another one of my colleges overheard our conversation, and said, "Try Ctrl + Scroll Lock".  WT..., how does Ctrl + Scroll Lock helps to solve this issue? Surprisingly, it worked!

The annoying part is that there is no explanation on how you get into to this state and how to fix it.  Obviously, no one will spend time continue investigate into this, because your main job is to develop your product and not debugging your development tools.

I suspect this maybe due some incorrect interaction between Visual Studio and the OS layer. The Scroll Lock button is rarely being used in modern software. In the past, when people still uses text-based UI, this button is used to make the arrow key to scroll the contents of the text window instead of moving the cursor.

Apr 8, 2008

Process cannot access the file! Please close your XmlReader!

At work, we have many scripts and utility programs to aid us in testing and developing our product.

After upgraded to VS 2008, I notice that one of utilities that I run regularly no longer working.

Here is the error that I got:

The process cannot access the file 'c:\xxx\yyy.xml' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, Fil
eOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.Xml.XmlDocument.Save(String filename)
   at GenRes.GenRes.Main(String[] args) in C:\xxx\GenRes.cs:line 191

I asked all my colleges, and they don't have any problem running this utility.

Struggling with the fact why my computer doesn't run the utility properly, I start debugging line by line in VS.

Looking into the GenRes.cs file, it is what it tries to do.

// Load Data to XmlDocument
XmlDocument xmlStringsdoc = new XmlDocument();
xmlStringsdoc.Load(XmlReader.Create(args[0] + ".xml", settings));
//...
// Save Data back to the xml file
xmlStringsdoc.Save(args[0] + ".xml");

Strangely, when I run the utility in the debugger, I don't get any error.

Not really sure why (which I hope I eventually find out), I decided to see if I can fix the code so that it will work on my machine, and hopefully it will works on others too.

By analyzing the code, most likely I get this error because XmlReader isn't close when xmlStringdoc try to save the data.

Looking into the revision of the file. I notice that one of my college changed the following:

//FROM xmlStringsdoc.Load(args[0] + ".xml"); // TO
settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
xmlStringsdoc.Load(XmlReader.Create(args[0] + ".xml", settings));

It turns out that we don't want to prohibit DTD when process the file.

Here is the simple fix

   1: XmlReader l_oXmlReader = XmlReader.Create(args[0] + ".xml", settings);
   2: xmlStringsdoc.Load(l_oXmlReader);
   3: // Close the reader since it is no longer needed
   4: l_oXmlReader.Close(); 

All I have done is CLOSE the reader! After testing the code, it works.

Here is the reminding questions I want to know:

  1. Does XmlDocument.Load(string) automatically close the file?
  2. Why this issue only happen on my machine and not others, is there some kind of  windows or .net framework setting?
  3. How can you write a unit test to ensure this utility work on all developers machine?
  4. How come I don't get an error when running the code in Debugger?
  5. Why does the error message say the file is being used by another process (but in fact, it is the same process that accessing it)?

Hopefully I can answer this question in the future.

Mar 16, 2008

Visual Studio Installation Strange Disk Space Requirement

Recently I attended "Hero Happen Here" event in Calgary, and obtained a copy of Visual Studio 2008 Standard Edition.  Similar to the Visual Studio 2005 lunch event, everyone get a copy of Visual Studio Standard edition. But since this is my first time attending such event, I was pretty excited that I got my own Visual Studio 2008.

After I got back home, I immediately uninstall my Visual Studio 2008 beta version.

Surprisingly, the first error that I encountered is not during VS installation (although I usually have faith that VS will install properly), but rather when I uninstall the beta.

"no disk Exception Processing Message c0000013 Parameters ...."

By doing a quick google search, I found this forum.  I recalled that I installed the beta from a external hard drive. I must have removed the VS 2008 installation file or changed the drive letter. My quick fix was to unplug my external hard drive, and uninstall the beta. But really, a software shouldn't need to check for disk during un-installation.

Anyhow, here is what strange about my VS 2008 installation experience. Notice my installation path is on C drive, but the Disk space requirements show that I need 204 MB on my E drive.

Strange VS Installation with Hightlight

My E drive only stores my media files like music. I never use this drive for program installation of virtual memory mapping.

After I installation, I checked my E drive and it doesn't seem to have any extra file installed. It would make more sense if it is D drive because this is where I store my user profile!

Mar 11, 2008

My First Experience with xUbuntu

Awhile ago, I promised my sister I would format her laptop. Her laptop, a SONY VAIO FX340 (800Mhz), has a broken LAN port and a broken memory slot. Her laptop can only run on 256 MB RAM max and has connect to Internet though D-Link 650 Express card.

Minimum Requirements

Initially, I downloaded Ubuntu and tried to install it.  However, every time I select the "Start and Install Ubuntu" or the "VGA Mode" in the boot up screen, I only got a blank screen. After doing some researches,  it turns out that Ubuntu needs a minimum of 387 MB.  I stumbled upon a forum about xUbuntu. It turns out that there are number of "spin-off" projects that based on Ubuntu.

xUbuntu uses a different desktop environment call Xfce. I am guessing this interface require less memory, because its minimum requirement is 128 MB.

Download

Download Ubuntu is easy and extreme fast. Using P2P Bit Torrent, I got up to 600kB/sec from my cable Internet. Man, I never see this kind of speed before using cable internet. I am so glad I switch from ADSL to cable! There are many peers and seeds out there so you won't have issue downloading it.

Installation

First, I used to start up xUbuntu using the first boot option. Well, it didn't work, it definitely related to the video card.  So I start up xUbuntu using VGA mode. After 10 minutes of loading... it loaded! a very small 640 x480 screen shows up.

The reason why it takes awhile to load is because it loads the core system to your RAM only. This mean you can literally run Ubuntu from a CD ROM without effecting your Windows XP system. This is an EXCELLENT idea, because it allows me to test and experience Ubuntu before I decided to install it onto the harddrive!

i.e. if you can't run Ubuntu just from Live CD, you may have trouble installing it. You are better to do more research before installing it.

However, it was impossible to run the installation with 640 x 480 screen. The installation dialogue box was much larger (no resize available) than the screen resolution. After some clicking around, I find that going though Applications->Settings->Screens and Graphics allows me to change the video card. Fortunately, xUbuntu comes with a number of video drive. The laptop uses Intel 815, which I quickly find it. After changed the video and resolution. xUbuntu requests me to logout so that changes can take effect.

Ah ha! Here was the problem. After I logout to the main screen, I have no idea how to log back in because I don't know the default user. I tried login as root and xUbuntu disallow me to log on using Xfce Session. The ultimate solution is to restart the machine. However, my video card setting didn't get persisted after restart.

To work around this issue, I created another user.  Luckily 80% of the Create User dialogue box fit on the screen.  After I changed the video setting, log out, and log back on, everything works accordingly. Btw, I did figured out that the default user is "ubuntu" by random guesses.

Installation is very easy, only 7 steps!  There was no interruption, other than it complained it can't get the latest security update because it had no Internet connection.

Also, my D-Link 640 was automatically detected and ready to use. It seamlessly installed the driver for it.

Desktop Screenshot

In the screenshot, GIMP is a very featured graphical editor. It supports layering and many effects you can use, and it is FREE!

Add/Remove Application

xUbuntu comes with this nice application call "Add/Remove Application", similar to Windows Add/Remove.

I opened it up, and the first trouble I had with xUbuntu was downloading new applications, even though it showed me a list of available application.  My problem is exactly mentioned here:

http://ubuntuforums.org/showthread.php?t=629621

Thanks to the strong community, it was that hard to find the solution.

Unlike like MS Windows, where you have to go online and click download for new software, the Linux community has setup a free applications repository for download. You can easy browse all available software and install the one that you selected.

I was surprised the number of freebie you can download. It even comes with the popularity rating.

Add Remove Application Screenshot

The Terminal

The one last problem that I needed to resolve was a crashing Terminal. Here is the problem and solution:

http://ubuntuforums.org/showthread.php?t=417661

I was surprised Linux would have a problem when opening a terminal. Terminal in Linux is essential for administrative works.

Notice that since my terminal doesn't work, I have to logon to Failsafe Terminal Session in the logon screen so that I can edit the configuration file using my all time favour editor, pico.

Menu Screenshot

Reasons why you want to use Ubuntu

A. You got tire of Windows XP (note that I didn't say XP is bad or worst than Linux, XP has many advantages too).

B. You need an OS that run fast though highly customization on a relatively slow machine.

C. You want to startup a business with low budget that still uses legitimate software. (you SHOULD use legitimate software) You can download a lot of free Linux software!

Is Ubuntu Ready for the Average Joe?

Well, I say Ubuntu is getting there, but not quiet yet. From the Desktop user interface perspective, it is definitely ready. Anyone who has experience with Windows XP should have much problem using Ubuntu. 

However, there is some fundamental ideas that the average XP desktop user need understand.

1. It is the idea of security, the different between root user and standard user.

2. User will need be comfortable editing configuration files.  There still a lot of configuration issue that can only be solved without a friendly Graphical User Interface (GUI).

3. The file system. The idea of mount to a physical storage, instead of the Window drivers from A to Z.

File Manager

Note there is no C, D, or E drive in the screenshot. Only directories or folders.

Linux Desktop environment has get to the point where you barely need to do command line. Thanks to the Linux community and the open source projects.  A lot more average joes can use Linux OS.

Nevertheless, MS Windows will still be dominated OS.  MS had spend a lot of money and marketing to get software company to write drivers for it, and ensure that its OS works in almost every PC.  This is what consumer pay for, it is the services and consistent support of the software. That is also one of the ways for open-source developers to earn money, it is the services and business solutions they provide.

Mar 6, 2008

Funny FireFox Bookmark Rendering!

I don't know when did it happen, but I better not play badminton!

In case you didn't get my joke from my above statement. Basically what happen is that FireFox incorrectly used the Coding Horror icon for my Calgary badminton link. Notice that I have subscribed to the Coding Horror RSS. The icon should be used beside the Code Horror RSS.

image

Hopefully this won't happen in FireFox 3. Maybe I should put this on "This is Broken".

Feb 5, 2008

What is Software Engineering

Recently, I find an interesting article on Slashdot about software engineer in Canada. Basically in Canada, the title "Engineer" is reserved specifically for licensed engineer under CCPE (Canadian Council of Professional Engineers). I read one person comment about saying that there is not such thing as software engineering.

I totally disagree, so I wrote the following comment:

" Hi, I have to disagree the following points that you made about software engineering:

A. "there's no way to learn software engineering the way Engineering disciplines are learned."

B. [Software] discipline simple doesn't exist.

C. "cannot use mathematics" design system software.

From my study in my computer engineering courses, we learn what is software engineering. Software Engineering doesn't mean just "programming", it involves many other aspect of software development, like collecting specifications, designing, implementation, testing and software maintenance.

In design phrase, software engineers have to consider the cost, quality, reliability, delivery time and many other matters just like any other engineer in the traditional disciplines.

Although it seems to there is no mathematically involve in general software design, but if you take computer science courses, you learn that your software performance rely on mathematical calculation (i.e. O(n)). If you are working on assembly level software development, you definitely require mathematically skills to solve complex problem because your software is limited by your hardware performance (memory and speed).

Just like any other engineering, software quality also based on statistic and software engineering models. Think about highway engineering, the quality of the road material is mostly base on statistical calculation. In software engineering, we have Lines of Codes, function-points, function metrics measurement and many others determine the software quality, maintainability and flexibility.

So, what is the obvious difference comparing to other traditional engineering fields? 1. The cost of correcting an engineering mistake is a lot less. If your bridge design is incorrectly, it will cost a lot rebuild or re-enforce bridge compare with solving software deflect. 2. Software “usually” doesn't have a direct impact on public safety. Billing system maybe a bad example, but think others, like automobile, airplane, traffic light, it is controlled by software. If the software crashes, it could cause death.

Unfortunately because software engineering doesn't have a total clear understand among the public, and mostly not even to CCPE I bet, therefore it is hard to distinguish one from a software engineer to just a programmer. It is probably very hard to have regulation on software that require engineer's stamp because the definition is not clear.

Does medical charting software require an engineering stamp before it can be use in a hospital? What happen if there is a defect in the software and doctor incorrectly prescribes drugs which cause a patient to die?

It is pretty much impossible to write a useful software that is flawless, even a bridge cannot participate every possible environmental hazards and combinations. It can be statistically said a bridge can last for 200 years, but it is not definite.

If you do claim yourself to be a software engineer, you have to do your job professionally with high standard and due diligence. This is a standard and common ground for all engineers in Canada. And yes, software engineering stream (usually from Computer Engineering discipline) does exist in a number of Universities in Canada. "

Feb 3, 2008

Some .NET Application Security Experience

While there are so many hype on .NET Framework 3.0 and 3.5, I am still studying .NET 2.0 for a MCTS exam.

In my past experience, I rarely deal with .NET programming using its build-in security framework.

Introduction

CAS (Code Access Security), is a .net security system that allow administrators to control .net application authorization to the OS resource. This security system ONLY works for .NET application (or managed code). It can't have security control on (unmanaged code).

For example, say your .NET application called a Excel COM library function, or calling a dll imported function, even you set your .net application no write access to C drive, it only means within your .NET application has no access to write on C drive. Your unmanaged dll will still able to write access to C drive as long as your OS allowed it to.

Layers of Security

Here is the basic security layers on how a user get access to the computer's resources:

  User's Action (i.e. click a button)
Your Application .NET Application Assembly
  .NET Framework CAS
  Operation System Security (i.e. Windows RBS)
Resources: Hard Disk, Registry, Printers, etc...

RBS - Role Base Security (Security based on user credential such as Administrator, Power User, System User, Guest, etc)

The first line of your application security defence is your .net assembly itself. You can prevent user from access resources programmatically. However, when you are running an unknown assembly that you are not comfortable with (say you downloaded a program, but don't want this program to access your C:\Windows\ directory, this is where CAS comes into play. Depending on the type or how your assembly is beginning execute (i.e. execute from web vs. from local computer) and etc, different permissions can be apply to your assembly.

However, even you give a write C:\ drive permission on .NET CAS level, if your OS doesn't allows your application to write to C:, say you log on as a Guest, .NET Framework will throw you a System.UnauthorizedAccessException.

How to configure the CAS

Other than using .NET Framework Caspol tool, which is usually located at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Caspol.exe, you should use the NET 2.0 Framework Configuration Tool.

Go to Control Panel -> Administrative Tools -> Microsoft .NET Framework 2.0 Configuration.

image

Under the Runtime Security Policy tree node, you will find all the CAS related settings.

In general, all assembly execute with something call Evidence. Evidence is basically your assembly's identification. Evidence can be the assembly's hash code, its Strong Name, its URL that it downloaded from (i.e. www.microsoft.com/assembly.exe), its site (i.e. www.microsoft.com), publisher or its Zone. Please refer to Evidence Class for details

image

Basics

First, when your assembly runs, it has to check though all 3 levels (Enterprise, Machine, and User). Your assembly will be checked though all 3 levels. CAS will takes the minimal set of all 3 level permissions. So say if under machine level, your assembly can't write to C:\Windows, even on Enterprise or User allows your assembly to do so, CAS will not let your application to write to C:\Windows.

Second, when CAS elevates your assembly for each level, it determines which "code" your assembly belong to. Is your assembly running under "My_Computer_Zone", or under "Internet_Zone" (see above diagram). An assembly can beyond to multiple code. For example, it can be in a "My_Computer_Zone", while it is also in "MyCodeGroup" (a custom one that I personally made) . CAS will take the union of all the code group and combine together them together.

If you don't want your application to have multiple permission, you can set the "This policy level will only have ...." option in the code group setting.

image

This way, even your assembly has access write to c:\ drive because it belongs to "My_Computer_Zone", since you set this option, the My_Computer_Zone no longer apply (like a intersection, instead of union) .

Membership Condition

In each code group, you can set the "Membership Condition". You can say if your assembly run from a specific URL, it will belong to this group, or if your assembly has a particular strong name, it will belong to another group. You can even made your custom condition, which I personally have no idea how to make one.

Example (any assembly has this Strong Name belong to "Local_Shared_Folder" code group that I made):

image

Permission Set

Notice that by default, .NET 2.0 configuration comes with these permission sets.

Permission Sets Name Brief Description
FullTrust Unrestricted access to all protected resources
SkipVerification Grants assembly right to bypass the verification
Execution Permit assembly to execute (doesn't mean it can access protected resources!)
Nothing Denies all resources, not even execution (Of course, if the assembly has skipverification permission, it can easily by pass this nothing...I guess)
LocalIntranet Some default permissions ideal for local intranet application
Internet Some default permissions ideal for Internet application
Everything Allows unrestricted access to all resources covered by .NET build-in permissions.

For example: My_Computer_Zone's permission set is "FullTrust", while Restricted_Zone's permission set is Nothing. If your assembly happens to have both of these zone (which it shouldn't), since CAS takes the union of all permission, your assembly will still able to access the FullTrust permission sets. That's why the option of setting policy level with the only grant permission helps.

The Everything Permission Set

Here is a list of all the build-in permissions.

image

Declarative and Imperative Security

Here is the confusing part about CAS and this "declarative and imperative security" when I first study the .NET security.

Since now you know how administrator can limit your assembly to access certain resources, as a developer, you should write your program to participate in the event when your assembly runs into security problems.  Otherwise, your assembly will get a very unfriendly System.Security's exceptions and your application has no idea what to do other than crashed.

Note that if your application are has the "FullTrusted" permission, nothing will matter because CAS will not check any permission when running your assembly.

Declarative Security Check

Basically all declarative security is done though the Permission Attributes . By applying declarative security check to your class or your methods, if the check failed, none of the code will run. For example:

[FileIOPermission(SecurityAction.Demand, Write = @"C:\Documents and Settings\Administrator\Something.txt")]
private void DeclarativeCreateFile()
{
    Console.WriteLine("Prepare to write to Administrator folder");
    CreateFile(@"C:\Documents and Settings\Administrator\something.txt");
    Console.WriteLine("Write completed");
}

Because we used declarative security check to "demand" if we have the right to write files under the Administrator folder, NONE of the code in this DeclarativeCreateFile() will run. When calling this method, you will get an System.Security.SecurityException.

Also, with declarative security, .NET Framework has provided some tool to check if your application can run under certain permission. I am guessing since we uses attributes, the runtime can use reflection to find all the declarative security check.

Imperative Security Check

To me, imperative security is a more refine way to check an assembly permission rights. Here is an example:

private void ImperativeDemandCreateFile()
{
    FileIOPermission writeFilePermission = new FileIOPermission(FileIOPermissionAccess.Write, @"C:\Documents and Settings\Administrator\something.txt");
 
    try
    {
        Console.WriteLine("Prepare to write to Administrator folder");
        writeFilePermission.Demand();
        createFile(fileName);
        Console.WriteLine("Write completed");
    }
    catch(Exception ex)
    {
        Console.WriteLine("Failed before attempting to create file. ");
    }
}

In the above example, if CAS doesn't give permission for this assembly to write to the administrator folder, the "writeFilePermission.Demand()" will throw you an SecurityException.

There are definitively different advantages of using imperative compare to declarative permission. Please refer to http://msdn2.microsoft.com/en-us/library/aa302422.aspx for more details.

Evaluating your Assembly

Since an assembly can belong to multiple code group, how can you tell what permission it has in the end? You can uses the .NET Framework 2.0 Configuration, click on "Runtime Security Policy" and you will see a link "Evaluate Assembly" on the right panel. Click on the link, select a .net assembly in the wizard and it will tells you what permission your selected assembly has.

Conclusion

CAS is very powerful, but yet I feel that it is hard to master it because of its flexibility and complexity.  I guess the only way to master this technology is to apply it in your daily programming routine. Especially when security is becoming a important issue. We can't expect all our user will run our application in Administrator mode. Therefore our application has to handle situations where the application has no permission to access certain resources.

Jan 28, 2008

R4 DS Hardware Compatibility Issues

Yesterday my sister got her so call "R4" card for her Nintendo  DS. It is basically an adaptor for micro SD card to the Nintendo DS game slot. (hmm... I am thinking about interface and adaptor design pattern).

Anyhow, thing should look very simple, my sister's friend uploaded some nds files (games) to the micro SD and she tries to run it. First we saw “硬件版本不兼容”.

This basically translated as "Hardware version not compatibles". So, what's going on???

Why does it display a Chinese Error message?

First, the NDS is brought in North America from a legitimate store. It's default NDS rom is in English. 2nd, the loaded R4 kernel is in English.

After trying a different version of English Kernel, and reload the firmware file by formatting the SD, same error message pop ups. So I decided to try the simplified Chinese kernel, which can be download here. Just look for the v1.15 link for those who can't read Chinese.

Finally, that fixes the problem.

It turns out that the NDS hardware has regional specification (i.e. not all NDS sold in the world has the same hardware). If it has different version, I can see why, but regional difference, I don't really get it. Especially when your NDS runs with an English UI.

Here is the explanation that I got from a Chinese site:

Q:启动的时候显示“硬件版本不兼容” w!RK\Q�  
A:R4 的硬件是分区域的:中文版(含简中版和繁中版)、英文版、日文版等,相应的内核也分中文版(含简中版和繁中版)、英文版、日文版等,内核版本必须和硬件版本一致(中文版硬件可以使用“简体中文版”和“繁体中文版”内核),否则会显示“硬件版本不兼容”。 (C{#O&j[V  

Basically it tells you that you need the proper R4 regional version kernel to run on your NDS.

In conclusion, the first thing R4 kernel should fix up is have its kernel support multiple regional hardware. 2nd, it should allow the user to pick its own regional UI (like English, or Chinese interface). Also it should come with a better error description than just a simple "hardware incompatibility issue" message, not sure if this is a Nintendo's message or R4 message. It looks like it is NDS internal error message since I uploaded English R4 Kernel and it display a Chinese error message. I guess that the manufacturing ("intentional or intentional") uses different region hardware to build the NDS, either to save money, or time. The result is that when you buy NDS, you may end up with hardware that have different regional specification than the market region.

Jan 22, 2008

Holy... 8 CPUs for Windows Server 2008

Recently I was given a task to write some small program for Windows 2008. We got the release candidate, and our company recently bought a new server. That's right, the machine has 8 CPU in it, each runs at 1.86 GHz.

I heard machine with 16 CPUs before for real time simulation, but today it is my first time to log on to a machine that has more than 2 CPUs (Core Duo 2).  I am so excited that I have to take a screen shoot of it, just like anyone who take picture of their pizza on their blogs.

image

Now this is what I call "multi-tasking"!

Jan 20, 2008

Bad Error Message : System.IO.Filenotfoundexception in Visual Studio 2005 Designer

 

Have you ever use Visual Studio Form or User Control designer?

Have you ever run into construction error where the designer can't display your form?

Well, if you use Visual Studio, you would most likely have encounter error displaying your form if you:
A. manually manipulate the designer file (i.e. myForm.designer.cs)
B. you add runtime code to the form/user control's constructor causing your designer not to load.

Today, as I was working on my project, I don't know what I did to the code, but when I open my main form on the designer, Visual Studio crashed, and I got the following error:

image

At first, I thought it is something to do with the ActiveX control that I was referencing. I unregistered it and re-register it. No help at all. After I start playing around with my code by recreating my project, I found out what I did wrong.

It turns out that I add a System.Threading.Timer object to one of my user control's constructor. For example:

public partial MyUserControl : UserControl
{
//....
System.Threading.Timer myTimer = new Timer(DoSomeWork, null, 0, 180000);
//....
}

Since the user control is in any project, VS didn't crash until I rebuild the project and I reopen my main form that contains this user control. The confusing part is that instead of seeing error like the following, VS crashed and ask me to restart.

image

Hopefully the designer in Visual Studio 2008 will improve error handling and not crashing Visual Studio.

Jan 18, 2008

Select Statement for DataSet with Complex Data Type

I have been very busy with a lot of stuff, I almost forgot that I have a blog. This post will be my first post in 2008.

In the project that I was working with, we never use complex data type for our column in a DataSet (System.Data.DataSet). If you uses Visual Studio DataSet Designer, you will notice that the default DataType for your column are either .NET value type, string, TimSpan, Guid, DateTime.

What if you want to use your won DataType?

Surprising, the dataset designer works with custom data type. For example:

image

The Column DSTestTable1Key is using a custom data type calls "DataType.Key"

The Key data type is basically similar to a GUID, except it is not a restrictive as a GUID. If you try to create a GUID using random string value, it won't work.

I wrote a number of test to see if I can insert, update and data data row from the table. It works as expected, except how do I do select using this Complex Data Type?

It turns out that there is a function call Covert that you can use: For example:

   1: string l_sColumnName = UIModel.UIDataModel.DSTestTable1.DSTestTable1KeyColumn.ColumnName;
   2: string l_sExpression = "CONVERT([" + l_sColumnName + "], 'System.String')" + " = " +
   3:                        "'" + l_oNewRow.DSTestTable1Key + "'";
   4:  
   5: DataRow[] oResult = UIModel.UIDataModel.DSTestTable1.Select(l_sExpression);

What happen in the above example is that it convert the data type of my column data to System.String and than compare with my Key.ToString() value.

So in conclusion, as long as your complex data type support an override ToString() that is unique, you can use the above example to retrieve value based on your complex data type. To learn how more about the select express, see reference:

Reference: http://msdn2.microsoft.com/en-us/library/system.data.datacolumn.expression(VS.71).aspx