Get rid of Regsvr32, Regasm, Gacutil… A Shellextension for .Net and COM dlls

I had originally written a Shellextension for COM dlls, which would give you the option of registering/unregistering a dll (if it is a com dll) by right clicking on it. Here is the original post :

After several years, I finally took out some time and created a Shellextension which works for .Net assemblies as well. These are the few features it has :

1. If you right click on a DLL and if it is a COM Plus dll it will show you the following menu.

COM Plus DllsIf you click on a COM dll but it is not installed in COM+, then you will get all above options except, the last 3 options which are relevant to COM+ only. Also, if you right clik a COM only dll, then it WILL give you an option called “Create COM+ package”.

2. IF you Right click on a dll which is a .Net assembly and is Strong Named as well, you will see the following menu :

If you right click on an Assembly which is not Strong Named, you will see all options except GACUTIL

3. If you hover your mouse over a dll which is a .Net dll, you will see some brief information about the dll like below :

4. If you right click on an Assembly, you will see a menu option called “Open with Lutz Reflector”. In case you dont know what Lutz Reflector is, it is an awesome free tool written by Lutz Roeder which disassembles any .Net assembly and shows you the source code in a very easy to view typelibrary browser. Since you could have downloaded Lutz Reflector anywhere in your PC, my shellextension will prompt you for the location just once when you first click on this option. It will then remember the location and will just open the Reflector with your assembly loaded in it.

Tested with Lutz Reflector 5.1

UPDATE (8/21/08) – Just heard from Lutz Roeder, that his software will be further developed and maintained by Red-Gate software from now on. (It will still be free though). See link for details –>Click to see article

5. If you go to the thumbnail view of any folder which has dlls, the shellextension analyzes the dlls and puts and changes their icon which helps you identify them. The Shellextension can distinguish between a regular dll, COM dll, .Net 1.0, 1.0, 2.0, 3.0 and 3.5 assembly. See below :

6. Last but not the least, you can customize the behavior of the dll and turn the ShellExtensions off or on. You can toggle, IconHandler extension, Right Click context menu extension and ToolTip extension. Here is a snapshot of the configuration screen :

This is the first time I am releasing this ShellExtension, so there may be a few bugs in it. I would really appreciate if you can report the bugs to me by leave a comment in this post. I will try to work on them as soon as I can find time.



Enumerate members of an Active Directory group in .Net

My previous post [Click Link] shows how to enumerate members of an AD group using an LDAP query written in VBscript.

Here I am showing you how to do the same using C#. Although, this function is not recursive (i.e doesn’t list members of a group that may be nested within the group you have specified)

            DirectoryEntry group = new DirectoryEntry(LDAP://CN=GroupXXX,OU=Groups, 
            object members = group.Invoke("Members", null);
            String s = "";

            foreach (object member in (IEnumerable)members)
                DirectoryEntry x = new DirectoryEntry(member);
                s+= x.Properties["displayName"].Value + "\n";
            MessageBox.Show( s);

I know, after reading this you are thinking, “I hate these code examples where they conveniently show you a long LDAP string, and tell you to figure out the DN of the group yourself”.  To figure out what you need to put in the long LDAP:// can use this piece of vbscript code.

        Group = "GroupXXX" 
        rs = CreateObject("ADODB.RecordSet") 
        rs.Open(";(sAMAccountName=" & Group & ");adspath", "provider=ADsDSOObject") 

        If Not rs.EOF Then 
            s = rs(0).Value 
        End If 


NOTE: If you are so LDAP /Active Directory challenged that you cannot figure out what to put in the ww, xx, yy, zz. Then you can go to Start–>Adminstrative Tools–>Active Directory Users and Computer and you will see your domain name in the format ww.xx.yy.zz……..

Including a Google Map mash up with an Info popup/bubble in your webpage

Here are 4 simple steps to include a Google map in your ASP.Net web page :

Dim Coord As CoordinateCoord = Geocode.GetCoordinates(“1600 Amphitheatre Parkway,Mountain View, CA  94043”)

_LONGITUDE = Coord.Longitude  ‘_LONGITUDE is a class level public variable
_LATITUDE = Coord.Latitude ‘_LONGITUDE is a class level public variable

  • In your ASPX page,

<tr align="center"> 

<td colspan="2"> 

<div id="map" style="width: 450px; height: 300px"> 


<script src="" type="text/javascript"> 


<script type="text/javascript"> 


function load() { 

if (GBrowserIsCompatible()){ 

var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(<%=LATITUDE %>, <%=LONGITUDE %>), 13); 

var point = new GLatLng(<%=LATITUDE %>, <%=LONGITUDE %>);
var marker = new GMarker(point);map.addOverlay(marker); 

marker.openInfoWindowHtml('<b>html content</b>');} 







Just replace the XXXXXXXXXXXXXX with your API key and you are good to go. Happy Mapping !

Making an website or virtual directory run under a specific .Net framework

If you several different .Net frameworks installed on your machine, you will inevitably run into a situation where your .net 1.1 website wants to run under 2.0 framework or vice-versa and your code doesn’t work. Here are few quick steps to make your web site or virtual directory run under a specific .net framework.


UPDATE : There is a free tool that will do all the hardwork for you. It is called ASP.Net version switcher. ASPNETVersionSwitcher.exe

  • Open Command Prompt and CD to any .Net Framework folder (1.1 or 2.0)·        
  • Run aspnet_regiis –lk. This will show you output like this. In this case all my websites are running under .net framework 2.0
  • C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>aspnet_regiis -lk
    • W3SVC/  2.0.50727.42
    • W3SVC/1/2.0.50727.42
    • W3SVC/1/ROOT/   2.0.50727.42
    • W3SVC/1/ROOT/Site1/      2.0.50727.42
  • To make a site run under .Net 1.1 framework in this example, I will CD to the v1.1.4322 folder on my machine where .Net framework 1.1 resides.
  • Run aspnet_regiis -SN w3svc/1/root/site1 – In my case  Site1 is the name of the virtual dir

You will get a confirmation message and you are all set.

Cross-thread operation not valid: Control ‘Form1’ accessed from a thread other than the thread it was created on

Also Check Out: My latest venture. – a way for you to ask questions and get answers about local businesses around you. iTunes link: (only available in US for now)

The Problem :

  1. You are writing a windows application
  2. You make an asynchronous webservice call (or you launch a background worker thread to get some data)
  3. m_WebService1.FuncAsync() ‘If you are using VB.Net you probably have a member variable declared for the webservice and you are calling the MethodXXXAsync() function generated by Visual Studio when you added the WebReference.
  4. In your m_WebService1_MethodXXCompleted() event handler, you try to update the User Interface (eg. txtBox.text = value)
  5. At this point the screen blows up and you get the dreaded error :

Cross-thread operation not valid: Control ‘Form1’ accessed from a thread other than the thread it was created on

The Reason:

  1. If you are from the old COM/COM+ Days, you must remember that an STA (Single Threaded Apartment) can only be accessed by the thread that originally created it. All the controls on the form are created by the main thread of the application, so only the main thread can update it. When your asynch webservice call returns it is calling the MethodXXCompleted() event handler in the context of a different thread. This thread is not allowed to touch any controls on the form

The Solution :

  1. From the Asynch event handler, you need to invoke the function which will update the UI from the context of the original thread.
  2. code1.jpg
  3. Say, the function which will update the UI is called Private Sub UpdateApps(), you need to declare a delegate for this function. Later we invoke this delegate (see step2 to do the actual work). You cannot call this function directly because it will still happen in the context of the second thread and you will get the same error.
  4. code2.jpg

That should take care of the problem. J

How to convert/display a unicode string in

I spent hours trying to figure out what to do to be able to make my unicode string (which contained english characters) to show up in my web browser. It always showed up as Question Marks (?????) or just plain garbled text (like Chinese characters). I tried using different responseencoding and fileencoding values in web.config, but to no avail.

For some reason Microsoft has change StrConv function and has removed the vbUniCode and vbFromUnicode constants. So, you can no longer use that to get an ASCII representation of the string. Well, this is what finally worked for me (assume the string to be converted is in the variable strBody):

Imports System.Text

‘This will take care of unicode messages. Basically it strips everything down to ASCII

strBody = Encoding.ASCII.GetString(Encoding.Unicode.GetBytes(strBody))

Before :


After :


Determining if a DLL is a COM, COM Plus, .Net Assembly or Win32 using code

There are so many flavors of dlls out there these days that it becomes confusing. There was a time when there was only a Win32 dll…..then came along COM dlls…COM Plus Dlls…. assemblies….strong named assemblies…. etc etcThis is a class that I wrote which tells you what is the type of a particular DLL file. You just pass the DLL filepath in the constructor and it exposes dll properties to you.

input.jpg DLLParser.vb class (<– Click to view contents)

input.jpg compluswrap.txt (<– Click to view contents)

input.jpg mtxadmin.tlb (Right click–> save as–>Mtxadmin.Tlb)

eg. usage :-

Dim oParse As New DLLParser(FullDllPath)

MsgBox(“IsComPlus :” & oParse.IsComPlus & ” ComPlusPackageName :” & oParse.ComPlusPackageName)

MsgBox(“IsStrongNamed :” & oParse.IsStrongNamed)

MsgBox(“IsCom :” & oParse.IsCom)

MsgBox(“IsAssembly :” & oParse.IsAssembly