Tuesday, April 02, 2013

C# code for Creating Shortcuts with Admin Privilege

Seattle skyline



If you just care about the code, then jump to the end

In the CLR team and across other engineering teams in Microsoft we use build environments which are essentially command shells with a custom environment setup using bat and cmd scripts. These scripts setup various paths and environment variables to pick up the right set of build tools and output paths matching the architecture and build flavor. E.g. one example of launching such a shell could be…

cmd.exe /k %BRANCH_PATH%\buildenv.bat <architecture> <build-flavor> <build-types> <etc...>

The architectures can vary between things like x86, amd64, ARM, build flavors vary between debug, check, retail, release, etc… The build-types indicate the target like desktop, CoreCLR, metro. Even though all combination is not allowed, the allowed combination approaches around 30. In case of .NET Compact Framework which supports way more architectures (e.g. MIPS, PPC) and targets (e.g. Xbox360, S60) the combination is even larger.

For day to day development I either need to enter this command each time to move to a different shell, or I have to create desktop shortcuts for all the combination. This becomes repetitive each time I move to a different code branch. I had created a small app that I ran each time I moved to a new branch and it would generate all the combination of shortcut given the branch details. However, our build requires elevation (admin-privilege). So even though I created the shortcuts, I’d have to either right click and use “Run as administrator” OR set that in the shortcuts property.



This was a nagging pain for me. I couldn’t find any easy programmatic way to create a shortcut with Administrator privilege (I’m sure there is some shell API to do that). So finally I binary compared two shortcuts, one with the “Run as administrator” and one without. I saw that only one byte was different. So I hacked up a code to generate the shortcut and then modify the byte. I am sure there is better/safer way to do this, but for now this “Works for me”.

The Code

Since I didn’t find any online source for this code, I thought I’d share. Do note that this is a major hack and uses un-documented stuff. I’d never do this for shipping code or for that matter anything someone other than me would rely on. So use at your own risk… Also if you have a better solution let me know and I will use that…

   1:  // file-path of the shortcut (*.lnk file)
   2:  string shortcutPath = Path.Combine(shortCutFolder, string.Format("{0} {1}{2}.lnk", arch, flavor, extra));
   3:  Console.WriteLine("Creating {0}", shortcutPath);
   4:  // the contents of the shortcut
   5:  string arguments = string.Format("{0} {1} {2} {3}{4} {5}", "/k", clrEnvPath, arch, flavor, extra, precmd);
   7:  // shell API to create the shortcut
   8:  IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath);
   9:  shortcut.TargetPath = cmdPath;
  10:  shortcut.Arguments = arguments;
  11:  shortcut.IconLocation = "cmd.exe, 0";
  12:  shortcut.Description = string.Format("Launches clrenv for {0} {1} {2}", arch, flavor, extra);
  13:  shortcut.Save();
  15:  // HACKHACK: update the link's byte to indicate that this is a admin shortcut
  16:  using (FileStream fs = new FileStream(shortcutPath, FileMode.Open, FileAccess.ReadWrite))
  17:  {
  18:      fs.Seek(21, SeekOrigin.Begin);
  19:      fs.WriteByte(0x22);
  20:  }

1 comment:

Anonymous said...

The Shortcuts WinForms Control supports the modifier keys, multiple keys shortcuts, and Shortcuts without modifier keys to build a keyboard trigger action, such as Ctrl, Alt and Shift with any other keys to trigger a specific action for their Windows applications.