Example #1
0
        protected override void ProcessRecord()
        {
            // make sure we've got fresh data, in case the requested time zone was added
            // to the system (registry) after our process was started
            TimeZoneInfo.ClearCachedData();

            // acquire a TimeZoneInfo if one wasn't supplied.
            if (this.ParameterSetName.Equals("Id", StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    InputObject = TimeZoneInfo.FindSystemTimeZoneById(Id);
                }
                catch (TimeZoneNotFoundException e)
                {
                    ThrowTerminatingError(new ErrorRecord(
                                              e,
                                              TimeZoneHelper.TimeZoneNotFoundError,
                                              ErrorCategory.InvalidArgument,
                                              "Id"));
                }
            }
            else if (this.ParameterSetName.Equals("Name", StringComparison.OrdinalIgnoreCase))
            {
                // lookup the time zone name and make sure we have one (and only one) match
                TimeZoneInfo[] timeZones = TimeZoneHelper.LookupSystemTimeZoneInfoByName(Name);
                if (0 == timeZones.Length)
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                                                   TimeZoneResources.TimeZoneNameNotFound, Name);
                    Exception e = new TimeZoneNotFoundException(message);
                    ThrowTerminatingError(new ErrorRecord(e,
                                                          TimeZoneHelper.TimeZoneNotFoundError,
                                                          ErrorCategory.InvalidArgument,
                                                          "Name"));
                }
                else if (1 < timeZones.Length)
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                                                   TimeZoneResources.MultipleMatchingTimeZones, Name);
                    ThrowTerminatingError(new ErrorRecord(
                                              new PSArgumentException(message, "Name"),
                                              TimeZoneHelper.MultipleMatchingTimeZonesError,
                                              ErrorCategory.InvalidArgument,
                                              "Name"));
                }
                else
                {
                    InputObject = timeZones[0];
                }
            }
            else // ParameterSetName == "InputObject"
            {
                try
                {
                    // a TimeZoneInfo object was supplied, so use it to make sure we can find
                    // a backing system time zone, otherwise it's an error condition
                    InputObject = TimeZoneInfo.FindSystemTimeZoneById(InputObject.Id);
                }
                catch (TimeZoneNotFoundException e)
                {
                    ThrowTerminatingError(new ErrorRecord(
                                              e,
                                              TimeZoneHelper.TimeZoneNotFoundError,
                                              ErrorCategory.InvalidArgument,
                                              "InputObject"));
                }
            }

            if (ShouldProcess(TimeZoneTarget))
            {
                bool acquireAccess = false;
                try
                {
                    // check to see if permission to set the time zone is already enabled for this process
                    if (!HasAccess)
                    {
                        // acquire permissions to set the timezone
                        SetAccessToken(true);
                        acquireAccess = true;
                    }
                }
                catch (Win32Exception e)
                {
                    ThrowTerminatingError(new ErrorRecord(e,
                                                          TimeZoneHelper.InsufficientPermissionsError,
                                                          ErrorCategory.PermissionDenied, null));
                }

                try
                {
                    // construct and populate a new DYNAMIC_TIME_ZONE_INFORMATION structure
                    NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION dtzi = new NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION();
                    dtzi.Bias           -= (int)InputObject.BaseUtcOffset.TotalMinutes;
                    dtzi.StandardName    = InputObject.StandardName;
                    dtzi.DaylightName    = InputObject.DaylightName;
                    dtzi.TimeZoneKeyName = InputObject.Id;

                    // Request time zone transition information for the current year
                    NativeMethods.TIME_ZONE_INFORMATION tzi = new NativeMethods.TIME_ZONE_INFORMATION();
                    if (!NativeMethods.GetTimeZoneInformationForYear((ushort)DateTime.Now.Year, ref dtzi, ref tzi))
                    {
                        ThrowWin32Error();
                    }

                    // copy over the transition times
                    dtzi.StandardBias = tzi.StandardBias;
                    dtzi.StandardDate = tzi.StandardDate;
                    dtzi.DaylightBias = tzi.DaylightBias;
                    dtzi.DaylightDate = tzi.DaylightDate;

                    // set the new local time zone for the system
                    if (!NativeMethods.SetDynamicTimeZoneInformation(ref dtzi))
                    {
                        ThrowWin32Error();
                    }

                    // broadcast a WM_SETTINGCHANGE notification message to all top-level windows so that they
                    // know to update their notion of the current system time (and time zone) if applicable
                    int result = 0;
                    NativeMethods.SendMessageTimeout((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE,
                                                     (IntPtr)0, "intl", NativeMethods.SMTO_ABORTIFHUNG, 5000, ref result);

                    // clear the time zone data or this PowerShell session
                    // will not recognize the new time zone settings
                    TimeZoneInfo.ClearCachedData();

                    if (PassThru.IsPresent)
                    {
                        // return the TimeZoneInfo object for the (new) current local time zone
                        WriteObject(TimeZoneInfo.Local);
                    }
                }
                catch (Win32Exception e)
                {
                    ThrowTerminatingError(new ErrorRecord(e,
                                                          TimeZoneHelper.SetTimeZoneFailedError,
                                                          ErrorCategory.FromStdErr, null));
                }
                finally
                {
                    if (acquireAccess)
                    {
                        // reset the permissions
                        SetAccessToken(false);
                    }
                }
            }
            else
            {
                if (PassThru.IsPresent)
                {
                    // show the user the time zone settings that would have been used.
                    WriteObject(InputObject);
                }
            }
        }
Example #2
0
        protected override void ProcessRecord()
        {
            // make sure we've got fresh data, in case the requested time zone was added
            // to the system (registry) after our process was started
            TimeZoneHelper.ClearCachedData();

            // acquire a TimeZoneInfo if one wasn't supplied.
            if (this.ParameterSetName.Equals("Id", StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    InputObject = TimeZoneInfo.FindSystemTimeZoneById(Id);
                }
#if CORECLR
                // TimeZoneNotFoundException is thrown by TimeZoneInfo, but not
                // publicly visible (so can't be caught), so for now we're catching
                // the parent exception time. This should be removed once the more
                // specific exception is available.
                catch (Exception e)
#else
                catch (TimeZoneNotFoundException e)
#endif
                {
                    ThrowTerminatingError(new ErrorRecord(
                        e,
                        TimeZoneHelper.TimeZoneNotFoundError,
                        ErrorCategory.InvalidArgument,
                        "Id"));
                }
            }
            else if (this.ParameterSetName.Equals("Name", StringComparison.OrdinalIgnoreCase))
            {
                // lookup the time zone name and make sure we have one (and only one) match
                TimeZoneInfo[] timeZones = TimeZoneHelper.LookupSystemTimeZoneInfoByName(Name);
                if (0 == timeZones.Length)
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        TimeZoneResources.TimeZoneNameNotFound, Name);
#if CORECLR
                    // Because .NET Core does not currently expose the TimeZoneNotFoundException
                    // we need to throw the more generic parent exception class for the time being.
                    // This should be removed once the correct exception class is available.
                    Exception e = new Exception(message);
#else
                    Exception e = new TimeZoneNotFoundException(message);
#endif
                    ThrowTerminatingError(new ErrorRecord(e,
                        TimeZoneHelper.TimeZoneNotFoundError,
                        ErrorCategory.InvalidArgument,
                        "Name"));
                }
                else if (1 < timeZones.Length)
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        TimeZoneResources.MultipleMatchingTimeZones, Name);
                    ThrowTerminatingError(new ErrorRecord(
                            new PSArgumentException(message, "Name"),
                            TimeZoneHelper.MultipleMatchingTimeZonesError,
                            ErrorCategory.InvalidArgument,
                            "Name"));
                }
                else
                {
                    InputObject = timeZones[0];
                }
            }
            else // ParameterSetName == "InputObject"
            {
                try
                {
                    // a TimeZoneInfo object was supplied, so use it to make sure we can find
                    // a backing system time zone, otherwise it's an error condition
                    InputObject = TimeZoneInfo.FindSystemTimeZoneById(InputObject.Id);
                }
#if CORECLR
                // TimeZoneNotFoundException is thrown by TimeZoneInfo, but not
                // publicly visible (so can't be caught), so for now we're catching
                // the parent exception time. This should be removed once the more
                // specific exception is available.
                catch (Exception e)
#else
                catch (TimeZoneNotFoundException e)
#endif
                {
                    ThrowTerminatingError(new ErrorRecord(
                        e,
                        TimeZoneHelper.TimeZoneNotFoundError,
                        ErrorCategory.InvalidArgument,
                        "InputObject"));
                }
            }

            if (ShouldProcess(TimeZoneTarget))
            {
                bool acquireAccess = false;
                try
                {
                    // check to see if permission to set the time zone is already enabled for this process
                    if (!HasAccess)
                    {
                        // acquire permissions to set the timezone
                        SetAccessToken(true);
                        acquireAccess = true;
                    }
                }
                catch (Win32Exception e)
                {
                    ThrowTerminatingError(new ErrorRecord(e,
                        TimeZoneHelper.InsufficientPermissionsError,
                        ErrorCategory.PermissionDenied, null));
                }

                try
                {
                    // construct and populate a new DYNAMIC_TIME_ZONE_INFORMATION structure
                    NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION dtzi = new NativeMethods.DYNAMIC_TIME_ZONE_INFORMATION();
                    dtzi.Bias -= (int)InputObject.BaseUtcOffset.TotalMinutes;
                    dtzi.StandardName = InputObject.StandardName;
                    dtzi.DaylightName = InputObject.DaylightName;
                    dtzi.TimeZoneKeyName = InputObject.Id;

                    // Request time zone transition information for the current year
                    NativeMethods.TIME_ZONE_INFORMATION tzi = new NativeMethods.TIME_ZONE_INFORMATION();
                    if (!NativeMethods.GetTimeZoneInformationForYear((ushort)DateTime.Now.Year, ref dtzi, ref tzi))
                    {
                        ThrowWin32Error();
                    }

                    // copy over the transition times
                    dtzi.StandardBias = tzi.StandardBias;
                    dtzi.StandardDate = tzi.StandardDate;
                    dtzi.DaylightBias = tzi.DaylightBias;
                    dtzi.DaylightDate = tzi.DaylightDate;

                    // set the new local time zone for the system
                    if (!NativeMethods.SetDynamicTimeZoneInformation(ref dtzi))
                    {
                        ThrowWin32Error();
                    }

#if !CORECLR
                    // broadcast a WM_SETTINGCHANGE notification message to all top-level windows so that they
                    // know to update their notion of the current system time (and time zone) if applicable
                    int result = 0;
                    NativeMethods.SendMessageTimeout((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE,
                        (IntPtr)0, "intl", NativeMethods.SMTO_ABORTIFHUNG, 5000, ref result);
#endif

                    // clear the time zone data or this PowerShell session
                    // will not recognize the new time zone settings
                    TimeZoneHelper.ClearCachedData();

                    if (PassThru.IsPresent)
                    {
                        // return the TimeZoneInfo object for the (new) current local time zone
                        WriteObject(TimeZoneInfo.Local);
                    }
                }
                catch (Win32Exception e)
                {
                    ThrowTerminatingError(new ErrorRecord(e,
                        TimeZoneHelper.SetTimeZoneFailedError,
                        ErrorCategory.FromStdErr, null));
                }
                finally
                {
                    if (acquireAccess)
                    {
                        // reset the permissions
                        SetAccessToken(false);
                    }
                }
            }
            else
            {
                if (PassThru.IsPresent)
                {
                    // show the user the time zone settings that would have been used.
                    WriteObject(InputObject);
                }
            }
        }