Sunday, October 6, 2013

Converting physical computer to virtual: Bluescreen

I have finally taken the leap and upgraded my trusty but painstakingly slow Windows Vista computer to Windows 8. I wanted to do a fresh install, but it is always nice to have a path back to using the old OS in case something goes wrong with the new installation. What better choice than doing a conversion of the physical Vista computer to a virtual one (a P2V)!

The free VMware vCenter Converter specializes in just that - it is an easy download and run application (the documentation is also good, but you won't really need it).

Caveat: Your only option is to do a full copy of your disk volume, which means you really need an extra disk drive of some kind (I used an external one) with at least the same amount of free space as the total capacity of your physical disk with all its partitions. It is fast however - a couple of hours was all it took to clone my 160 Gb drive - fully acceptable.

I went with all recommended/standard options and chose a VMware Workstation or other VMware virtual machine as the destination type, since I wanted VMware Player to handle the computer from inside my new Windows 8 after the installation.

Problem: The first conversion failed at around 96% with an error message stating that it could not update drive letters. However, the virtual disk and the .vmx file was already there, so I went ahead and tried to boot it from VMWare Player, making sure the network interfaces on the toolbar were all turned off to avoid the physical computer and the virtual one to find each other. Of course, the VM would not boot, but went into the bluescreen of death (BSOD) after the initial progress bars.

Cause/Solution: One of the recommended settings was to use SCSI as the virtual disk controller. On a second conversion attempt, I only changed this to IDE (corresponding to the physical controller in my computer). Another couple of hours later, my VM was ready and booted fine.

Wednesday, September 11, 2013

TFS 2012 authenticates trusted domain users, but not groups

I am configuring my first Team Foundation Server (TFS) 2012 in a domain we can call TFSdomain, that has a one-way trust to another domain where most users will access TFS from, let's call it the UserDomain. I tried to add UserDomain\Domain Admins to the Team Foundation Administrators group to let one of the group's users, UserDomain\Administrator have access to the TFS Web Administration. It did not allow access.

The UserDomain\Domain Admins is also a member of the local BUILTIN\Administrators which is a member of the Team Foundation Administrators group. This gives access to TFSdomain\Administrator, but not to UserDomain\Administrator.

I then added UserDomain\Administrator directly to the Team Foundation Administrators and tried again. Now I was allowed access as expected.

I then noticed the icon of the UserDomain\Administrator entry in the Team Foundation Administrators group. It shows the icon for a single user - not for a group. It is also not possible to see group members from the TFS Administration Console.


Have I discovered a bug in TFS 2012, or is there some other reason for this behavior?


Saturday, May 25, 2013

Language neutral Pin shortcut to Start Menu using C#

Problem: I needed a program that would automatically pin an existing shortcut on the desktop to the start menu, regardless what localization the Windows user was using. I was using Windows Server 2008 R2 with a couple of alternate languages to English installed for testing. The program was written in C#. I hit the wall a copule of times while trying to make c# code from an earlier implementation written in VB.NET - this is a summary of what I got to work in the end:
Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
Object oShell = Activator.CreateInstance(shellAppType);
Shell32.Folder oFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, oShell, new object[] { 0 }); //25 = common desktop, 0 is local desktop
 


if (System.IO.File.Exists(ShortcutTarget) & (oFolder != null))
{
   Shell32.FolderItem oFolderItem = oFolder.ParseName("somefile.lnk");
   Shell32.ShellLinkObject oShellLink = (Shell32.ShellLinkObject)oFolderItem.GetLink;
   if (oShellLink != null)
   {
      // Find localized shell32 verb used to pin shortcut to the start menu (so that it works in any language)
      StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
      IntPtr hShell32 = LoadLibrary("SHELL32");
      LoadString(hShell32, 5381, szPinToStartLocalized, MAX_PATH); // 5381 is the DLL index for "Pin to start menu", ref. http://www.win7dll.info/shell32_dll.html
      string localizedVerb = szPinToStartLocalized.ToString();

      foreach (Shell32.FolderItemVerb verb in oFolderItem.Verbs())
      {
         if (verb.Name == localizedVerb)
         {
            verb.DoIt();
            break;
         }
      }
   }
}


You need to reference Shell32 - i.e. Microsoft Shell Controls and Automation on the COM tab of your "Add reference" dialog in VS2010. Also make sure you copy the shell32.interop.dll along with your application when you move the application out of your bin folder.

The following problems were encountered and solved on the way:

BadImageFormatException when entering the method containing this code. The code worked well on a Windows Vista computer, but crashed when running on Server 2008 R2. I assume this happened because of the fact that Server 2008 R2 is a 64 bit OS, and this did not work well with using the unmanaged Shell32.
Solution: Change the target CPU of your application to x86. If you use VS2010 Express, this tip on StackOverflow may be helpful to you - Make sure to read all the answers if you are stuck.

InvokeVerb did not work. Before ending up using the line verb.DoIt(), I tried using oFolderItem.InvokeVerb(verb.Name), which used to work in an earlier VB.NET implementation of the same code. I have no explanation to why this did not work, but it did not. A conspiracy theory is that Nike paid them off to just do it...

By the way, this earlier post mentions a problem I encountered trying to do the same in VB.NET some time ago. It probably applies here too, which is why the top three lines of the code looks like they do.