如何使用.net更改Windows2k8的时区设置

发布于 2024-09-13 01:49:13 字数 7766 浏览 3 评论 0原文

我已经尝试用 C# 代码更改系统的时区几天了,但我所做的一切都没有多大意义或根本不起作用。我开始尝试使用我在其他问题中看到的 SetTimeZoneInformation 的 PInvoke 语法。

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

我正在研究应该如何创建 TimeZoneInformation 结构,但很困惑,因为我的系统显然有一个动态 DST 系统。事实证明,自从 Vista 以来,微软添加了一种处理时区的新方法。您现在必须使用 SetDynamicTimeZoneInformation

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

我在 msdn 上搜索了有关此 API 的帮助,并发现了一些内容:“应用程序必须具有 SE_TIME_ZONE_NAME 权限才能使此功能成功。”最终我找到了 this 页面,其中包含看起来非常好的代码来获取此内容完毕。问题是它不起作用。

这是我的非工作代码:

[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 系统中设置时区?也许还有更好的方法。

谢谢

I have tried to change the timezone of my system with c# code for a few days now and nothing I'm trying is making much sense or working at all. I started out trying to use the PInvoke syntax for SetTimeZoneInformation that I've seen on other questions here.

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

I was looking into how I should create the TimeZoneInformation struct and got confused since my system obviously has a dynamic DST system. Turns out that ever since Vista Microsoft added a new way of handling Timezones. You now have to use SetDynamicTimeZoneInformation

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

I searched for help with this API on msdn and found something saying, "An application must have the SE_TIME_ZONE_NAME privilege for this function to succeed." Eventually I found this page with what seems like pretty good code for getting this done. The problem is that it's just not working.

Here is my non-working code:

[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;
}

Has anyone had any luck with this...setting the timezone in a post Vista system? Perhaps there is a better way altogether.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦醒灬来后我 2024-09-20 01:49:13

TheCloudlessSky 的答案适用于 Windows XP:从 Vista 开始,要调用的函数是 SetDynamicTimeZoneInformation,否则将显示“无法识别您当前的时区。”,直到下次重新启动为止。 。

额外好处:调用 SetDynamicTimeZoneInformation 无需手动编辑注册表,因此无需以管理员身份启动程序。

这是 TheCloudlessSky 的代码片段,经过修改可在 Vista 及更高版本上运行

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace TimeZoneTest
{

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct SystemTime
    {
        [MarshalAs(UnmanagedType.U2)]
        public short Year;
        [MarshalAs(UnmanagedType.U2)]
        public short Month;
        [MarshalAs(UnmanagedType.U2)]
        public short DayOfWeek;
        [MarshalAs(UnmanagedType.U2)]
        public short Day;
        [MarshalAs(UnmanagedType.U2)]
        public short Hour;
        [MarshalAs(UnmanagedType.U2)]
        public short Minute;
        [MarshalAs(UnmanagedType.U2)]
        public short Second;
        [MarshalAs(UnmanagedType.U2)]
        public short Milliseconds;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string StandardName;
        public SystemTime StandardDate;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string DaylightName;
        public SystemTime DaylightDate;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
    }

    [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;
        [MarshalAs(UnmanagedType.U1)]
        public bool DynamicDaylightTimeDisabled;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RegistryTimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
        public SystemTime StandardDate;
        public SystemTime DaylightDate;

        public RegistryTimeZoneInformation(TimeZoneInformation tzi)
        {
            this.Bias = tzi.Bias;
            this.StandardDate = tzi.StandardDate;
            this.StandardBias = tzi.StandardBias;
            this.DaylightDate = tzi.DaylightDate;
            this.DaylightBias = tzi.DaylightBias;
        }

        public RegistryTimeZoneInformation(byte[] bytes)
        {
            if ((bytes == null) || (bytes.Length != 0x2c))
            {
                throw new ArgumentException("Argument_InvalidREG_TZI_FORMAT");
            }
            this.Bias = BitConverter.ToInt32(bytes, 0);
            this.StandardBias = BitConverter.ToInt32(bytes, 4);
            this.DaylightBias = BitConverter.ToInt32(bytes, 8);
            this.StandardDate.Year = BitConverter.ToInt16(bytes, 12);
            this.StandardDate.Month = BitConverter.ToInt16(bytes, 14);
            this.StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x10);
            this.StandardDate.Day = BitConverter.ToInt16(bytes, 0x12);
            this.StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
            this.StandardDate.Minute = BitConverter.ToInt16(bytes, 0x16);
            this.StandardDate.Second = BitConverter.ToInt16(bytes, 0x18);
            this.StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 0x1a);
            this.DaylightDate.Year = BitConverter.ToInt16(bytes, 0x1c);
            this.DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
            this.DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x20);
            this.DaylightDate.Day = BitConverter.ToInt16(bytes, 0x22);
            this.DaylightDate.Hour = BitConverter.ToInt16(bytes, 0x24);
            this.DaylightDate.Minute = BitConverter.ToInt16(bytes, 0x26);
            this.DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
            this.DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 0x2a);
        }
    }

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

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

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

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs,
            [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGE 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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                LUID LD = new LUID();

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

                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Attributes = SE_PRIVILEGE_ENABLED;
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

                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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                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
                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

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

    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID
    {
        internal uint LowPart;
        internal uint HighPart;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID_AND_ATTRIBUTES
    {
        internal LUID Luid;
        internal uint Attributes;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TOKEN_PRIVILEGE
    {
        internal uint PrivilegeCount;
        internal LUID_AND_ATTRIBUTES Privilege;
    }

    public class Program
    {

        public const int ERROR_ACCESS_DENIED = 0x005;
        public const int CORSEC_E_MISSING_STRONGNAME = -2146233317;

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

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

        public static void Main(string[] args)
        {

            var regTimeZones = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");

            // Print out all the possible time-zones.
            //foreach(var subKey in regTimeZones.GetSubKeyNames())
            //{
            //    Console.WriteLine(subKey);
            //}

            var subKey = regTimeZones.GetSubKeyNames().Where(s => s == "Atlantic Standard Time").First();
            string daylightName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Dlt");
            string standardName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Std");
            byte[] tzi = (byte[])regTimeZones.OpenSubKey(subKey).GetValue("TZI");

            var regTzi = new RegistryTimeZoneInformation(tzi);

            TokenPrivilegesAccess.EnablePrivilege("SeTimeZonePrivilege");

            bool didSet;
            if (Environment.OSVersion.Version.Major < 6)
            {
                var tz = new TimeZoneInformation();
                tz.Bias = regTzi.Bias;
                tz.DaylightBias = regTzi.DaylightBias;
                tz.StandardBias = regTzi.StandardBias;
                tz.DaylightDate = regTzi.DaylightDate;
                tz.StandardDate = regTzi.StandardDate;
                tz.DaylightName = daylightName;
                tz.StandardName = standardName;

                didSet = Program.SetTimeZoneInformation(ref tz);
            }
            else
            {
                var tz = new DynamicTimeZoneInformation();
                tz.Bias = regTzi.Bias;
                tz.DaylightBias = regTzi.DaylightBias;
                tz.StandardBias = regTzi.StandardBias;
                tz.DaylightDate = regTzi.DaylightDate;
                tz.StandardDate = regTzi.StandardDate;
                tz.DaylightName = daylightName;
                tz.StandardName = standardName;
                tz.TimeZoneKeyName = subKey;
                tz.DynamicDaylightTimeDisabled = false;

                didSet = Program.SetDynamicTimeZoneInformation(ref tz);
            }
            int lastError = Marshal.GetLastWin32Error();
            TokenPrivilegesAccess.DisablePrivilege("SeTimeZonePrivilege");

            if (didSet)
            {
                Console.WriteLine("Success, TimeZone Set!");
            }
            else
            {

                if (lastError == Program.ERROR_ACCESS_DENIED)
                {
                    Console.WriteLine("Error: Access denied... Try running application as administrator.");
                }
                else if (lastError == Program.CORSEC_E_MISSING_STRONGNAME)
                {
                    Console.WriteLine("Error: Application is not signed ... Right click the project > Signing > Check 'Sign the assembly'.");
                }
                else
                {
                    Console.WriteLine("Win32Error: " + lastError + "\nHRESULT: " + Marshal.GetHRForLastWin32Error());
                }
            }

            Console.ReadLine();
        }

    }
}

TheCloudlessSky's answer works for windows XP: starting with Vista the function to call is SetDynamicTimeZoneInformation, otherwise "Your current time zone is not recognized. Please select a valid time zone using the link below." will be shown until the next reboot.

Bonus: calling SetDynamicTimeZoneInformation makes it unnecessary to manually edit the registry, and so it won't be necessary to start the program as administrator.

Here is TheCloudlessSky's snippet modified to work on Vista and higher

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace TimeZoneTest
{

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct SystemTime
    {
        [MarshalAs(UnmanagedType.U2)]
        public short Year;
        [MarshalAs(UnmanagedType.U2)]
        public short Month;
        [MarshalAs(UnmanagedType.U2)]
        public short DayOfWeek;
        [MarshalAs(UnmanagedType.U2)]
        public short Day;
        [MarshalAs(UnmanagedType.U2)]
        public short Hour;
        [MarshalAs(UnmanagedType.U2)]
        public short Minute;
        [MarshalAs(UnmanagedType.U2)]
        public short Second;
        [MarshalAs(UnmanagedType.U2)]
        public short Milliseconds;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string StandardName;
        public SystemTime StandardDate;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string DaylightName;
        public SystemTime DaylightDate;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
    }

    [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;
        [MarshalAs(UnmanagedType.U1)]
        public bool DynamicDaylightTimeDisabled;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RegistryTimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
        public SystemTime StandardDate;
        public SystemTime DaylightDate;

        public RegistryTimeZoneInformation(TimeZoneInformation tzi)
        {
            this.Bias = tzi.Bias;
            this.StandardDate = tzi.StandardDate;
            this.StandardBias = tzi.StandardBias;
            this.DaylightDate = tzi.DaylightDate;
            this.DaylightBias = tzi.DaylightBias;
        }

        public RegistryTimeZoneInformation(byte[] bytes)
        {
            if ((bytes == null) || (bytes.Length != 0x2c))
            {
                throw new ArgumentException("Argument_InvalidREG_TZI_FORMAT");
            }
            this.Bias = BitConverter.ToInt32(bytes, 0);
            this.StandardBias = BitConverter.ToInt32(bytes, 4);
            this.DaylightBias = BitConverter.ToInt32(bytes, 8);
            this.StandardDate.Year = BitConverter.ToInt16(bytes, 12);
            this.StandardDate.Month = BitConverter.ToInt16(bytes, 14);
            this.StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x10);
            this.StandardDate.Day = BitConverter.ToInt16(bytes, 0x12);
            this.StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
            this.StandardDate.Minute = BitConverter.ToInt16(bytes, 0x16);
            this.StandardDate.Second = BitConverter.ToInt16(bytes, 0x18);
            this.StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 0x1a);
            this.DaylightDate.Year = BitConverter.ToInt16(bytes, 0x1c);
            this.DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
            this.DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x20);
            this.DaylightDate.Day = BitConverter.ToInt16(bytes, 0x22);
            this.DaylightDate.Hour = BitConverter.ToInt16(bytes, 0x24);
            this.DaylightDate.Minute = BitConverter.ToInt16(bytes, 0x26);
            this.DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
            this.DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 0x2a);
        }
    }

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

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

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

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs,
            [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGE 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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                LUID LD = new LUID();

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

                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Attributes = SE_PRIVILEGE_ENABLED;
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

                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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                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
                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

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

    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID
    {
        internal uint LowPart;
        internal uint HighPart;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID_AND_ATTRIBUTES
    {
        internal LUID Luid;
        internal uint Attributes;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TOKEN_PRIVILEGE
    {
        internal uint PrivilegeCount;
        internal LUID_AND_ATTRIBUTES Privilege;
    }

    public class Program
    {

        public const int ERROR_ACCESS_DENIED = 0x005;
        public const int CORSEC_E_MISSING_STRONGNAME = -2146233317;

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

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

        public static void Main(string[] args)
        {

            var regTimeZones = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");

            // Print out all the possible time-zones.
            //foreach(var subKey in regTimeZones.GetSubKeyNames())
            //{
            //    Console.WriteLine(subKey);
            //}

            var subKey = regTimeZones.GetSubKeyNames().Where(s => s == "Atlantic Standard Time").First();
            string daylightName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Dlt");
            string standardName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Std");
            byte[] tzi = (byte[])regTimeZones.OpenSubKey(subKey).GetValue("TZI");

            var regTzi = new RegistryTimeZoneInformation(tzi);

            TokenPrivilegesAccess.EnablePrivilege("SeTimeZonePrivilege");

            bool didSet;
            if (Environment.OSVersion.Version.Major < 6)
            {
                var tz = new TimeZoneInformation();
                tz.Bias = regTzi.Bias;
                tz.DaylightBias = regTzi.DaylightBias;
                tz.StandardBias = regTzi.StandardBias;
                tz.DaylightDate = regTzi.DaylightDate;
                tz.StandardDate = regTzi.StandardDate;
                tz.DaylightName = daylightName;
                tz.StandardName = standardName;

                didSet = Program.SetTimeZoneInformation(ref tz);
            }
            else
            {
                var tz = new DynamicTimeZoneInformation();
                tz.Bias = regTzi.Bias;
                tz.DaylightBias = regTzi.DaylightBias;
                tz.StandardBias = regTzi.StandardBias;
                tz.DaylightDate = regTzi.DaylightDate;
                tz.StandardDate = regTzi.StandardDate;
                tz.DaylightName = daylightName;
                tz.StandardName = standardName;
                tz.TimeZoneKeyName = subKey;
                tz.DynamicDaylightTimeDisabled = false;

                didSet = Program.SetDynamicTimeZoneInformation(ref tz);
            }
            int lastError = Marshal.GetLastWin32Error();
            TokenPrivilegesAccess.DisablePrivilege("SeTimeZonePrivilege");

            if (didSet)
            {
                Console.WriteLine("Success, TimeZone Set!");
            }
            else
            {

                if (lastError == Program.ERROR_ACCESS_DENIED)
                {
                    Console.WriteLine("Error: Access denied... Try running application as administrator.");
                }
                else if (lastError == Program.CORSEC_E_MISSING_STRONGNAME)
                {
                    Console.WriteLine("Error: Application is not signed ... Right click the project > Signing > Check 'Sign the assembly'.");
                }
                else
                {
                    Console.WriteLine("Win32Error: " + lastError + "\nHRESULT: " + Marshal.GetHRForLastWin32Error());
                }
            }

            Console.ReadLine();
        }

    }
}
时光无声 2024-09-20 01:49:13

我以前曾这样做过,这就是我的做法。

唯一的问题是,当您检查任务栏中的日期时间时,它显示无法识别您当前的时区。请使用下面的链接选择有效的时区。。我从来没有能够“修复”这个问题......所以是的。

编辑:我找到了一种使时区“有效”的方法(您必须重新启动计算机才能使其有效)工作)。请务必阅读说明 app.manifest 需要 requireAdministrator 的注释。 ^_^

祝你好运!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace TimeZoneTest
{

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct SystemTime
    {
        [MarshalAs(UnmanagedType.U2)]
        public short Year;
        [MarshalAs(UnmanagedType.U2)]
        public short Month;
        [MarshalAs(UnmanagedType.U2)]
        public short DayOfWeek;
        [MarshalAs(UnmanagedType.U2)]
        public short Day;
        [MarshalAs(UnmanagedType.U2)]
        public short Hour;
        [MarshalAs(UnmanagedType.U2)]
        public short Minute;
        [MarshalAs(UnmanagedType.U2)]
        public short Second;
        [MarshalAs(UnmanagedType.U2)]
        public short Milliseconds;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string StandardName;
        public SystemTime StandardDate;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string DaylightName;
        public SystemTime DaylightDate;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RegistryTimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
        public SystemTime StandardDate;
        public SystemTime DaylightDate;

        public RegistryTimeZoneInformation(TimeZoneInformation tzi)
        {
            this.Bias = tzi.Bias;
            this.StandardDate = tzi.StandardDate;
            this.StandardBias = tzi.StandardBias;
            this.DaylightDate = tzi.DaylightDate;
            this.DaylightBias = tzi.DaylightBias;
        }

        public RegistryTimeZoneInformation(byte[] bytes)
        {
            if ((bytes == null) || (bytes.Length != 0x2c))
            {
                throw new ArgumentException("Argument_InvalidREG_TZI_FORMAT");
            }
            this.Bias = BitConverter.ToInt32(bytes, 0);
            this.StandardBias = BitConverter.ToInt32(bytes, 4);
            this.DaylightBias = BitConverter.ToInt32(bytes, 8);
            this.StandardDate.Year = BitConverter.ToInt16(bytes, 12);
            this.StandardDate.Month = BitConverter.ToInt16(bytes, 14);
            this.StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x10);
            this.StandardDate.Day = BitConverter.ToInt16(bytes, 0x12);
            this.StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
            this.StandardDate.Minute = BitConverter.ToInt16(bytes, 0x16);
            this.StandardDate.Second = BitConverter.ToInt16(bytes, 0x18);
            this.StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 0x1a);
            this.DaylightDate.Year = BitConverter.ToInt16(bytes, 0x1c);
            this.DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
            this.DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x20);
            this.DaylightDate.Day = BitConverter.ToInt16(bytes, 0x22);
            this.DaylightDate.Hour = BitConverter.ToInt16(bytes, 0x24);
            this.DaylightDate.Minute = BitConverter.ToInt16(bytes, 0x26);
            this.DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
            this.DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 0x2a);
        }
    }

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

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

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

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs,
            [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGE 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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                LUID LD = new LUID();

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

                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Attributes = SE_PRIVILEGE_ENABLED;
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

                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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                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
                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

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

    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID
    {
        internal uint LowPart;
        internal uint HighPart;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID_AND_ATTRIBUTES
    {
        internal LUID Luid;
        internal uint Attributes;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TOKEN_PRIVILEGE
    {
        internal uint PrivilegeCount;
        internal LUID_AND_ATTRIBUTES Privilege;
    }

    public class Program
    {

        public const int ERROR_ACCESS_DENIED = 0x005;
        public const int CORSEC_E_MISSING_STRONGNAME = -2146233317;

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

        public static void Main(string[] args)
        {

            var regTimeZones = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");

            // Print out all the possible time-zones.
            //foreach(var subKey in regTimeZones.GetSubKeyNames())
            //{
            //    Console.WriteLine(subKey);
            //}

            var subKey = regTimeZones.GetSubKeyNames().Where(s => s == "Atlantic Standard Time").First();
            string daylightName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Dlt");
            string standardName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Std");
            byte[] tzi = (byte[])regTimeZones.OpenSubKey(subKey).GetValue("TZI");

            var regTzi = new RegistryTimeZoneInformation(tzi);

            var tz = new TimeZoneInformation();
            tz.Bias = regTzi.Bias;
            tz.DaylightBias = regTzi.DaylightBias;
            tz.StandardBias = regTzi.StandardBias;
            tz.DaylightDate = regTzi.DaylightDate;
            tz.StandardDate = regTzi.StandardDate;
            tz.DaylightName = daylightName;
            tz.StandardName = standardName;

            TokenPrivilegesAccess.EnablePrivilege("SeTimeZonePrivilege");
            bool didSet = Program.SetTimeZoneInformation(ref tz);
            int lastError = Marshal.GetLastWin32Error();
            TokenPrivilegesAccess.DisablePrivilege("SeTimeZonePrivilege");

            // NOTE: This fixes the "Your current time zone is not recognized. Please select a valid time zone using the link below" error 
            //       only when the machine is *restarted*.
            //       
            //       You must have the following set in your app.manifest to request admin rights to write to this key.
            //       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
            //          <security>
            //          <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
            //              <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
            //          </requestedPrivileges>
            //      ...
            var key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", true);
            key.SetValue("TimeZoneKeyName", key.GetValue("StandardName"));

            if (didSet)
            {
                Console.WriteLine("Success, TimeZone Set!");
            }
            else
            {

                if (lastError == Program.ERROR_ACCESS_DENIED)
                {
                    Console.WriteLine("Error: Access denied... Try running application as administrator.");
                }
                else if (lastError == Program.CORSEC_E_MISSING_STRONGNAME)
                {
                    Console.WriteLine("Error: Application is not signed ... Right click the project > Signing > Check 'Sign the assembly'.");
                }
                else
                {
                    Console.WriteLine("Win32Error: " + lastError + "\nHRESULT: " + Marshal.GetHRForLastWin32Error());
                }
            }

            Console.ReadLine();
        }

    }
}

I've done this before and here's how I did it.

The only problem is that when you check the DateTime in the task bar, it says Your current time zone is not recognized. Please select a valid time zone using the link below.. I've never been able to "fix" that... so yeah.

EDIT: I found a way to make the timezone "valid" (you must restart the machine to make it work). Be sure to read the NOTE that explains that app.manifest needs requireAdministrator. ^_^

Good luck!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace TimeZoneTest
{

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct SystemTime
    {
        [MarshalAs(UnmanagedType.U2)]
        public short Year;
        [MarshalAs(UnmanagedType.U2)]
        public short Month;
        [MarshalAs(UnmanagedType.U2)]
        public short DayOfWeek;
        [MarshalAs(UnmanagedType.U2)]
        public short Day;
        [MarshalAs(UnmanagedType.U2)]
        public short Hour;
        [MarshalAs(UnmanagedType.U2)]
        public short Minute;
        [MarshalAs(UnmanagedType.U2)]
        public short Second;
        [MarshalAs(UnmanagedType.U2)]
        public short Milliseconds;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string StandardName;
        public SystemTime StandardDate;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
        public string DaylightName;
        public SystemTime DaylightDate;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RegistryTimeZoneInformation
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;
        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;
        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
        public SystemTime StandardDate;
        public SystemTime DaylightDate;

        public RegistryTimeZoneInformation(TimeZoneInformation tzi)
        {
            this.Bias = tzi.Bias;
            this.StandardDate = tzi.StandardDate;
            this.StandardBias = tzi.StandardBias;
            this.DaylightDate = tzi.DaylightDate;
            this.DaylightBias = tzi.DaylightBias;
        }

        public RegistryTimeZoneInformation(byte[] bytes)
        {
            if ((bytes == null) || (bytes.Length != 0x2c))
            {
                throw new ArgumentException("Argument_InvalidREG_TZI_FORMAT");
            }
            this.Bias = BitConverter.ToInt32(bytes, 0);
            this.StandardBias = BitConverter.ToInt32(bytes, 4);
            this.DaylightBias = BitConverter.ToInt32(bytes, 8);
            this.StandardDate.Year = BitConverter.ToInt16(bytes, 12);
            this.StandardDate.Month = BitConverter.ToInt16(bytes, 14);
            this.StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x10);
            this.StandardDate.Day = BitConverter.ToInt16(bytes, 0x12);
            this.StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
            this.StandardDate.Minute = BitConverter.ToInt16(bytes, 0x16);
            this.StandardDate.Second = BitConverter.ToInt16(bytes, 0x18);
            this.StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 0x1a);
            this.DaylightDate.Year = BitConverter.ToInt16(bytes, 0x1c);
            this.DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
            this.DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 0x20);
            this.DaylightDate.Day = BitConverter.ToInt16(bytes, 0x22);
            this.DaylightDate.Hour = BitConverter.ToInt16(bytes, 0x24);
            this.DaylightDate.Minute = BitConverter.ToInt16(bytes, 0x26);
            this.DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
            this.DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 0x2a);
        }
    }

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

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

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

        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs,
            [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGE 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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                LUID LD = new LUID();

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

                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Attributes = SE_PRIVILEGE_ENABLED;
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

                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_PRIVILEGE TP = new TOKEN_PRIVILEGE();
                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
                var luidAndAtt = new LUID_AND_ATTRIBUTES();
                luidAndAtt.Luid = LD;
                TP.Privilege = luidAndAtt;

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

    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID
    {
        internal uint LowPart;
        internal uint HighPart;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct LUID_AND_ATTRIBUTES
    {
        internal LUID Luid;
        internal uint Attributes;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TOKEN_PRIVILEGE
    {
        internal uint PrivilegeCount;
        internal LUID_AND_ATTRIBUTES Privilege;
    }

    public class Program
    {

        public const int ERROR_ACCESS_DENIED = 0x005;
        public const int CORSEC_E_MISSING_STRONGNAME = -2146233317;

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

        public static void Main(string[] args)
        {

            var regTimeZones = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");

            // Print out all the possible time-zones.
            //foreach(var subKey in regTimeZones.GetSubKeyNames())
            //{
            //    Console.WriteLine(subKey);
            //}

            var subKey = regTimeZones.GetSubKeyNames().Where(s => s == "Atlantic Standard Time").First();
            string daylightName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Dlt");
            string standardName = (string)regTimeZones.OpenSubKey(subKey).GetValue("Std");
            byte[] tzi = (byte[])regTimeZones.OpenSubKey(subKey).GetValue("TZI");

            var regTzi = new RegistryTimeZoneInformation(tzi);

            var tz = new TimeZoneInformation();
            tz.Bias = regTzi.Bias;
            tz.DaylightBias = regTzi.DaylightBias;
            tz.StandardBias = regTzi.StandardBias;
            tz.DaylightDate = regTzi.DaylightDate;
            tz.StandardDate = regTzi.StandardDate;
            tz.DaylightName = daylightName;
            tz.StandardName = standardName;

            TokenPrivilegesAccess.EnablePrivilege("SeTimeZonePrivilege");
            bool didSet = Program.SetTimeZoneInformation(ref tz);
            int lastError = Marshal.GetLastWin32Error();
            TokenPrivilegesAccess.DisablePrivilege("SeTimeZonePrivilege");

            // NOTE: This fixes the "Your current time zone is not recognized. Please select a valid time zone using the link below" error 
            //       only when the machine is *restarted*.
            //       
            //       You must have the following set in your app.manifest to request admin rights to write to this key.
            //       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
            //          <security>
            //          <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
            //              <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
            //          </requestedPrivileges>
            //      ...
            var key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", true);
            key.SetValue("TimeZoneKeyName", key.GetValue("StandardName"));

            if (didSet)
            {
                Console.WriteLine("Success, TimeZone Set!");
            }
            else
            {

                if (lastError == Program.ERROR_ACCESS_DENIED)
                {
                    Console.WriteLine("Error: Access denied... Try running application as administrator.");
                }
                else if (lastError == Program.CORSEC_E_MISSING_STRONGNAME)
                {
                    Console.WriteLine("Error: Application is not signed ... Right click the project > Signing > Check 'Sign the assembly'.");
                }
                else
                {
                    Console.WriteLine("Win32Error: " + lastError + "\nHRESULT: " + Marshal.GetHRForLastWin32Error());
                }
            }

            Console.ReadLine();
        }

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文