Welcome to MSDN Blogs Sign in | Join | Help

Generic list and powershell

I met with an accident recently riding my motorcycle and hence was unable to blog for some time. Here is my post after a brief break.

 

I wanted to create a generic list of my class in power shell. It was an interesting experience. Here is what I found.

 

When I tried to create a generic list of say type int it was straight forward ... well sort of ... the syntax was awkward, but still worked.

 

$list = New-Object "System.Collections.Generic.List``1[System.Int32]"

$list.Add(3)

$list

 

I wrote a sample assembly as below:

using System;

public class Sample

{

    public Sample() {}

    public void SampleMethod() { Console.WriteLine("Hello");}

 

}

 

Compiled this to sample.dll as csc /target:library sample.cs

 

[Reflection.Assembly]::LoadFrom("c:\Sample\Sample.dll")

 

Make sure if the assembly is loaded

 

[System.AppDomain]::CurrentDomain.GetAssemblies()

 

Now add the class Sample to the list. It gave me the error below.

 

$list = New-Object "System.Collections.Generic.List``1[Sample]"

New-Object : Cannot find type [System.Collections.Generic.List`1[Test]]: make sure the assembly containing this type is loaded.

At line:1 char:19 + $list = New-Object  <<<< "System.Collections.Generic.List``1[Test]"

 

I am not sure why this is not working as the syntax is very similar to the one I had above for Int32. After some search and experimenting I figured out another way to get the generic list working.

 

$si = new-object Sample

$st = [Type] $si.GetType()

$base = [System.Collections.Generic.List``1]

$qt = $base.MakeGenericType(@($st))

$so = [Activator]::CreateInstance($qt)

$so.Add($si)

write-host $so

Sample

$so[0].SampleMethod()

Hello

 

 

Debug .NET Framework Source Code and loading SOS in Visual Studio

I found this blog post from Shawn Burke to be very useful. Comes in handy if you have to step through .NET source when debugging.

http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

Another helpful post is to load sos from Visual Studio which is explained here:

http://blogs.msdn.com/vijaysk/archive/2007/11/15/sos-your-visual-studio.aspx

Asynchronous delegates and callback

I was debugging some issue related to asynchronous delegates and wanted to share that information with everyone.

 

When you do a BeginInvoke the delegate is invoked on a thread from the thread pool and on completion the callback is also called on the same thread pool thread. Now, any exceptions that is thrown on this thread cannot be caught by the main thread and so will crash the process. If you want to handle the exception, then you have to catch the expected exception in the callback and store it to some state and rethrow the exception from the main thread so that the callers above you can handle it gracefully.

 

In the sample below if you remove the try catch block in the callback or replace the exception.Add(e) with a throw, then the exception will crash the process. If you swallow the exception then you will be hiding failures and continuing which could result in other failures.

 

 

using System;

using System.Threading;

using System.Runtime.Remoting.Messaging;

using System.Collections.Generic;

 

namespace Delegate

{

    public class SampleClass

    {

        public static bool SampleMethod()

        {

            Console.WriteLine("Inside sample method ...");

            throw new ArgumentException();

        }

    }

 

    public delegate bool SampleMethodCaller();

 

    public class DelegateSample

    {

        List<Exception> exceptions;

        ManualResetEvent waiter;

 

        public DelegateSample()

        {

            exceptions = new List<Exception>();

        }

 

        public void CallBackMethodForDelegate(IAsyncResult result)

        {

            SampleMethodCaller smd = (SampleMethodCaller)((AsyncResult)result).AsyncDelegate;

            try

            {

                bool returnValue = smd.EndInvoke(result);

            }

            catch (ArgumentException e)

            {

                exceptions.Add(e);

            }

            finally

            {

                waiter.Set();

            }

        }

 

        public void CallDelegateUsingCallBack()

        {

            try

            {

                waiter = new ManualResetEvent(false);

                SampleMethodCaller smd = new SampleMethodCaller(SampleClass.SampleMethod);

                IAsyncResult result = smd.BeginInvoke(CallBackMethodForDelegate, null);

                waiter.WaitOne();

 

                if (exceptions.Count != 0)

                {

                    throw exceptions[0];

                }

            }

            catch (ArgumentException)

            {

                Console.WriteLine("Catch exceptions here ...");

            }

        }

 

        public static void Main()

        {

            DelegateSample ds = new DelegateSample();

            ds.CallDelegateUsingCallBack();

            Console.WriteLine(" -----------------");

        }

    }

}

 

 

 

System.Data.DataException and System.Data.DataSet.RaiseMergeFailed exception

This was another interesting issue I encountered recently. The error presented itself as an event log entry from our logging as below:

 

Unhandled Exception: System.Data.DataException: <target>.Column2 and <source>.Column2 have conflicting properties: DataType property mismatch.

   at System.Data.DataSet.RaiseMergeFailed(DataTable table, String conflict, MissingSchemaAction missingSchemaAction)

   at System.Data.Merger.MergeSchema(DataTable table)

   at System.Data.Merger.MergeTableData(DataTable src)

   at System.Data.Merger.MergeDataSet(DataSet source)

   at System.Data.DataSet.Merge(DataSet dataSet, Boolean preserveChanges, MissingSchemaAction missingSchemaAction)

   at System.Data.DataSet.Merge(DataSet dataSet)

   at ConsoleApplication1.Program.TryMerge(DataSet original)

   at ConsoleApplication1.Program.DemonstrateMerge()

   at ConsoleApplication1.Program.Main(String[] args)

 

If you look deeper in to the exception it tells you the column that Merge is complaining about. You get into this problem if the data type of the columns that you are merging are different. Now, you might wonder how you could run into an issue like this.

 

The scenario in which I ran into this issue was interesting. If one of your stored procedures returns a nvarchar in one case and returns a null in another, you will run into this error. One the merge when C# tries to merge the nvarchar and null it does not know the type of null and fails with a DataException. Another interesting observation is that the same error does not happen when you return a variable of a defined type and assign null to it.

 

 

Hope it is useful to others who have run into a similar stack and are trying to debug it.

 

I have tweaked a sample from MSDN to expose the same stack.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data;

 

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            Program p = new Program();

            p.DemonstrateMerge();

        }

 

        private void DemonstrateMerge()

        {

            DataSet dataSet = new DataSet("dataSet");

            DataTable table = new DataTable("Table1");

            DataColumn idColumn = new DataColumn("Column1", Type.GetType("System.Int32"));

            idColumn.AutoIncrement = true;

            DataColumn itemColumn = new DataColumn("Column2", Type.GetType("System.Int32"));

            itemColumn.Unique = true;

 

            DataColumn[] keyColumn = new DataColumn[1];

            DataRow row;

 

            table.Columns.Add(idColumn);

            table.Columns.Add(itemColumn);

            dataSet.Tables.Add(table);

 

            keyColumn[0] = idColumn;

            table.PrimaryKey = keyColumn;

 

            for (int i = 0; i < 3; i++)

            {

                row = table.NewRow();

                row["Column2"] = i+100;

                table.Rows.Add(row);

            }

 

            dataSet.AcceptChanges();

            PrintValues(dataSet, "Original values");

            dataSet.EnforceConstraints = true;

            TryMerge(dataSet);

        }

 

        private void TryMerge(DataSet original)

        {

            DataSet dataSet = new DataSet("dataSet");

            DataTable table = new DataTable("Table1");

            DataColumn idColumn = new DataColumn("Column1", Type.GetType("System.Int32"));

            idColumn.AutoIncrement = true;

            DataColumn itemColumn = new DataColumn("Column2", Type.GetType("System.Int64"));

            itemColumn.Unique = false;

 

            DataColumn[] keyColumn = new DataColumn[1];

            DataRow row;

 

            table.Columns.Add(idColumn);

            table.Columns.Add(itemColumn);

            dataSet.Tables.Add(table);

 

            keyColumn[0] = idColumn;

            table.PrimaryKey = keyColumn;

 

            for (int i = 0; i < 3; i++)

            {

                row = table.NewRow();

                row["Column2"] = 100;

                table.Rows.Add(row);

            }

 

            dataSet.AcceptChanges();

            original.Merge(dataSet);

            PrintValues(original, "Merged values");

        }

 

        private void PrintValues(DataSet dataSet, string label)

        {

            Console.WriteLine("\n" + label);

            foreach (DataTable table in dataSet.Tables)

            {

                Console.WriteLine("TableName: " + table.TableName);

                foreach (DataRow row in table.Rows)

                {

                    foreach (DataColumn column in table.Columns)

                    {

                        Console.Write("\t table " + row[column]);

                    }

                    Console.WriteLine();

                }

            }

        }

    }

}

 

CString and GetLength

I ran into this problem recently when debugging some native code and thought that it will be good to share this with everyone.

 

CString sampleString = CString(_T("Sample\0String"), 14);

int len = sampleString.GetLength();          // len is 14

CString trimmedString = sampleString.Trim(); // trimmedString = "Sample"

CString newstring = CString(sampleString);   // newString = "Sample"

len = newstring.GetLength();                 // len = 14

 

CString GetLength returns the length that you passed to it in the constructor and not the length of the string. This can be confusing if you copy the string and loop through the length. It can also be the cause of bugs is you get the length and use CString.GetBuffer() and loop through the buffer for the length.

It looks like CString.GetLength() is the size of the internal buffer and nothing more.

 

MSDN documentation for CString - http://msdn.microsoft.com/en-us/library/aa300471(VS.60).aspx

NTSD and SOS: StopOnException

using System;

class Program

{

    static void Main(string[] args)

    {

        Program p = new Program();

        p.ExceptionSample();

    }

 

    private void ExceptionSample()

    {

        int i=0;

        while (i < 100)

        {

            if (i == 60)

            {

                try

                {

                    throw new ArgumentException();

                }

                catch (Exception)

                {

                }

            }

            else

            {

                try

                {

                    throw new OutOfMemoryException();

                }

                catch (Exception)

                {

                }

            }

            i++;

        }

    }

}

 

!StopOnException comes in handy when you want if you want to break when a specific exception occurs.

 

csc /debug Program.cs

 

ntsd program.exe

 

.sympath+ .

sxe ld mscorwks

 

g

 

.loadby sos msorwks

!StopOnException -Create System.ArgumentException 1

 

g

 

!ClrStack -a

OS Thread Id: 0x103c (0)

Child-SP         RetAddr          Call Site

000000000019ee50 000007ff00180182 Program.ExceptionSample()

    PARAMETERS:

        this = 0x0000000002603358

    LOCALS:

        0x000000000019ee78 = 0x000000000000003c

        0x000000000019ee7c = 0x0000000000000000

 

000000000019eec0 000007fefa3f2672 Program.Main(System.String[])

    PARAMETERS:

        args = 0x0000000002603338

    LOCALS:

        0x000000000019eee0 = 0x0000000002603358

 

!pe

Exception object: 00000000026087d0

Exception type: System.ArgumentException

Message: Value does not fall within the expected range.

InnerException: <none>

StackTrace (generated):

<none>

StackTraceString: <none>

HResult: 80070057

 

This will stop when the exception occurs. You can print the details of the exception using pe and look into locals using the clrstack -a. This comes in handy if you want to debug some problem and want to break when the exception occurs.

XMLSerializer, XDocument and LINQ

I took the sample from my previous post and wanted to use LINQ to query the XML. You can pretty much use the power of SQL on the document object to richly query for things you are looking for.

 

using System;

using System.Linq;

using System.Xml.Linq;

using System.Collections.Generic;

using System.Xml;

using System.Xml.Serialization;

using System.IO;

 

namespace Sample

{

    public class Company

    {

        List<Book> books;

 

        [XmlElement(ElementName = "Book")]

        public List<Book> Books

        {

            get

            {

                if (this.books == null)

                {

                    this.books = new List<Book>();

                }

                return books;

            }

            set { }

        }

    }

 

    public class Book

    {

        [XmlAttribute(AttributeName = "Title")]

        public string Name { get; set; }

 

        [XmlAttribute(AttributeName = "Author")]

        public string Author { get; set; }

 

        [XmlAttribute(AttributeName = "Year")]

        public string Year { get; set; }

    }

 

    public class Demo

    {

        static void Main(string[] args)

        {

            Company c = new Company

            {

                Books =

                {

                    new Book

                    {

                        Name = "First Book",

                        Author = "First Author",

                        Year = "First Year",

                    },

                    new Book

                    {

                        Name = "Second Book",

                        Author = "Second Author",

                        Year = "Second Year",

                    },

                    new Book

                    {

                        Name = "Third Book",

                        Author = "Third Author",

                        Year = "Third Year",

                    },

                    new Book

                    {

                        Name = "Fourth Book",

                        Author = "Fourth Author",

                        Year = "Fourth Year",

                    },

                    new Book

                    {

                        Name = "Fifth Book",

                        Author = "Fifth Author",

                        Year = "Fifth Year",

                    }

                }

            };

 

            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Company));

            FileStream fs = new FileStream("test.xml", FileMode.Create);

            xmlSerializer.Serialize(fs, c);

            fs.Close();

            XDocument doc = XDocument.Load("test.xml");

           

            var bks = from books in doc.Elements("Company").Elements("Book") where (books.Attribute("Title").Value.Equals("Fourth Book")) select books;

            foreach (var book in bks)

            {

                Console.WriteLine(book);

            }

        }

    }

}

XmlSerialization to generate and consume XML

I want to talk about Xml Serialization this month. One of the work I was involved in recently required generation of XML and a I came across this wonderful technology which helps you generate and consume XML seamlessly.

 

If you are generating XML in a clumsy way using printf containing the XML tags, I would strongly suggest you to look into this technology. Incidetaly this plays well with Linq too. The XML after it is loaded into the object can be parsed with Linq queries. I will write a sample for that soon.

 

 

using System;

using System.Collections.Generic;

using System.Xml;

using System.Xml.Serialization;

 

namespace Sample

{

    public class Company

    {

        List<Book> books;

 

        [XmlElement(ElementName = "Book")]

        public List<Book> Books

        {

            get

            {

                if (this.books == null)

                {

                    this.books = new List<Book>();

                }

                return books;

            }

            set { }

        }

    }

 

    public class Book

    {

        [XmlAttribute(AttributeName = "Title")]

        public string Name { get; set; }

 

        [XmlAttribute(AttributeName = "Author")]

        public string Author { get; set; }

 

        [XmlAttribute(AttributeName = "Year")]

        public string Year { get; set; }

    }

 

    public class Demo

    {

        static void Main(string[] args)

        {

            Company c = new Company

            {

                Books =

                {

                    new Book

                    {

                        Name = "First Book",

                        Author = "First Author",

                        Year = "First Year",

                    },

                    new Book

                    {

                        Name = "Second Book",

                        Author = "Second Author",

                        Year = "Second Year",

                    }

                }

            };

 

            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Company));

            xmlSerializer.Serialize(Console.Out, c);

        }

    }

}

 

I find that there are too many ways to load and parse XML such as XDocument, XPath, XMLSerialize, XDocument and so on.  I feel it to be hard to make the right choice of technology for the scenario on hand sometimes. Yet again, documentation leaves you stranded in this space!

Simple sample for Events and Delegates

I wanted to write a small sample to illustrate events and delegates. Here is a compact sample that illustrates it.

 

using System;

public class EventSample

{

    public delegate void EventHandler();

    public event EventHandler myeh;

 

    public void Method()

    {

        Console.WriteLine("Inside Sample Method ... ");

    }

 

    public void OnChange()

    {

        myeh();

    }

 

    public static void Main()

    {

        EventSample es = new EventSample();

        es.myeh += new EventHandler(es.Method);

        es.OnChange();

    }

}

DBNull and Nullable types

When we have C# code interacting with the data base you run into this problem. Let me try and explain it. The database has nullable columns and C# has nullable types. For example, let us take a table Employee which has Id (int), name (string) and age (int). Let us assume that age will be null if no values are provided.

 

When you query the database for employee, the dataset or datareader will have DBNull for age. Now, this DBNull is not the same as C# null. This is the beginning of the problem. In order to make sure your code works properly, it has to expect that the reader can return a DBNull. You have to do the following in your code:

 

 

int? age = null;

if (!DBNull.Value.Equals(reader["Age"]))

{

    age = (int)reader["Age"];

}

 

This code converts the DBNull to a C# null. The lack of common null types between the two makes code have two sets of defaults for data, one in the DB and the other in C#. Which can get confusing.

 

If you don't use nullable types due to performance, you have to invent your own null value:

 

int age = -1;

if (!DBNull.Value.Equals(reader["Age"]))

{

    age = (int)reader["Age"];

}

 

This conversion seems ugly and it is all over the code. Is there any other elegant solution to this?

Diagnostics: Using ETW tracing in .NET 3.5 (EventProviderTraceListener)

.NET exposes an elegant diagnostics model that can be used by applications. It is a bit confusing to start with. There are a few listeners that exist in the Diagnostics namespace. Some of them are

 

1.       TextWriterTraceListener

2.       DefaultTraceListener

3.       EventLogTraceListener

4.       EventProviderTraceListener

5.       EventSchemaTraceListener

6.       XMLWriterTraceListener

7.       ConsoleTraceListener

 

The EventSchemaTraceListener, EventLogTraceListener and EventProviderTraceListener were too confusing as they all read the same at a glance. Here is a sample I wrote using this listener to get some clarity around it.

 

ETW.cs:

using System;

using System.Diagnostics;

 

/// <summary>

/// EventProviderTraeListener:

///   http://msdn.microsoft.com/en-us/library/system.diagnostics.eventing.eventprovidertracelistener.aspx

/// Trace Switch:

///   http://msdn.microsoft.com/en-us/library/aa983740.aspx

/// </summary>

class ETWSample

{

    static void Main(string[] args)

    {

        TraceSource myTraceSource = new TraceSource("TraceSourceApp");

        myTraceSource.TraceEvent(TraceEventType.Error, 1, "Tracing Error Message.");

        myTraceSource.TraceEvent(TraceEventType.Warning, 2, "Tracing Warning Message.");

        myTraceSource.TraceEvent(TraceEventType.Information, 3, "Tracing Information.");

        myTraceSource.TraceEvent(TraceEventType.Verbose, 4, "Tracing Verbose Message.");

        myTraceSource.TraceEvent(TraceEventType.Critical, 5, "Tracing Critical Message.");

        myTraceSource.Close();

        return;

    }

}

I also wrote the following configuration file such that the appropriate listeners are added to the source.

 

ETW.exe.config

<configuration>

  <system.diagnostics>

    <sources>

      <source name="TraceSourceApp" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch">

        <listeners>

          <add name="ConsoleListener"/>

          <add name="ETWListener"/>

          <remove name="Default"/>

        </listeners>

      </source>

    </sources>

 

    <switches>

      <add name="SourceSwitch" value="Verbose" />

    </switches>

 

    <sharedListeners>

      <add name="ConsoleListener" type="System.Diagnostics.ConsoleTraceListener"/>

      <add name="ETWListener" type="System.Diagnostics.Eventing.EventProviderTraceListener, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

               initializeData="{BA2DC22C-CCCE-4D17-AFC9-9811DD739970}" />

    </sharedListeners>

  </system.diagnostics>

</configuration>

 

I compiled the cs file as csc ETW.cs /d:TRACE and got etw.exe. On running etw.exe I see the trace messages in the screen. This is because of the fact that consolelistener is added as a listener.

 

Now in order to enable ETW tracing I ran logman to start a logging session.

logman start mysession -p {BA2DC22C-CCCE-4D17-AFC9-9811DD739970} -o etwtrace.etl –ets

 

This creates an .etl file which is filled with data when I stop the session.  It looks like it has parameters that you can use to tweak the behavior, but help around here is very poor and hence unfortunately requires lots of trial and error. Run perfmon and look into Data Collector Sets\Event Trace Sessions. The properties for mysession has a few options that you can experiment with.

 

To stop the session use

logman stop mysession –ets

 

If you notice, the provider guid given in the logman session and the listener configuration are the same.

 

To get information on what has been traced in the etl file run the following command

tracerpt etwtrace.etl

 

This will give you two files summary.txt and dumpfile.xml, which have readable information.

 

I was wondering if the etl files were viewable through event viewer. I tried to load the etl file from eventvwr using open saved log and it failed to load it. But it has another option to save events as an evtx file in the eventvwr actions menu. Kamesh Jayaram and Krishna Kumar enlightened me with this.

 

I saved the etl file events as an evtx file and tried opening the evtx file in event viewer. I was able to see the trace messages in event viewer.

 

I added the EventSchemaTraceListener and generated a XML log file. I tried loading that file in eventvwr and it failed to load. I am yet to figure that out! If someone knows anything about it I will be interested to know.

 

I also learn that if you set the schema of the etl upfront with eventvwr you can avoid the step of extracting events from the etl file and load the etl directly. Lack of quality help makes that hard to do as well!

 

Another important thing to note is that the changes to the configuration files are not dynamic and hence requires the process to be restarted.

 

Summary:

 

Logging should be simple such it in itself doesn't become a problem. This is a good step in the right direction, but needs more polishing. I feel that the multiple hoops involved in getting this right makes it complex. Lack of proper help worsens it. Similar reading names for the filters is exasperating. I would like to hear your views and perspectives on this if you have used the ETW tracing libraries.

 

 

Unhandled Exception handler (UnhandledExceptionEventHandler) to collect more information about unexpected exceptions

 

To continue on the exception post from last week I did a bit more research and learnt some more. I thought that I will share that with everyone. We had some interesting conversations in our team about exception handling and the following thought came up.

.NET gives you an option to write an unhandled exception handler which can be used to catch exceptions that you did not expect in your code and hence did not handle in your catch block. These are errors in the code as you did not expect them and should fail the application. This interestingly works even if you “throw;” or “throw new Exception(..)” from within the catch block.

It will be a good pattern to use this to log information about all unexpected exceptions in the application without introducing a “catch(Exception e)” in the code.

The sample below demonstrates the code for the exception handler. If you uncomment the throw blocks one then the handler will be invoked when the exception is thrown. Does anyone use this pattern and have benefited from it? Are there other ways to do this? Love to hear your thoughts!

 

using System;

public class Sample

{

   public static void Example()

   {

      AppDomain currentDomain = AppDomain.CurrentDomain;

      currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);

 

      try

      {

         throw new Exception("First Handled Exception");

      }

      catch (Exception e)

      {

         Console.WriteLine("Catch clause caught : " + e.Message);

      }

 

      try

      {

          throw new Exception("Second Handled Exception");

      }

      catch (Exception e)

      {

          Console.WriteLine("Catch clause caught : " + e.Message);

          // throw;

          // throw new Exception("Re-throw second exception", e);

      }

 

      // throw new Exception("Un-Handled Exception");

   }

 

   static void MyHandler(object sender, UnhandledExceptionEventArgs args)

   {

      Exception e = (Exception) args.ExceptionObject;

      Console.WriteLine("Exception Message: {0}", e.Message);

   }

 

   public static void Main()

   {

      Example();

   }

}

Handling, throwing - exceptions and Clean up on error

There are four ways to throw an exception in my opinion. They are:

 

1.  Throw a new exception

a.  throw new ArgumentException( … );

2.  Throw the exception you caught

a.  throw e;

3.  Throw the same exception preserving the stack

a.  throw;

4.  Throw with the original exception as an internal exception

a.  throw ArgumentException(innerException);

 

using System;

class Sample

{

    public void Method1()

    {

        // possible throw options

        // throw new ArgumentException(); - Origin of the exception

    }

 

    public void Method2()

    {

        try

        {

            Method1();

        }

        catch(ArgumentException ae)

        {

            // possible throw options

            // throw;

            //      - Preserves the original stack

            // throw ae;

            //      - Breaks the stack an and throws the same exception from now on

            // throw new ArgumentException(ae);

            //      - throws a new exception with an inner exception

            // throw new ArgumentException();

            //      - Throws a new exception

        }

        catch(Exception e)

        {

            Console.WriteLine(e.ToString());

        }

    }

 

    public void Method3()

    {

        bool cleanup = true;

        try

        {

            Method2();

            Method1();

            cleanup = false;

        }

        catch (Exception)

        {

            // perform Cleanup on error

        }

        finally

        {

            if (cleanup)

            {

                // perform cleanup on error

            }

        }

    }

 

    public static void Main()

    {

        Sample s = new Sample();

        try {

            s.Method2();

        }

        catch(ArgumentException ae)

        {

            Console.WriteLine(ae.ToString());

        }

    }

}

 

I personally would like to classify them as into two categories,

1.  Origin of the exception, the place where the exception starts

a.  Throw new ArgumentException(..)

2.  The place where the exception is handled and either gets mapped or rethrown

a.  Throw new ArgumentException()

b.  Throw new ArgumentException(innerException)

c.  Throw e;

d.  Throw;

 

There are not many options during the origin of the exception and so that is very clear. The confusion comes only when an exception passes through your code and you attempt to handle it.

 

In this case again, all four options are available, but only a few make sense. For example

1.  Throw new ArgumentException()

2.  Throw ae

 

both don’t make much sense. Both of these have brighter counterparts in throw new ArgumentException(ae) and throw; which either captures the inner exception  or preserves the stack. That leaves us with only two options in the way you handle and throw an exception:

 

1.  If you want to map your exceptions

a.  Throw new ArgumentException(innerException); (or)

2.  If you want to log contextual information and pass on the same exception

a.  Throw;

 

If you use the finally pattern as below, then you don’t need the throw;

If you use the Exception pattern as shown below then you need the throw to preserve the stack.

 

Incidentally, I noticed that performing cleanup on error in .NET is complicated. You have to either catch all exceptions and cleanup or use a variable that can tell you if a cleanup is required in the finally block. Both of them seem to violate the .NET patterns of catching only exceptions that you can handle and not using return values to understand errors.

 

If you had the cleanup in the catch block and you want to make sure it runs on any error, you have to catch Exception e which is not advised. This is another pattern that can be used to avoid that, but seems to me to rely on return value type paradigm which is also not advised either.

 

So what you choose seems to be up to you to choose!

 

Krzysztof Cwalina has a very interesting article on exception at http://blogs.msdn.com/kcwalina/archive/2007/01/30/ExceptionHierarchies.aspx

 

Code Access Security, LinkDemand and Effective Sandbox

I wrote about Deny and Assert in my previous blog post. In my repeated attempts to get the previous sample working for LinkDemand, I discovered that Deny and PermitOnly are not effective against LinkDemand. The code worked all the time and I was wondering why.

 

After some good research and lots of learning (from Shawn) I learnt that Deny and PermitOnly CANNOT create an effective sandbox environment. Shawm Farkas’s article on this is a must read. It clearly states how you can circumvent deny’s with asserts and so on.

 

Now with Deny and PermitOnly being a not so good mechanism for providing a secure sand box environment, we are on to finding the good sandbox environment. In my pursuit towards that I figured the following out.

 

An effective sandbox comes from grants associated with an AppDomain and the assemblies within the domain. The big issue with PermitOnly and Deny is that they don’t modify either grant set.

 

The sample below demonstrates how a LinkDemand works. It also demonstrates why a Demand does not work for the same case. Let us now look into the grant sets that are used to compare to either succeed or fail the call.

 

I have three assemblies A, B and C where A calls B which in turns calls C. C has two scenarios, one it has a LinkDemand for a permission and second it has a Demand for the permission. A, B and C instances are created in their own AppDomain and passed as MarshallByRef to C’s AppDomain. Shawn explains in this article very cleary the two grant sets that an assembly in an AppDomain gets, a full trust or a grant set depending on if it is in the GAC or one of the strong name assemblies passed to the CreateDomain call.

 

In the example below I create an instance of A, B and C in their own AppDomain and pass them to B and C which end up calling methods on them. Domain A does not grant EnvironmentPermission, Domain B grants EnvironmentPermission and C either Demands EnvironmentPermission or LinkDemands EnvironmentPermission.

 

Why does the LinkDemand work?

LinkDemands do not walk the stack and are evaluated at JIT time. You only JIT once, and hence grant sets are assigned when assemblies are loaded into an AppDomain and are not changed after that. In the sample below the linkdemand permission in C’s Method is compared with the grant set of the C’s AppDomain Technically, it’s comparing the LinkDemand on C’s Method with the grant set of C’s calling assembly in C’s AppDomain.  For instance, if C’s caller were on the FullTrust list or were from the GAC, the LinkDemand would succeed even though C’s AppDomain has a partial trust grant set. Thus this succeeds.

 

Why does the Demand Fail?

The demand fails because the demand results in a stack walk. It walks the stack and compared the demanded permission set with the permission set of the callers in the call stack. Since A does not have this permission set in A’s AppDomain the demand fails. It is important to notice that it does have the permission set in C’s Domain for instance which is irrelevant in this case.

 

LinkDemand is primarily used by framework code to gain elevation to perform its tasks. In general it should not be required in common scenarios.

 

I want to thanks Shawn Farkas for helping me with this blog post. He has tons of valuable information on CAS in this blog which are excellent reads – Shawn’s blog

 

Main.cs:

using System;

using System.Security;

using System.Security.Permissions;

using System.Reflection;

using System.Runtime.Remoting;

 

class Sample

{

    public static void Main()

    {

        AppDomainSetup ads = new AppDomainSetup();

        ads.ApplicationBase = System.Environment.CurrentDirectory;

 

        PermissionSet psMain = new PermissionSet(PermissionState.None);

        SecurityPermission sec = new SecurityPermission(PermissionState.Unrestricted);

        psMain.AddPermission(sec);

        AppDomain md = AppDomain.CreateDomain("A", null, ads, psMain, null);

        ObjectHandle obj = md.CreateInstance(@"A", "A");

        A a = (A)obj.Unwrap();

 

        PermissionSet psFirst = new PermissionSet(PermissionState.None);

        EnvironmentPermission env1 = new EnvironmentPermission(PermissionState.Unrestricted);

        psFirst.AddPermission(sec);

        psFirst.AddPermission(env1);

        AppDomain fd = AppDomain.CreateDomain("B", null, ads, psFirst, null);

        ObjectHandle obj1 = fd.CreateInstance(@"B", "B");

        B b = (B)obj1.Unwrap();

 

        PermissionSet psSecond = new PermissionSet(PermissionState.None);

        psSecond.AddPermission(sec);

        AppDomain sd = AppDomain.CreateDomain("C", null, ads, psSecond, null);

        ObjectHandle obj2 = sd.CreateInstance(@"C", "C");

        C c = (C)obj2.Unwrap();

        a.MethodMain(b, c);

    }

}

 

A.cs:

 

using System;

using System.Security;

using System.Security.Permissions;

using System.Reflection;

using System.Runtime.Remoting;

 

public class A : MarshalByRefObject

{

    public void Method(B b, C c)

    {

        Console.WriteLine("Inside A::Method");

        b.Method(c);

    }

}

 

B.cs:

 

using System;

using System.Security;

using System.Reflection;

 

public class B : MarshalByRefObject

{

    public void Method(C c)

    {

        Console.WriteLine("Inside B::Method");

        c.Method();

    }

}

 

C.cs:

 

using System;

using System.Security;

using System.Security.Permissions;

 

[SerializableAttribute()]

public class C

{

    [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)]

    public void Method()

    {

        Console.WriteLine("Inside C::Method");

    }

}

 

Code Access Security - Understanding Demand and Declarative Security

I wanted to talk about Code Access Security this time. Code Access Security is a big in itself. In this post I wanted to talk about Declarative Security. Declarative security uses attributes to place security information on assemblies, classes and methods.

 

In the sample below I have defined a method “MethodDemandingFileIOPermission” which demands “FileIOPermission” declaratively. In Main I deny FileIOPermission to begin with and try calling this method. The call to this method should fail as we have denied this permission. The first output from the code proves this.

 

Deny FileIOPermission

  Unable to access MethodDemandingFileIOPermission after Deny

 

Now, I call into another method which asserts FileIOPermission and calls the same method. This time call should succeed as a Demand stops walking the stack wen it encounters an Assert. So, in this case the Deny from Main has no effect on the call and it succeeds. The output is shown as below

 

Assert FileIOPermission from another method

  Calling method MethodDemandingFileIOPermission succeeded

 

Next, we revert the assert in the method where we asserted to make sure that the call indeed succeeded because of the assert. We make the same call again and as expected it fails this time. The output from the code is shown below.

 

RevertAssert in AssertAndCall and call again

  Unable to access MethodDemandingFileIOPermission Assert reverted in AssertAndCall

 

We Assert one more time and make the call to ensure the call succeeds this time. The output is as below.

 

Assert FileIOPermission one more time from another method

  Calling method MethodDemandingFileIOPermission succeeded

 

When the call returns to Main the Assert is reverted. The Deny takes effect and so a subsequent call to the method from Main fails. The output from the code shows the following result.

 

Assert permission reverted when returned to Main()

  Unable to access MethodDemandingFileIOPermission Assert reverted on return

 

We now Assert declaratively and make the call and the call succeeds this time also. On return the Assert is reverted and the call fails as expected.

 

Assert FileIOPermission Declaratively

  Calling method MethodDemandingFileIOPermission succeeded

 

Assert permission reverted when returned to Main()

  Unable to access MethodDemandingFileIOPermission Assert reverted on return

 

We now revert the Deny from Main and make the call to make sure that it was the Deny that was failing the call. As expected the call succeeds as soon as the Deny is reverted.

 

RevertDeny from Main()

  Calling method MethodDemandingFileIOPermission succeeded

 

using System;

using System.Reflection;

using System.Security.Permissions;

using System.Security;

using System.IO;

class Sample

{

    public static void Main()

    {

        FileIOPermission fileIOPerm = new FileIOPermission(PermissionState.Unrestricted);

        fileIOPerm.Deny();

       

        Console.WriteLine("Deny FileIOPermission");

 

        try

        {

            Sample.MethodDemandingFileIOPermission();

        }

        catch(Exception e)

        {

            Console.WriteLine("  Unable to access MethodDemandingFileIOPermission after Deny");

        }

 

        Sample.AssertAndCall(fileIOPerm);

 

        Console.WriteLine("Assert permission reverted when returned to Main()");

 

        try

        {

            Sample.MethodDemandingFileIOPermission();

        }

        catch (Exception e)

        {

            Console.WriteLine("  Unable to access MethodDemandingFileIOPermission Assert reverted on return");

        }

 

        CodeAccessPermission.RevertDeny();

        Console.WriteLine("RevertDeny from Main()");

 

        try

        {

            Sample.MethodDemandingFileIOPermission();

        }

        catch (Exception e)

        {

            Console.WriteLine("  Unable to access MethodDemandingFileIOPermission Assert reverted on return");

        }

 

        Sample.AssertDeclarativelyAndCall();

    }

 

    static public void AssertAndCall(FileIOPermission fileIOPerm)

    {

        Console.WriteLine("Assert FileIOPermission from another method");

        fileIOPerm.Assert();

        Sample.MethodDemandingFileIOPermission();

        CodeAccessPermission.RevertAssert();

        Console.WriteLine("RevertAssert in AssertAndCall and call again");

       

        try

        {

            Sample.MethodDemandingFileIOPermission();

        }

        catch (Exception e)

        {

            Console.WriteLine("  Unable to access MethodDemandingFileIOPermission Assert reverted in AssertAndCall");

        }

 

        Console.WriteLine("Assert FileIOPermission one more time from another method");

        fileIOPerm.Assert();

        Sample.MethodDemandingFileIOPermission();

    }

   

    [FileIOPermissionAttribute(SecurityAction.Assert, Unrestricted = true)]

    static public void AssertDeclarativelyAndCall()

    {

        Console.WriteLine("Assert FileIOPermission Declaratively");

        Sample.MethodDemandingFileIOPermission();

    }

 

    [FileIOPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]

    static public void MethodDemandingFileIOPermission()

    {

        Console.WriteLine("  Calling method MethodDemandingFileIOPermission succeeded");

    }

 }

More Posts Next page »
 
Page view tracker