Hi Pramod,
here is the updated Code which does change.
Remember to declare the ZonesHT at Form Level.
Put one button and one Listbox on your form and use the code.
Feel Free to modify and use....
<Code>
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Collections;
using System.Text;
namespace TestApp
{
[StructLayoutAttribute(LayoutKind.Sequential)]
struct SystemTime
{
public short year;
public short month;
public short dayOfWeek;
public short day;
public short hour;
public short minute;
public short second;
public short milliseconds;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TimeZoneInformation
{
public int bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string standardName;
SystemTime standardDate;
public int standardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string daylightName;
SystemTime daylightDate;
public int daylightBias;
}
public class ClassTime
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern int GetTimeZoneInformation(out TimeZoneInformation
lpTimeZoneInformation);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool SetTimeZoneInformation( ref TimeZoneInformation
lpTimeZoneInformation);
public static void SetTimeZone(TimeZoneInformation tzi)
{
// set local system timezone
SetTimeZoneInformation(ref tzi);
}
public static TimeZoneInformation GetTimeZone()
{
// create struct instance
TimeZoneInformation tzi;
// retrieve timezone info
int currentTimeZone = GetTimeZoneInformation(out tzi);
return tzi;
}
}
public class ReadTimeZones
{
public static Hashtable GetTimeZones()
{
RegistryKey HKLM =
RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,"");
RegistryKey TimeZoneKeys;
string timeZoneSubKey = "Software\\Microsoft\\Windows
NT\\CurrentVersion\\Time Zones";
TimeZoneKeys = HKLM.OpenSubKey(timeZoneSubKey);
RegistryKey IndividualZone;
Hashtable ZonesHT = new Hashtable();
foreach(string zonekey in TimeZoneKeys.GetSubKeyNames())
{
IndividualZone = TimeZoneKeys.OpenSubKey(zonekey);
TimeZoneInformation TZI = new TimeZoneInformation();
TZI.standardName = (string)IndividualZone.GetValue("Dlt");
TZI.daylightName = (string)IndividualZone.GetValue("Display");
byte [] b = (byte[]) IndividualZone.GetValue("TZI");
TZI.bias = BitConverter.ToInt32(b,0);
ZonesHT.Add(TZI.daylightName,TZI);
}
return ZonesHT;
}
}
}
</Code>
<Code for button to load the time Zones>
//ZonesHT is declared at Form Level and is a Hashtable
ZonesHT = ReadTimeZones.GetTimeZones();
foreach(string key in ZonesHT.Keys)
{
listBox1.Items.Add(key);
}
</Code for button to load the time Zones>
<Code for Listbox Selected Index Change>
TimeZoneInformation tz =(TimeZoneInformation)
ZonesHT[listBox1.SelectedItem];
ClassTime.SetTimeZone(tz);
</Code for Listbox Selected Index Change>
HTH
With Regards,
Kunal Cheda
pramod said:
Thanks Kunal for a prompt reply.
This is exactly what I have done.
But in my scenario I have a list box populated with all the time zones which
can be obtained from HKLM\SOFTWARE\Microsoft\Windows NT\Time Zones\
When a user select a different time zone from the list lets say "(GMT-04:00)
Santiago" which is Pacific SA Standard Time , then the system should set to
this time zone. In the registry there is a TZI key which are binary values
used to fill up the TIME_ZONE_INFORMATION structure. I have written helper
functions to parse these values. But even though the TIME_ZONE_INFORMATION
seems to contain valid information after setting the time zone, the system
clock does not change but the registry values at
HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation is set which is the
place holder for current time zone of the system.
Yes I am using SendMessageTimeout to broadcast the change.
In your code you have hard code bias = 240, which I achieve by interpreting
the TZI bytes.
After doing all this it seems I am unsuccessful in achieving the
functionality that windows provides through Control Panel\Date Time.
Any further suggestions appreciated.
Kunal Cheda said:
Hi Pramod,
Here is the sample code that should change your system clock as well..
Add a class and copy the code snippet, add the button to a form and copy the
second code snippet, Hope this works fine for you...
<Code>
using System;
using System.Runtime.InteropServices;
namespace TestApp
{
[StructLayoutAttribute(LayoutKind.Sequential)]
struct SystemTime
{
public short year;
public short month;
public short dayOfWeek;
public short day;
public short hour;
public short minute;
public short second;
public short milliseconds;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TimeZoneInformation
{
public int bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string standardName;
SystemTime standardDate;
public int standardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string daylightName;
SystemTime daylightDate;
public int daylightBias;
}
public class ClassTime
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern int GetTimeZoneInformation(out TimeZoneInformation
lpTimeZoneInformation);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool SetTimeZoneInformation( ref TimeZoneInformation
lpTimeZoneInformation);
public static void SetTimeZone(TimeZoneInformation tzi)
{
// set local system timezone
SetTimeZoneInformation(ref tzi);
}
public static TimeZoneInformation GetTimeZone()
{
// create struct instance
TimeZoneInformation tzi;
// retrieve timezone info
int currentTimeZone = GetTimeZoneInformation(out tzi);
return tzi;
}
}
}
</Code>
<Code for button to test>
TimeZoneInformation tzi = ClassTime.GetTimeZone();
TimeZoneInformation tz = new TimeZoneInformation();
tz.standardName = "Pacific SA Standard Time";
tz.bias = 240;
ClassTime.SetTimeZone(tz);
</Code for button to test>
With Regards,
Kunal Cheda
http://www.KCheda.com
Kunal Cheda said:
Hi Pramod,
try using this API to update.
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg,
UIntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags,
uint uTimeout, out UIntPtr lpdwResult);
http://www.pinvoke.net/default.aspx/kernel32/SetTimeZoneInformation.html
With Regards,
Kunal Cheda.
http://www.KCheda.com
:
Hi,
I am trying to set the time zone information for a windows machine from
a C# application. I have written a wrapper class for win32 api
SetTimeZoneInformation and GetTimeZoneInformation. I am able to get all the
time zones and the current time zone information. But when I try to set a new
time zone information i see that the registry values get updated but the
actual windows clock does not display these changes. I also broadcast the
WM_SETTINGCHANGE message so all applications know about the changed time zone
information, but with no effect.
Also how to determine for whether it is daylight saving time from TZI
byte values.
Can anyone point me to documentation as to how to set the time zone in C# or
give some suggestions.
thanks in advance.