Как я уже когда-то писал, у меня на компе сейчас стоят Mac OS X Snow Leopard, Windows 7 и Linux Mandriva. И все нормально работает, кроме одного досадного факта: каждый раз после выхода из Mac OS X и загрузки Windows 7, системное время для Windows почему-то сбрасывается на время по Гринвичу (хотя в настройках четко стоит наш часовой пояс). Комичность ситуации заключается в том, что в Linux все нормально: он продолжает показывать правильное время после любой последовательности загрузки/выгрузки других операционных систем. В итоге мне надоело каждый раз вручную исправлять системное время, поэтому было решено написать небольшую программку, которая автоматизировала бы этот процесс.
Как и другие мои программы под Windows, она писалась на C#.
Итак, сначала передо мной встала задача: научиться получать и устанавливать текущее время в системе. После непродолжительных поисков в интернете, было найдено короткое и несложное решение:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public short wYear; public short wMonth; public short wDayOfWeek; public short wDay; public short wHour; public short wMinute; public short wSecond; public short wMilliseconds; } [DllImport("kernel32.dll", SetLastError = true)] public static extern bool SetSystemTime(ref SYSTEMTIME time); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool GetSystemTime(ref SYSTEMTIME time); |
Как видно, делается импорт функций WinAPI из системной DLL.
И далее код использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SYSTEMTIME time = new SYSTEMTIME(); //получаем текущее время GetSystemTime(ref time); time.wYear = 2011; time.wMonth = 8; time.wDay = 11; time.wHour = 18; time.wMinute = 47; time.wSecond = 30; //устанавливаем новые значения SetSystemTime(ref time); |
Отлично. Теперь вроде бы осталось только написать правильную логику восстановления правильного времени… Но, не тут то было. Пресловутый UAC (User Account Control) не позволит сделать желаемое. Он просто не даст программе внести изменения, потому что правка времени в Windows 7 требует прав администратора. Что же делать? Решение есть. О нем ниже.
Для того, чтобы программа запускалась с правами администратора, необходимо к проекту в Visual Studio добавить «файл манифеста приложения». И вынести из комментария в нем строчку
1 |
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> |
По умолчанию у меня была вынесена строчка
1 |
<requestedExecutionLevel level="asInvoker" uiAccess="false" /> |
но она делает не совсем то, что нужно.
Пару слов об атрибуте requestedExecutionLevel. Он может иметь три возможных значения:
- asInvoker – приложение запускается с правами процесса-родителя. Этот режим рекомендуется Microsoft в большинстве случаев. Т.е. это те программы, которые не требуют прав администратора;
- highestAvailable – приложение запускается с более высокими правами, чем имеет текущий пользователь. С ними запускаются Regedit.exe, Mmc.exe и Eventvwr.exe;
- requireAdministrator – требуются для приложений, которые не могут работать без прав администратора.
Все, теперь программа сможет менять системное время. Правда, перед запуском она будет запрашивать разрешение на права администратора.
Полезная статья? Их будет больше, если вы поддержите меня!