0

Since in XP most people are logged as admins - it's easy for a programmer to make a program work with the registry. What I am trying to do is this:

The software is started and it's added as a startup process in the registry- however this should be done only when the application is closing - not before.

However this doesn't work in XP when the user is limited and same thing in Vista, 7, 2008.

What are the workarounds? I was thinking to make the program create a scheduled task or being attached to a process with higher privileges? Any working way? My software is .NET related - actually same thing happens and in C++ - but I secretly hope that net offers easier methods to work it out.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
leo
  • 61
  • 1
  • 3
  • I'm not sure why this doesn't happen during **installation**. That's the best time for an app to register itself as a startup process, because the installer is already running as an elevated process with Admin privileges. It's not clear why you have to be able to do this on-the-fly. (But just in case, my answer below provides a solution.) – Cody Gray - on strike Apr 01 '11 at 00:36

3 Answers3

6

Um, this isn't a limitation of Windows 7; it's actually by-design. See my answer here for details.

What you need is called process elevation. It's the standard way of dealing with this, a mechanism built into UAC to allow users to authenticate themselves as Administrators and temporarily gain all of the privileges and responsibilities that come with this title. Windows itself uses this all over the place:

Example of elevation shield displayed in Windows UI

There's a fantastic how-to article available here: Shield icons, UAC, and process elevation in .NET.
But just to summarize in case of link rot, here are the steps:

  1. Determine if the user has the appropriate permissions already. The simplest way is calling the IsUserAnAdmin API function.

  2. Notify the user that elevation is required using a "shield" icon. In WinForms, you need to set the button's FlatStyle property to "System", and use P/Invoke to display the shield. Sample code:

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
                                            IntPtr wParam, IntPtr lParam);
    
    public const int BCM_SETSHIELD = 0x0000160C;
    
    public static void SetButtonShield(Button btn, bool showShield)
    {
        // Verify that we're running on Vista or later
        if ((Environment.OSVersion.Platform == PlatformID.Win32NT) &&
            (Environment.OSVersion.Version.Major >= 6))
        {
            SendMessage(btn.Handle, BCM_SETSHIELD, IntPtr.Zero,
                        showShield ? new IntPtr(1) : IntPtr.Zero);
        }
    }
    
  3. Re-launch the process with administrator privileges. This involves showing the elevation dialog to allow the user to elevate the program. Sample code:

    ProcessStartInfo psi = new ProcessStartInfo
                               {
                                   Arguments = "-justelevated",
                                   ErrorDialog = true,
    
                                   // Handle is the handle for your form
                                   ErrorDialogParentHandle = Handle,
                                   FileName = Application.ExecutablePath,
                                   Verb = "runas"
                               };
    try
    {
        Process.Start(psi);
        Close();
    }
    catch (Exception ex)
    {
        // the process couldn't be started. This happens for 1 of 3 reasons:
    
        // 1. The user cancelled the UAC box
        // 2. The limited user tried to elevate to an Admin that has a blank password
        // 3. The limited user tries to elevate as a Guest account
        MessageBox.Show(ex.Message);
    }
    
  4. [Optional] Code sign your application to replace the hostile-looking yellow UAC elevation box with a more pleasing gray or blue one.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
1

It should be per user anyway, and then you won't have permission problems. HKCU\Software\Microsoft\Windows\CurrentVersion\Run

Mark Sowul
  • 10,244
  • 1
  • 45
  • 51
0

the whole purpose of limited users is to prevent this.

m4tt1mus
  • 1,642
  • 14
  • 24
  • 2
    It is not to prevent it, it is there to let the user *know* that you're about to mess with the private parts. – Hans Passant Apr 01 '11 at 01:34
  • @leo Then you should register it as startup process only for the current user, not the whole system. To do it, just add an [entry to HKCU](http://stackoverflow.com/questions/5507818/workaround-against-registry-manipulation-limitation-in-windows-7/5508034#5508034) as @Mark suggests. – Alexey Ivanov Apr 01 '11 at 06:05
  • @Hans in XP limited users were made to restrict access. In windows 7 they're there in conjunction with UAC to warn you when messing with the innards. – m4tt1mus Apr 01 '11 at 18:39