2005 2006 2007 2008 2009 2010 2011 2015 2016 2017 aspnet azure csharp debugging elasticsearch exceptions firefox javascriptajax linux llblgen mongodb powershell projects python security services silverlight training videos wcf wpf xag xhtmlcss

Obtaining Enumeration Names and Values in Silverlight 2.0

In .NET, when you are dealing with singular enumerations (the ones singular names) or flags enumerations (the ones with plural names), you have the ability to access the names and values of each of the items in the enumeration.  For example, the below code iterates through and prints out both the values and names of the enumeration items:

using System;
//+
namespace Sample
{
    public enum Component
    {
        Keyboard,
        Mouse,
        Display,
        Disk,
        Memory,
        Network
    }

    public class Program
    {
        //- $Main -//
        private static void Main(String[] args)
        {
            //+ name
            foreach (String name in Enum.GetNames(typeof(Component)))
            {
                Console.WriteLine(name);
            }
            //+ value
            foreach (Object value in Enum.GetValues(typeof(Component)))
            {
                Console.WriteLine((Int32)value);
            }
        }
    }
}

Now let’s go to do the same thing in Silverlight 2.0.

image

Err... wait a minute.  Where’s GetNames and GetValues?  Well, they don’t exist.  Fortunately, we have the ability to access these via reflection.  To obtain the names, we just need to obtain the Type object of our enumeration and call GetFields with the Public and Static binding flags set, and look in the resulting FieldInfo array.  Each FieldInfo object will have a Name property without item name.  For the values, we simply use Enum.Parse to turn that name into the actual value.  For the underlying value, we can just cast that to the underlying type of the enumeration.  In the example above, that would be System.Int32.  Here’s all that in action:

 

//- $OnLoaded -//
private void OnLoaded(Object sender, System.Windows.RoutedEventArgs e)
{
    Type enumType = typeof(Component);
    System.Reflection.FieldInfo[] fiArray = enumType.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
    foreach (System.Reflection.FieldInfo fi in fiArray)
    {
        //+ name
        sp01.Children.Add(new TextBlock
        {
             Text = fi.Name
        });
    }
    foreach (System.Reflection.FieldInfo fi in fiArray)
    {
        //+ value
        sp01.Children.Add(new TextBlock
        {
            Text = ((Int32)Enum.Parse(enumType, fi.Name, false)).ToString()
        });
    }
}

I’ve left the namespaces of the items in the System.Reflection namespace in place so you can see exactly what types were working with here.

Of course, you can always wrap this up into it’s own class so you can reuse this logic all over:

namespace Themelia
{
    public class EnumReader
    {
        /// <summary>
        /// Gets the names of an enumeration type.
        /// </summary>
        /// <param name="enumerationType">Type of enumeration.</param>
        /// <returns>List of names of the enumeration.</returns>
        public static List<String> GetNameList(Type enumType)
        {
            if (!enumType.IsEnum)
            {
                throw new InvalidOperationException("Specified generic parameter must be an enumeration.");
            }
            List<String> nameList = new List<String>();
            //+ type
            FieldInfo[] fiArray = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
            foreach (FieldInfo fi in fiArray)
            {
                nameList.Add(fi.Name);
            }
            //+
            return nameList;
        }

        //- @GetNameList -//
        /// <summary>
        /// Gets the names of an enumeration type.
        /// </summary>
        /// <typeparam name="T">Type of enumeration.</typeparam>
        /// <returns>List of names of the enumeration.</returns>
        public static List<String> GetNameList<T>() where T : struct
        {
            return GetNameList(typeof(T));
        }

        //- @GetValueList -//
        /// <summary>
        /// Gets the values of an enumeration type.
        /// </summary>
        /// <typeparam name="T">Type of enumeration.</typeparam>
        /// <returns>List of values of the enumeration.</returns>
        public static List<T> GetValueList<T>() where T : struct
        {
            Type enumType = typeof(T);
            if (!enumType.IsEnum)
            {
                throw new InvalidOperationException("Specified generic parameter must be an enumeration.");
            }
            List<T> valueList = new List<T>();
            FieldInfo[] fiArray = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
            foreach (FieldInfo fi in fiArray)
            {
                valueList.Add((T)Enum.Parse(enumType, fi.Name, false));
            }
            //+
            return valueList;
        }
    }
}

In this example class, you can see that two of the methods are actually declared as generic.  So, to use them like this:

//- $OnLoaded -//
private void OnLoaded(Object sender, System.Windows.RoutedEventArgs e)
{
    foreach (String name in EnumReader.GetNameList<Component>())
    {
        //+ name
        sp01.Children.Add(new TextBlock
        {
            Text = name
        });
    }
    foreach (Component component in EnumReader.GetValueList<Component>())
    {
        //+ value
        sp01.Children.Add(new TextBlock
        {
            Text = ((Int32)component).ToString()
        });
    }
}

One thing to keep in mind is that reflection does have a performance hit.  However, given that most of WPF, Silverlight, and WCF are all about constant reflection, you can rest comfortably that it’s not nearly as bad as some people would say.  Having said that, if your application profiling does say that you are reflecting too much, you can always cache the data returned from these method and access the cache instead.  Don’t however, cache for the sake of caching.  Saying “We’re always going to cache, just to be consistent” is as stupid as saying “We’re always going to drive 45mph, just to be consistent.”  This kills people on both the interstate and in school zones.  Make your caching decisions (and ALL other decisions!) based upon your current situation never upon dangerous mindless consistency.

Silverlight Feature Requests

Silverlight is probably the most important technology to be released since Firefox 1.0 and that since .NET 1.0.  However, as with most early-edition pieces of software, there are some major things missing.  Below is a list of things that I request that Microsoft add with a quick note on each.  It ranges from a few UI things to the more hardcore mechanical things (...things that many developers will say are meaningless until they learn how to spell C-L-R).

  • GIF Support - Obvious.  It's very odd that some manager somewhere said "no one ever uses GIF anymore".
  • Style Inheritance - Another obvious one.  We who knew WPF long before Silverlight was around THRIVE on this.
  • DockPanel - COME ON! You MUST be joking! I shouldn't have to use a third party CodePlex control for this.
  • VisualBrush - The ability to paint controls on a background and in other places will go a long way in helping people creating more interactive help files and training software.
  • RelativeSource - The ability to bind one element's property to another is EXTREMELY important (i.e. my height == my parent's height).
  • MultiView - It takes almost no code to write this; just make it native so we don't have dozens of versions all over.
  • WebHttpBinding for JSON - POX is less important, but would be nice; JSON is the de facto web standard.
  • System.Security.Cryptography.RSA with providers - This would greatly increase the security of client-server communication.
  • Workflow Foundation - Even a light version with only the basic activities (for, if, while, etc...) would be nice.
  • SVG Viewer - This should shut up the anti-Microsoft cult.
  • Better font rendering - It's HORRIBLE in 2.0.
  • iPhone Support - I think this may take a miracle.
  • MultiTouch - Need this for iPhone support.
  • CSS3 DOM Selector (http://www.w3.org/TR/selectors-api/) - So we use it instead of jQuery's version for closer-to-native speed on EVERY browser without even needing JQuery.
  • A XMLHttpRequest object - This would allow us to use Silverlight's CrossDomainPolicy.xml stuff for cross domain stuff instead of playing games with browser detection nonsense and adding hacks for browsers which don't support it.
  • API for browser abstraction - Web developers HATE having to do lame detection to figure out if we are on IE so we can talk to it like a child.  Give us the ability to create managed extensions to Silverlight so we can add in our pain-in-the-butt browser differences in Silverlight instead of relying on painfully slow JScript rendering and browser detection.
  • Service for extensions - This goes with the last one.  We should have the ability to 1) extend the hardcore functionality of Silverlight and 2) have a centralize service that Silverlight calls to download our functionality when our application requests it.  This would be very just like what Firefox does when it needs a plugin.  It would also do auto-updating like with Firefox extensions.
  • JSON deserializer that actually works to deserialize data serialized by the JSON serializer - JSON is critically important to the web; it should be supported better.
  • The ability to get 500 HTTP status codes from Firefox, Chrome, and IE - This would allow us to use fault contracts in WCF.  This would have to be a pain to implement, though. So, I wouldn't expect it for a while.
  • The ability for NPCTRL to communicate CLR configuration information to the CoreCLR to tweak GC things that are normally in configuration - If the hosting NPCTRL control would just allow us to give it configuration parameters to send to the CoreCLR, that would RULE (like we can already do in .NET with configuration).
  • Hosting documentation that doesn't SUCK - Using Win32/ATL to host a Silverlight control is insane right now.  The documentation is very incomplete and there are NO samples (and the IDL is wrong!)
  • Background GC on Windows - I suspect that this would increase performance in many scenarios.
  • The missing GC methods - The System.GC class is missing a PUBLICLY ACCESSIBLE GetCollectionCount.  This will help us with profiling.  It's marked as internal now and if you try to access it via reflection or other fancy tricks you get security errors.
  • ICorProfilerCallback interface - This is my NUMBER ONE FEATURE REQUEST!  This is REQUIRED to create a Silverlight profiler.  Silverlight will NOT be a technology ready for enterprise usage without this.  PERIOD.
  • Documentation on Silverlight's ETW - it's there and it's working in SL2, but I see absolutely zero docs on how to access it.
  • The native AGCORE and NPCTRL source code - This will aide in performance and feature creation
  • COM interface for hosting the CoreCLR - not really a Silverlight feature, but this would be REALLY nice.

Project Sneak Peek

Today I thought I would give a teaser of my latest side project (I'm about a month into it).

Since I'm not a general "business application" developer, but am a specialist in various areas of technology, most of the projects I work on are awesome.  Two of my favorite projects are the Brainbench C# 2.0 exam and the Brainbench C# 2.0 Fundamentals exam, both as the author.  Immediately after finishing the later project, I ended my 2 year long on-and-off consultancy with Brainbench as author and technical editor.

Now, nearly a year later, I've gone on my own (more teasers in Q2 2009):

Which of the following statements regarding a .NET object's sync block index are true?
 
When an ephemeral segment GC occurs, the synch block index contains a pointer to the next object.
If a root is found by a GC, a bit will be enabled in the synch block index.
Constructed objects have the sync block index initialized to a negative value.
Value types have their synch block index set to the value of their location on the stack.
When a monitor lock is entered, the index of a free sync block is recorded in the synch block index.

Setting a Silverlight 2 Startup Breakpoint using WinDBG

As I've mentioned on a previous occasion, hardcore debugging is done with WinDBG and SOS.  Visual Studio's debugger just isn't enough for the super interesting scenarios.  I've also mentioned that I have no intention of giving a step-by-step introduction into how to use SOS.  However, given that debugging is directly related to internals and that most people with advanced Silverlight issues will search for "advanced Silverlight debugging" or the like, I'll provide a little information here and there to help people find what they are looking for quicker.

Here I would like to explain how you can set a break point very early in the Silverlight load process, before your application even loads.  This technique will give you a glimpse into the internals of Silverlight to see how things work.  It will also help you to step through your method calls from the very beginning in WinDBG.

First, however, understand that Silverlight has three major components that you need to be aware of:

  • NpCtrl.dll
  • AgCore.dll
  • CoreCLR.dll

Each of these components is critical to loading and running a Silverlight application.  NpCtrl.dll is a browser plugin which follows the Netscape Plugin API (NPAPI).  When your browser sees that you are trying to load Silverlight 2, it will call the NP_Initialize export (a public DLL function).  Later, this plug-in will load the AgCore.dll and create a instance of the COM class XcpControl2 to allow NpCtrl to interact with Silverlight (you too can use XcpControl in your COM development).  AgCore is the unmanaged part of Silverlight 2.  It handles everything from DOM interaction, to rendering, to media play.

At this point you will see the spinning XAP-loading progress bar.  When this is complete, NpCtrl will finally load CoreCLR.dll.  Upon load, the DllMain function for this DLL is called.  This function will start up the CoreCLR, the CLR that Silverlight 2 uses.  Upon completion, NpCtrl then calls the GetCLRRuntimeHost DLL export to get the loaded instance of the CLR.  The rest of your application is ready to run (as a side note, the order of a few of these things changes under certain circumstances, so you may actually see CoreCLR load AgCore.)

With this information you're ready to start a fresh instance of a web browser (it's crucial that Silverlight 2 isn't already loaded) and attach WinDBG to your browser's process.  Upon attach you are given control to the command interface.  To set a breakpoint when Silverlight 2 starts, you set a breakpoint when a specific DLL is loaded.  Depending on your needs this may be the npctrl.dll, agcore.dll, or coreclr.dll.

You set a breakpoint for a DLL load in WinDBG by using the following command:

sxe ld:DLLNAME

Thus, if you wanted to break at a specific point in the Silverlight loading procedure, you use one of the following commands:

sxe ld:npctrl

sxe ld:agcore

sxe ld:coreclr

If you want to remove these breakpoints, just type the the following:

sxr

Once you have one or more DLL load breakpoints these and resume your application (the 'g' command or F5 in WinDBG) you can test it our by going to http://themelia.netfxharmonics.com/. If successful, WinDBG will break when your DLL loads.  In the call stack window (or when you type the 'k' command), you will see a call stack that looks something like the following:

kernel32!LoadLibraryW+0x11
npctrl!GetCLRRuntimeHost+0x112
npctrl!CWindowsServices::CreateCLRRuntimeHost+0x19
agcore!CCLRHost::Initialize+0x12a
agcore!CRuntimeHost::Initialize+0x60
agcore!CCoreServices::CLR_Startup+0x95
agcore!CDeployment::Start+0x27
agcore!CCoreServices::StartDeploymentTree+0x53
npctrl!CXcpBrowserHost::put_Source+0x10f
npctrl!CommonBrowserHost::OnGotSourceDownloadResponse+0x4b
npctrl!CXcpDispatcher::OnReentrancyProtectedWindowMessage+0x284
npctrl!CXcpDispatcher::WindowProc+0x51
USER32!InternalCallWinProc+0x28
USER32!UserCallWinProcCheckWow+0x150

Chances are, though, that you won't see this information like this at first.  Instead, you will probably see a series of memory addresses.  To view the actual function names, you must configure your symbol paths in WinDBG.  These symbols, often called PDBs, will relate the machine information with information from the original source.  In our case, we need them to view the function names.

To setup symbols, use the following command, replacing C:\_SYMBOL with a symbol location of your choice (symbols are very important and, therefore, should not be thrown into a "temp" folder):

. symfix SRV*C:\_SYMBOL*http://msdl.microsoft.com/download/symbols;SRV*C:\_SYMBOL*http://symbols.mozilla.org/firefox

You may also enter this information in the window that is shown when you hit Ctrl-S.  Either way, this will configure the symbols for both Microsoft's symbol server and Mozilla's.  The latter will help you view exactly how far the loading processing has gone while in Firefox.

With the symbols configured, you will then be able see something like the above call stack.  If you set the symbols after you had already loaded Silverlight 2 in your browser, then you need to exit the browser, start a new instance, and reattach WinDBG.  Regardless, every time a DLL is loaded, WinDBG will automatically access the appropriate Microsoft and Mozilla and download the symbol file for that DLL.  This will take time for every DLL that is to be loaded.  Expect the WinDBG status bar to read *BUSY* for a long time.  It will only load the symbol for each DLL once.

The method I've just described works perfectly for breaking in WinDBG Firefox and IE.  But, what about Chrome?  Depending on settings, Google Chrome uses either a process-per-tab model or a process-per-site model.  While this flexibility is great for daily use, for debugging we can't have processes bouncing around like jack rabbits on cocaine.  You need a process that you can attach to that won't run away as soon as you use it.  So, to successfully attach WinDBG to Chrome, you should start Chrome up in single process mode.  You do this as follows:

chrome.exe --single-process

At this point, you can attach to Firefox, IE, and Chrome for Silverlight 2 debugging in Silverlight.

Silverlight SOS Commands

Today I became rather curious of what commands Silverlight's version of SOS provided (see my Learning WinDBG/SOS and Advanced Debugging post for more information on SOS).  I didn't really have any guess to whether there would be more, less, or the same.  So I ran Silverlight's SOS.dll through .NET's dumpbin.exe application with the /exports switch to get a list of what you can do with it.  In this case, the lower case DLL exports are the actual SOS commands you can use.  I did dumpbin.exe on the .NET 2.0 version and did a diff between them.  The results?  The Silverlight version of SOS actually has more commands than the .NET version.

Here is a list of SOS commands that aren't in the .NET version:

analyzeoom histobj vh
ao histobjfind vo
dumpsigelem histroot  
findroots histstats  
fq hof  
gcheapstat listnearobj  
gcwhere lno  
heapstat t  
histclear tp  
histinit verifyobj  

You can type these into your debugger to see the specific syntax for each of these.  For detailed information on most of these, you'll have to wait until something gets posted on MSDN or one of the SOS developers post something.  For a few, however, Sasha Goldshtein has provided some information and examples.  Here are some posts from this person's web site where you can find information no some of these new commands:

In case you're wondering, the .NET version has a few commands that the Silverlight version didn't have too.  This isn't a big deal as the commands that are missing don't really have much meaning for Silverlight (or have an alternative).  Here's a list of these:

comstate
dumpmethodsig
rcwcleanuplist
tst

Also, for the sake of completeness, below is the completely list of all Silverlight commands.  Just type then into WinDBG with the ! prefix to play with each of them.  For many of them you can type "!sos.help COMMANDNAME" to get help for a specific COMMANDNAME.

analyzeoom dumpsigelem histclear syncblk
ao dumpstack histinit t
bpmd dumpstackobjects histobj threadpool
clrstack dumpvc histobjfind threads
da eeheap histroot token2ee
do eestack histstats tp
dso eeversion hof traverseheap
dumparray ehinfo ip2md u
dumpassembly finalizequeue listnearobj verifyheap
dumpclass findappdomain lno verifyobj
dumpdomain findroots minidumpmode vh
dumpheap fq name2ee vmmap
dumpil gchandleleaks objsize vmstat
dumplog gchandles pe vo
dumpmd gcheapstat printexception  
dumpmodule gcinfo procinfo  
dumpmt gcroot savemodule  
dumpobj gcwhere soe  
dumpruntimetypes heapstat sosflush  
dumpsig help stoponexception  

Then there's the complete list of .NET SOS commands:

bpmd dumpstack procinfo
clrstack dumpstackobjects rcwcleanuplist
comstate dumpvc savemodule
da eeheap soe
do eestack sosflush
dso eeversion stoponexception
dumparray ehinfo syncblk
dumpassembly finalizequeue threadpool
dumpclass findappdomain threads
dumpdomain gchandleleaks token2ee
dumpheap gchandles traverseheap
dumpil gcinfo tst
dumplog gcroot u
dumpmd help verifyheap
dumpmethodsig ip2md vmmap
dumpmodule minidumpmode vmstat
dumpmt name2ee  
dumpobj objsize  
dumpruntimetypes pe  
dumpsig printexception  

If you haven't noticed yet, most of these aren't even documented commands. However, if you type them into SOS, you will not only see that they exist, you will be given the syntax for how to use them (and, then, there's !sos.help).

kick it on DotNetKicks.com