How do I mark a shortcut file as requiring elevation?


Specifying whether elevation is required is typically something that is the responsibility of the program. This is done by adding a requestedExecutionLevel element to your manifest. (Bart De Smet shows you how. Calvin Hsia does the same for your Visual FoxPro programs.) But if the program you're running doesn't have such a manifest—maybe it's an old program that you don't have any control over—you can create a shortcut to the program and mark the shortcut as requiring elevation.

To do this, you set the SLDF_RUNAS_USER flag in the shortcut attributes. Here's a skeleton program that sets the flag on the shortcut whose path is passed on the command line. For expository purposes, I've skimped on the error reporting, and just to shake things up, I've used ATL smart pointers.

#include <windows.h>
#include <shlobj.h>
#include <atlbase.h>

void MarkShortcutRunAs(LPCWSTR pszShortcut)
{
 CComPtr<IPersistFile> sppf;
 if (FAILED(sppf.CoCreateInstance(CLSID_ShellLink))) return;
 if (FAILED(sppf->Load(pszShortcut, STGM_READWRITE))) return;
 CComQIPtr<IShellLinkDataList> spdl(sppf);
 if (!spdl) return;
 DWORD dwFlags;
 if (FAILED(spdl->GetFlags(&dwFlags))) return;
 dwFlags |= SLDF_RUNAS_USER;
 if (FAILED(spdl->SetFlags(dwFlags))) return;
 if (FAILED(sppf->Save(NULL, TRUE))) return;
 wprintf(L"Succeeded\n");
}

int __cdecl wmain(int argc, wchar_t *argv[])
{
 if (argc == 2 && SUCCEEDED(CoInitialize(NULL))) {
  MarkShortcutRunAs(argv[1]);
  CoUninitialize();
 }
 return 0;
}

There's not really much to this program. It creates a shell link object (CLSID_ShellLink) and asks it to load from the file whose path is given on the command line. It then uses IShellLinkDataList::GetFlags and IShellLinkDataList::SetFlags to fetch the old flags and set new flags that include SLDF_RUNAS_USER. Once that's done, it saves the result back out.

The hard part was knowing that the SLDF_RUNAS_USER flag existed in the first place.

(I fear that most people will read this article and say, "Awesome! My program requires elevation, and this is how I can mark my Start menu shortcut to prompt for elevation. Thanks, Raymond!" These people will have completely ignored the opening paragraph, which explains that that is the wrong thing to do.)

Comments (25)
  1. John says:

    Wouldn’t it be easier to drop a manifest next to the executable?

  2. Joseph S. says:

    John, congratulations for not reading past the first sentence.

  3. "Wouldn’t it be easier to drop a manifest next to the executable?"

    Awesome. Just awesome.

    I’d be very sad if you were to stop writing here, Raymond, but it’s comments like this that really show what you’re up against trying to communicate with people who are too lazy (or full of themselves) to bother actually reading what you have to say.

    Have your dentistry bills increased now you’re gritting your teeth so often?

  4. Tim Smith says:

    As the first paragraph states, "maybe it’s an old program that you don’t have any control over".  This to me implies you are the user and not the developer.

    As a user, maybe you do have the option of adding a manifest file, maybe not.  Raymond is just trying to point out what you can do when you can’t take the "proper" approach.

  5. Ben Cooke says:

    Is there some means (other than this shortcut mechanism, which is of course for end users and not for developers) by which a particular program can support being run both elevated and not elevated? I’m thinking of a program which in normal circumstances wouldn’t require elevation, but sometimes you might need to run it that way to do some rarely-done thing.

    I suppose a cleaner solution in many cases would be to run the privileged part in a separate process which the unprivileged process can start, but I’m still curious as to whether the above is possible for curiosity’s sake.

  6. mvadu says:

    Hi Ben Cook, have a look at new version of AutoRuns (by earlier Sysinternals) at http://technet.microsoft.com/en-us/sysinternals/bb963902.aspx

    This version by default runs as a normal user, when you check or uncheck any auto run entry it pops up with a option to run itself as "Elevated Mode", it basically runs its own exe in elevated mode then terminates.

    So your idea is now a new thing.. and it might the "Proper" thing to do as a developer.

  7. mvadu says:

    "So your idea is now a new thing.. and it might the "Proper" thing to do as a developer."

    Sorry typo.. I mean your idea is NOT a new thing.. and it might be the "Proper" thing to do as a developer.

  8. Paul Gunn says:

    I don’t understand why people are flaming the first poster for a perfectly reasonable question. A manifest is just an xml file – creating one seems to require less technical ability than creating a program to create or modify a shortcut. Am I missing something here?

  9. Leo Davidson says:

    Paul Gunn, I think the first poster made a good point as well. I suspect the people flaming him misunderstood what he said and thought he meant modifying/adding the manifest into the exe. Maybe they don’t realise that the manifest can be a separate XML file next to the exe.

    About Raymond’s post itself: I believe he’s just trying to tell us what to do if we need to programatically create such a shortcut (maybe as part of a deployment tool for a legacy app?). If a user just wants to create a shortcut to run an app elevated then they can go to Properties -> Compatibility and check "Run this program as an administrator", which I expect runs some code in the Shell which does exactly as Raymond has described.

    Ben Cooke: UAC lets programs run themselves with an elevation prompt, like mvadu describes. It also allows programs to create elevated COM objects (again with an elevation prompt) which the unelevated code can then talk to, which is often a good solution when only parts of a program need to be elevated.

  10. Ron Parker says:

    Ben Cooke: Somewhat off topic, but if your application only occasionally needs to do tasks that require elevation, one "right" way to do it is to encapsulate that functionality in a COM object and use the COM Elevation Moniker to instantiate that object when you need to use that functionality: http://msdn2.microsoft.com/en-us/library/ms679687.aspx

    The difference between doing it this way and just doing it in an .exe running in a separate process is largely academic, of course, since your COM object gets instantiated in a surrogate process anyway.  One (very small) advantage is that you don’t have any .exe files lying around just waiting for end users to run them "to see what it does."  The advantage to both methods over what you propose is that the code that runs with privileged access in both cases is generally much smaller and easier to give the extra-careful audit it deserves.

  11. Ron Parker says:

    Leo Davidson: Properties->Compatibility adds an entry to the registry that causes the program to be run as administrator regardless of where it’s run from.  I suspect you meant to draw a parallel to the Properties->Shortcut "Advanced" tab and its "Run as administrator" checkbox.

  12. Dean Harding says:

    Don’t forget, the program may already have a manifest (e.g. common controls v6) and so just "dropping a new one in" may break whatever functionality it was relying on.

  13. Ben Cooke says:

    Thanks for the feedback, everyone. I like the elevated COM object thing; very clever! Presumably the complication of it running in another process is hidden from the developer behind the COM API, which is nice.

    Hopefully one day I’ll get a chance to play with this stuff. (My company’s still doing development on Windows XP, and we don’t have any Vista boxes.)

  14. ERock says:

    Awesome! My program requires elevation, and this is how I can mark my Start menu shortcut to prompt for elevation. Thanks, Raymond! :)

    (I kid I kid)

  15. John says:

    No, I meant for *ME* to drop a manifest there, not the *DEVELOPER*.  Why would I want to create a special shortcut when I could just create a manifest and have the application work regardless of how it is invoked?

  16. Bob Riemersma says:

    AFAIK you can extract the existing application manifest resource, edit it, and replace it too.

  17. jd2066 says:

    That doesn’t work for all programs though as some programs will not run if they have been changed. How the program would know if changed I don’t know.

  18. waleri says:

    OK, its an old program and I don’t have any control over (no manifest). Creating a link with SLDF_RUNAS_USER isn’t the proper approach either. So what *is* the proper approach for the user (if any)?

    Creating a manifest seems a better idea, because I won’t have to fix *all* shortcuts to that program. I believe, Raymond’s approach can be used by any user, while adding a manifest next to an exe requires… well, elevation.

  19. AndyC says:

    I can think of a handful of situations that can be solved with this approach that a manifest can’t manage. If you wanted a Start menu shortcut for editing a .ini file within the program’s directory in Notepad, for example.

  20. argv says:

    @waleri: It seems rather pointless for a user who doesn’t have access to an administrative account to add the SLDF_RUNAS_USER flag to a shortcut.

  21. MSDN Archive says:

    One example of "an old program that you don’t have any control over" is CMD.EXE.  

    When I was working on Visual Studio, we our build environment was set up by opening a CMD window and running a batch file to set PATH and other variables.  Typically you’d create a desktop shortcut that ran something like:

    CMD /k BUILDENVIRONMENT.CMD no_optimization

    These shortcuts were typically created by an automated tool which was written in C#.  

    Our build required you to be an administrator (silly) so we wanted to mark the shortcuts to run as admin on Vista.  However, you can’t mark CMD.EXE to always run elevated!

    It was my job to figure out how to develop VS on Vista, and I had to write the code to do the above.  It was tedious to write the P/Invoke declarations, but then the implementation was very clean.

    (Oh, and it was Raymond who helped me find SLDF_RUNAS_USER :-) )

  22. Drak says:

    Might this be a way to always run Studio 2005 as Admin on Vista (as that’s what it wants I think) ?

  23. hayate says:

    I wanna ask another question about shortcut and elevation here.

    If I wanna run a program in HOMEPATH, I can put this path in the shortcut’s "start in" property, but it will not work while marking it as requiring elevation.

    So is there a way to achieve it? Thanks

  24. hayate says:

    @Dean Harding

    Thanks very much. Since my rss items grow too many always, sometimes important items have been ignored.

Comments are closed.

Skip to main content