Tuesday, June 19, 2012

Shell32 code compiled on Windows 7/ Vista does not run on XP/2003

Shell32 code which is compiled error-free on Windows Vista or Windows 7 doesn't run on Win2003/XP. 

Problem: I had a task of interacting with the windows shell32 to move items from one location to another (as a per-requisite for a build). I had this written in XP initially and executed it on a XP machine. Latter on, for unknown reasons (organizational policy ;)) I was upgraded to a Windows 7 machine. I had the same piece of code compiled in Windows 7 without any compile-time errors. However, it threw a run time exception when executed on a Windows Xp box.

          Shell32.ShellClass sc = new Shell32.ShellClass();
     Shell32.Folder SrcFlder = sc.NameSpace(from); //source
     Shell32.Folder DestFlder = sc.NameSpace(to); //destination
     Shell32.FolderItems items = SrcFlder.Items();

     DestFlder.MoveHere(items, 16);


Error when run on XP box: Unable to cast COM object of type "Shell32.ShellClass" to interface type "Shell32.IShellDispatch5"

Reason: The Shell library comes with a new library in Windows 7. The problem with this is that, in XP, the Shell32.ShellClass is not casted to Shell32.IShellDispatch5 but to  Shell32.IShellDispatch4 which is deprecated or obsolete (or whatever term MSFT uses)

As usual, after tonnes of googling I found a piece of VB code in a blog which boasts of solving the problem. I wrote a C# version of it and tried it. Yea, it did work like charm. :)

Solution: The C# method to solve the problem:

        public Shell32.Folder GetShell32NameSpace(Object folder)
     {
      Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
      Object shell = Activator.CreateInstance(shellAppType);
      return (Shell32.Folder)shellAppType.InvokeMember("NameSpace",System.Reflection.BindingFlags.InvokeMethod, null,shell, new object[] { folder });
     }


So, now all you have to do is to call the GetShell32NameSpace()to create Shell32 folder type and remove the first line from the error prone code. This will work in all machines irrespective of the Windows OS (XP, 2003, Vista, 7)

                   Shell32.Folder SrcFlder = GetShell32NameSpace(from);                      
             Shell32.Folder DestFlder = GetShell32NameSpace(to);

             Shell32.FolderItems items = SrcFlder.Items();
             DestFlder.MoveHere(items, 16);


Happy coding!

9 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. @Dong Hoang Minh, You are Welcome :)

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Had the same issue on a Windows 8 machine going down to W7, this solved it too! Thanks!

    ReplyDelete
  5. Thanks a lot!
    Article did really help with application compiled on W7 crashed on 2003 Server.

    ReplyDelete
  6. Thanks,
    It also works for an application compiled on win8 and run on win7.

    The same method works for "BrowseForFolder"

    ReplyDelete