tags:

views:

89

answers:

3

I'm porting an application from Windows 2000 (don't ask) to Windows 7 and I need to replicate functionality that allows the user to set the time from a GUI. Previously this had been done with a call directly to 'time' using the command prompt, but it appears the user permissions have changed somewhat in Windows 7.

Having done some research, it appears that you can set the time using a call to the kernel32.dll method Win32SetSystemTime, but the same permissions issue arises. Reading MSDN I think I need to enable SE_SYSTEMTIME_NAME, however no matter what I try I can't seem to make this work.

Does anyone have some tested example code for Windows 7 to allow an API call to Win32SetSystemTime?

+1  A: 

Well, if worst comes to worst, there is always

System.Diagnostics.Process.Start("CMD", "/C TIME 19:58");  // set time to 7:58PM
I. J. Kennedy
Sadly this doesn't seem to work in Windows 7. I get the error "A required privilege is not held by the client". My user is an administrator and this has been verified on 3 separate machines. If you have a work around for this I'd be grateful (as would many others judging from my research)
Tim Joseph
@I.J.: You would have to start the process with elevated permissions
Steve Ellinger
+1  A: 

Not sure why it's not working for you. The following code sets the time to today's date at 4:12 PM UTC. (Worked for me)

public class Program 
{
    public struct SystemTime
    {
        public ushort Year;
        public ushort Month;
        public ushort DayOfWeek;
        public ushort Day;
        public ushort Hour;
        public ushort Minute;
        public ushort Second;
        public ushort Millisecond;
    };

    [DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)]
    public extern static bool Win32SetSystemTime(ref SystemTime st);

    public static void Main(string[] args)
    {
        SystemTime st = new SystemTime
        {
            Year = 2010, Month = 10, Day = 18, Hour = 16, Minute = 12, DayOfWeek = 1
        };
    }
}

According to the docs:

The calling process must have the SE_SYSTEMTIME_NAME privilege. This privilege is disabled by default. The SetSystemTime function enables the SE_SYSTEMTIME_NAME privilege before changing the system time and disables the privilege before returning. For more information, see Running with Special Privileges.

So seems like that shouldn't be an issue.

Kirk Woll
"The calling process must have the SE_SYSTEMTIME_NAME privilege". Any ideas on assigning that privilege?
Tim Joseph
@Tim Joseph: Administrators and several other accounts have this privilege. You can use Procexp from Sysinternals to check what privileges are granted to each process and whether they are currently enabled. Local security policy can be changed to assign the privilege to other accounts.
Juho Östman
+1  A: 

Your app needs to be elevated to change the time (since changing the time could result in activity logs etc being untrue) but not to change the time zone. Put a manifest on your application with requireAdministrator and the app will elevate. (To test this before making the manifest, right-click your exe and Run As Adminstrator. This will elevate the app just the one time. Elevating is a different thing from being launched by someone who happens to be in the Administrators group. It's about choosing to use your powers.)

Chances are the user won't like the UAC prompt, so if the time-changing is rare, split it out into a separate exe, put a manifest on the main app with asInvoker and another on the time-changer with requireAdministrator, and launch the time-changer from the main app with ShellExecute. Ideally have a button or menu item to make this happen and put a shield icon on it so that the UAC prompt doesn't surprise the user. I decline UAC prompts I wasn't expecting.

Kate Gregory