9

I already know how to create shortcuts programmatically from my C# applications using IWshRuntimeLibrary and WshShellClass. Or I could use IShellLink.

Now, if the user's PC is running Windows Vista or Windows 7, I would like to be able to set the "Run as administrator" property of that shortcut programmactically as well.

Is that possible? If so, how?

alt text

JohnB
  • 18,046
  • 16
  • 98
  • 110
  • 1
    If Vista allows Run as Administrator to be set programatically, that is an absolutely enormous, breathtaking and horrendous security hole. Don't you think? – Adam Crossland Oct 27 '10 at 17:49
  • 2
    @Adam: No, because you are prompted to authorize every time you run with elevated privileges, even if the flag is set on the shortcut (as opposed to right click and run as admin) - Now, if you could turn off UAC programmatically without the user's OK... – Gabriel Magana Oct 27 '10 at 18:05
  • *absolutely* not! 1. Because even if the shortcut has that property set, Windows still prompts with the infamous UAC dialog. 2. Because there are other ways to get your application to Run as administrator (i.e. manifest sets requireAdministrator or have the process restart itself with `ProcessStartInfo.Verb = "runas"`) and both those would prompt with the UAC dialog too. – JohnB Oct 27 '10 at 18:12
  • 1
    If you want the app to ALWAYS run as Admin, @Doug is right, and you can use an embedded manifest if you wrote the app and an external one if you didn't. If you sometimes want to run this app as admin and sometimes not (eg a shortcut to IE or notepad, while the user could still run it non elevated through a different shortcut or the start menu) and you're creating the shortcut programmatically then @Anders is right. There's no security hole, and either approach is right for certain circumstances. – Kate Gregory Oct 28 '10 at 11:34

4 Answers4

8

This example is in PowerShell, but is uses the same objects and classes as C#.

Use the following code to get the byte number to activate:

# Find the missing admin byte (use this code, when changing the link):
$adminon = [System.IO.File]::ReadAllBytes($shortCutLocation)
$adminoff = [System.IO.File]::ReadAllBytes($shortCutLocation)
for ($i = 0; $i -lt $adminon.Count; $i++) { 
    if ($adminon[$i] -ne $adminoff[$i]) { 
        Write-Host Location: $i Value: $($adminon[$i])  
    } 
}

I got byte number 21 and its value was 34. So this is the script I user:

# Turning on the byte of "Run as Admin"
$lnkBytes = [System.IO.File]::ReadAllBytes($shortCutLocation)
$lnkBytes[21] = 34
[System.IO.File]::WriteAllBytes($shortCutLocation, $lnkBytes)
mklement0
  • 382,024
  • 64
  • 607
  • 775
Mor Shemesh
  • 2,689
  • 1
  • 24
  • 36
6

While Doug's answer is the correct solution to this problem, it is not the answer to this specific question...

To set that property on a .lnk, you need to use the IShellLinkDataList COM interface. The great Raymond Chen has c++ sample code on his blog for this

mklement0
  • 382,024
  • 64
  • 607
  • 775
Anders
  • 97,548
  • 12
  • 110
  • 164
  • 2
    Not very useful until you show him how to get the interface declarations into his C# program. – Hans Passant Oct 27 '10 at 19:03
  • @Hans: I was thinking of embedded the C++ DLL into my C# program; is there a better way? @Anders: thank you for pointing out this solution. I agree with you that Doug's answer is the correct approach to this UAC issue. – JohnB Oct 27 '10 at 19:36
5

You will need to create a manifest file for your application in order to get it to request run as an administrator privileges. Here is a nice tutorial you can follow.

Enjoy!

mklement0
  • 382,024
  • 64
  • 607
  • 775
Doug
  • 5,268
  • 24
  • 31
  • 1
    +1 for the nice tutorial. Yes I already know about the manifest file, as well as another option (see my comment below my question), but I was still wondering if was possible to set that *new* property on the shortcuts. – JohnB Oct 27 '10 at 18:15
  • FYI, here's a video tutorial about the manifest: http://channel9.msdn.com/Blogs/jmazner/How-To-Tell-Vistas-UAC-What-Privelege-Level-Your-App-Requires. He mentions the *shortcut* option, but re-iterates that **the *UAC Manifest* is the correct solution**. – JohnB Oct 27 '10 at 19:03
  • Create and Embed an Application Manifest (UAC): http://msdn.microsoft.com/en-us/library/bb756929.aspx – JohnB Oct 29 '10 at 19:16
5

With this method you can create a shortcut that its “Run as administrator” property is set: first, you need to add a reference to the "Windows Script Host Object Model" library, it is a COM library, so in the project, right-click on the reference go to the COM section, and add the library.

using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using IWshRuntimeLibrary;

class Solution
{


    static void CreateShortcut(string shortcutPath, string sourcePath, bool runAsAdmin, params string[] args)
    {
        var shortcut = new IWshShell_Class().CreateShortcut(shortcutPath) as IWshShortcut;
        shortcut.TargetPath = System.IO.Path.GetFullPath(sourcePath);

        shortcut.Arguments = "\"" + string.Join("\" \"", args) + "\"";
        shortcut.Save();

        if (runAsAdmin)
            using (var fs = new FileStream(shortcutPath, FileMode.Open, FileAccess.ReadWrite))
            {
                fs.Seek(21, SeekOrigin.Begin);
                fs.WriteByte(0x22);
            }
    }

    static void Main(string[] args)
    {
        CreateShortcut(Directory.GetCurrentDirectory() + "\\" + "shortcutName" + ".lnk", @"C:\...... path to file ... .exe", true);

    }
}

Credit for run as admin section belongs to here

ssz
  • 177
  • 3
  • 5