Как изменить настройку часового пояса Windows2k8 с помощью .net [duplicate]

На этот вопрос уже есть ответ здесь:

Установите системный часовой пояс из .NET 3 ответа

Я пытался изменить часовой пояс моей системы с помощью кода C # в течение нескольких дней, и ничто из того, что я пытаюсь сделать, не имеет особого смысла или не работает вообще. Я начал пытаться использовать синтаксис PInvoke для SetTimeZoneInformation, который я видел по другим вопросам здесь.

[DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool
SetTimeZoneInformation([In] ref TimeZoneInformation lpTimeZoneInformation);

Я пытался понять, как создать структуру TimeZoneInformation, и запутался, поскольку моя система, очевидно, имеет динамическую систему DST. Оказывается, с тех пор как в Vista Microsoft добавила новый способ обработки часовых поясов. Теперь вы должны использовать SetDynamicTimeZoneInformation

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool SetDynamicTimeZoneInformation([In] ref DynamicTimeZoneInformation lpTimeZoneInformation);

Я искал справку по этому API в msdn и нашел что-то, говорящее: «Приложение должно иметь привилегию SE_TIME_ZONE_NAME для успешной работы этой функции». В конце концов я нашелэтот страница с довольно хорошим кодом для этого. Проблема в том, что это просто не работает.

Вот мой нерабочий код:

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
    public int LowPart;
    public int HighPart;
}

[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
    public LUID Luid;
    public UInt32 Attributes;
    public UInt32 PrivilegeCount;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
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;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DynamicTimeZoneInformation
{
    public int bias;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string standardName;
    public SystemTime standardDate;
    public int standardBias;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string daylightName;
    public SystemTime daylightDate;
    public int daylightBias;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string timeZoneKeyName;
    public bool dynamicDaylightTimeDisabled;
}

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetDynamicTimeZoneInformation(out DynamicTimeZoneInformation lpTimeZoneInformation);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool SetDynamicTimeZoneInformation([In] ref DynamicTimeZoneInformation lpTimeZoneInformation);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int OpenProcessToken(int ProcessHandle, int DesiredAccess, ref int tokenhandle);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentProcess();

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int LookupPrivilegeValue(string lpsystemname, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES Newstate, int bufferlength, int PreivousState, int Returnlength);

public const int TOKEN_ASSIGN_PRIMARY = 0x00000001;
public const int TOKEN_DUPLICATE = 0x00000002;
public const int TOKEN_IMPERSONATE = 0x00000004;
public const int TOKEN_QUERY = 0x00000008;
public const int TOKEN_QUERY_SOURCE = 0x00000010;
public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public const int TOKEN_ADJUST_GROUPS = 0x00000040;
public const int TOKEN_ADJUST_DEFAULT = 0x00000080;

public const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
public const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
public const UInt32 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;

public static bool EnablePrivilege(string privilege)
{
    try
    {
        int token = 0;
        int retVal = 0;

        TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
        LUID LD = new LUID();

        retVal = OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token);
        retVal = LookupPrivilegeValue(null, privilege, ref LD);


        TP.PrivilegeCount = 1;
        TP.Attributes = SE_PRIVILEGE_ENABLED;
        TP.Luid = LD;

        retVal = AdjustTokenPrivileges(token, 0, ref TP, 1024, 0, 0);

        return true;
    }
    catch
    {
        return false;
    }
}

public static bool DisablePrivilege(string privilege)
{
    try
    {
        int token = 0;
        int retVal = 0;

        TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
        LUID LD = new LUID();

        retVal = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token);
        retVal = LookupPrivilegeValue(null, privilege, ref LD);
        TP.PrivilegeCount = 1;
        // TP.Attributes should be none (not set) to disable privilege
        TP.Luid = LD;

        retVal = AdjustTokenPrivileges(token, 0, ref TP, 1024, 0, 0);
        return true;
    }
    catch
    {
        return false;
    }
}

public bool SetSystemTimeZone(string timeZoneId)
{
    //I'm using the TimeZoneInfo class to populate a list in the UI.  This code to retrieve the correct timezone is working
    TimeZoneInfo newTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
    DynamicTimeZoneInformation dtzi = new DynamicTimeZoneInformation();
    dtzi.bias = -(Convert.ToInt32(newTimeZone.BaseUtcOffset.TotalMinutes));
    dtzi.standardBias = 0;
    //Here's where I start to lose it.  I don't know which adjustment rule to use from the GetAdjustmentRules call.  I'm just using the last one as that seems to usually be the most recent, but it doesn't always have to be.
    dtzi.daylightBias = Convert.ToInt32(newTimeZone.GetAdjustmentRules().Last().DaylightDelta.TotalMinutes);
    dtzi.standardName = newTimeZone.StandardName;
    dtzi.daylightName = newTimeZone.DaylightName;
    //It would be nice if this key name would just look up the timezone from the registry and use its settings
    dtzi.timeZoneKeyName = newTimeZone.Id;

    //No idea if this is the right way to create the SystemTime object I need here.
    SystemTime standardDate = new SystemTime();
    standardDate.Year = 0;
    standardDate.Hour = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionEnd.TimeOfDay.Hour;
    standardDate.Minute = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionEnd.TimeOfDay.Minute;
    standardDate.DayOfWeek = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionEnd.DayOfWeek;
    standardDate.Month = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionEnd.Month;
    standardDate.Day = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionEnd.Week;
    dtzi.standardDate = standardDate;

    SystemTime daylightDate = new SystemTime();
    standardDate.Year = 0;
    standardDate.Hour = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionStart.TimeOfDay.Hour;
    standardDate.Minute = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionStart.TimeOfDay.Minute;
    standardDate.DayOfWeek = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionStart.DayOfWeek;
    standardDate.Month = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionStart.Month;
    standardDate.Day = (ushort)newTimeZone.GetAdjustmentRules().Last().DaylightTransitionStart.Week;
    dtzi.daylightDate = daylightDate;

    dtzi.dynamicDaylightTimeDisabled = false;


    EnablePrivilege("SeTimeZonePrivilege");
    if (!SetDynamicTimeZoneInformation(ref dtzi))
        returnVal = false;
    DisablePrivilege("SeTimeZonePrivilege");

    return returnVal;
}

Кому-нибудь повезло с этим ... установкой часового пояса в системе после Vista? Возможно, есть лучший способ вообще.

Спасибо

Ответы на вопрос(2)

Ваш ответ на вопрос