2010-08-04 10 views
8

He intentado cambiar la zona horaria de mi sistema con el código C# durante unos días y nada de lo que intento tiene mucho sentido o no funciona. Empecé tratando de usar la sintaxis de PInvoke para SetTimeZoneInformation que he visto en otras preguntas aquí.Cómo cambiar la configuración de la zona horaria de Windows2k8 con .net

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

que estaba buscando en la forma en que debería crear la estructura TimeZoneInformation y se confundió ya que mi sistema, obviamente, tiene un sistema de dinámica de DST. Resulta que desde Vista Microsoft agregó una nueva forma de manejar Timezones. Ahora tiene que utilizar SetDynamicTimeZoneInformation

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

Busqué ayuda con esta API en MSDN y encontré algo que dice, "Una aplicación debe tener el privilegio SE_TIME_ZONE_NAME para esta función tenga éxito." Finalmente encontré this página con lo que parece ser un código bastante bueno para hacer esto. El problema es que simplemente no funciona.

Aquí está mi código que no funciona:

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

Alguien ha tenido un poco de suerte con este ... establecer la zona horaria en un sistema de post Vista? Tal vez hay una mejor manera en conjunto.

Gracias

Respuesta

10

que he hecho esto antes y aquí está cómo lo hice.

El único problema es que cuando se marca el DateTime en la barra de tareas, dice Your current time zone is not recognized. Please select a valid time zone using the link below.. Nunca he sido capaz de "arreglarlo" ... así que sí.

EDITAR: He encontrado una manera de hacer que la zona horaria "válida" (debe reiniciar la máquina para que funcione). Asegúrese de leer la NOTA que explica que app.manifest necesita requireAdministrator.^_^

¡Buena suerte!

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(); 
     } 

    } 
} 
+0

Esto es impresionante, gracias! – Rory

+0

Me ayudó, gracias. – Vadim

+0

He estado probando varios fragmentos de código de Internet y SO, pero este es el primero en funcionar. ¡GRACIAS! – HenryAdamsJr

12

respuesta de TheCloudlessSky funciona para Windows XP: a partir de Vista, la función para llamar es SetDynamicTimeZoneInformation, de lo contrario ". su zona horaria actual no es reconocido Por favor, seleccione una zona horaria válida utilizando el siguiente enlace" será mostrado hasta el próximo reinicio.

Bonificación: al llamar a SetDynamicTimeZoneInformation no es necesario editar manualmente el registro, por lo que no será necesario iniciar el programa como administrador.

Aquí se fragmento de TheCloudlessSky modificado para trabajar en Vista y más

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(); 
     } 

    } 
} 
+3

Esta debería ser la respuesta marcada. –

Cuestiones relacionadas