Ron,
This isn't really documented very well in Microsoft's Technet or MSDN. I want to write a VB program to change the machine's ShortDate in its Regional Settings under Windows 95 to "mm/dd/yyyy" as the default is "m/d/yy" for the USA regional settings. This old setting will cause Y2K issues. Rather than change 600+ workstations by hand via the Control Panel "Regional Settings" Date settings, I would rather write a VB 5.0 program that runs from a Server Login script.
Any ideas?
-- Norman
Hello Norman,
Actually, I've always wondered how to retrieve and set the date and time format from Visual Basic, and have constantly included it as an action item on my "to do" list. But evidently, I've never really wanted to know badly enough to find out, since it's remained a perpetual action item. That was the situation when your question arrived, and a very good question it is.
I had thought that the answer would be shrouded in obscurity and mystery, and require the use of either the registry or the initialization file functions in the Win32 API, along with some spying tools to see from where Windows was retrieving its regional settings. As it turns out, though, that's really unnecessary; as Visual Basic programmers, we just don't pay much attention to regional settings because Visual Basic -- for better or for worse -- handles them for us, and so their operation is somewhat mysterious to us.
But in fact, a single Win32 function, SetLocaleInfo, can be used to set a wide range of regional settings. On success, the function returns a non-zero value; otherwise, it returns zero (or False). Its C language prototype is:
BOOL SetLocaleInfo(LCID Locale,
LCTYPE LCType, LPCTSTR lpLCData);
where the parameters are the following:
#define LOCALE_SSHORTDATE 0x0000001F
Of course, it would be just too simple if we were to change the system's date format unconditionally; instead, we have to provide the locale identifier whose short date format we want to change. This, however, is easily retrieved from the Win32 GetSystemDefaultLCID function; its prototype is:
LCID GetSystemDefaultLCID();
To translate all of this to Visual Basic, we have to add the following in the declarations section of our project's code module:
Public Const LOCALE_SSHORTDATE = &H1F
Public Declare Function GetSystemDefaultLCID _
Lib "kernel32" () As Long
Public Declare Function SetLocaleInfo Lib _
"kernel32" Alias "SetLocaleInfoA" ( _
ByVal Locale As Long, _
ByVal LCType As Long, _
ByVal lpLCData As String) As Boolean
Note that you want to use the ByVal keyword in passing lpLCData to the function, since you want to pass a pointer to a null-terminated C string; if you pass the argument by reference, you end up passing a pointer to a Visual Basic string, which will have rather unfortunate consequences.
Once you've figured out which Win32 API functions to call, changing the setting is simplicity itself:
Private Sub Main()
Dim lngLocale As Long
lngLocale = GetSystemDefaultLCID()
If SetLocaleInfo(lngLocale, _
LOCALE_SSHORTDATE, _
"MM/dd/yyyy") = _
False Then
' Handle error, possibly by writing it
' to a server error log
End If
End Sub
There are a couple of embellishments that you might want to make to the basic code. Since the utility will run transparently to the user, you'll want to log failures on the server rather than notify a no doubt astonished user. And presumably you want to call the PostMessage function to notify other applications that a Windows system setting has changed (although I've never noticed that it really makes a difference).
Thanks for your question. And for helping me remove one rather long-standing item from my "to do" list.
--Ron
Return to: Ron's VB Forum
Copyright © 2009 O'Reilly Media, Inc.