none
Region specific date formats - Incorrect InstalledOn date from Get-Hotfix RRS feed

  • Question

  • I first noticed when trying to look in powershell (v4) at what updates were applied after a given date by using:

    Get-HotFix | where { $_.installedon -gt "12/05/2015"}

    This returned no results, I expanded it to 12/05/2013, from that I received about 30 or so lines. Which to me was obviously wrong.

    Running "Get-Hotfix" returns a LOT of lined but the vast majority have no ‘InstalledOn’ value.

    Looking at the results and comparing them to the GUI I can see that where a date in en-GB format (dd/mm/yyyy) has a value for dd greater than 12 there is no value for ‘installedon’. I looked at other values where there was a date and if the date said it was installed on 01/12/2014 in powershell then it showed in the GUI that it was installed 12/01/2014. From that I believe that powershell is getting the date format confused with en-US (mm/dd/yyyy).

    When I looked at the region settings on my PC they are all correct and show en-GB. I’ve looked at other PCs in our domain using Enter-PSSession and the same is true there too.

    From the above, I know that the value for date is available as it displays OK in the GUI, but it won’t display in powershell.

    Can anyone help me find out where is powershell getting confused with date formats? I’m all out of places to look right now.

    -    I’m not sure if this helps but when I looked in WSUS computer status reports the language shows as en-US – I’m not sure where this is picked up from so I thought I’d include it.

    Friday, May 15, 2015 12:41 PM

Answers

  •  Thanks guys. For anyone else that stumbles across this page...

    This is what I ended up using:

    Get-HotFix -ComputerName . | Select-Object pscomputername,description,hotfixid,installedby, @{l="InstalledOn";e={ [DateTime]::Parse($_.psbase.properties["installedon"].value, $([System.Globalization.CultureInfo]::GetCultureInfo("en-US")))}} | Sort-Object InstalledOn -Descending | Format-list

    Found on page: http://powershell.com/cs/forums/t/12409.aspx 

    • Marked as answer by JG.UK Monday, May 18, 2015 2:43 PM
    Monday, May 18, 2015 2:43 PM

All replies

  • Does using parseexact work? It sounds as though it isn't recognising the string as a datetime, try this - 

    $date = [datetime]::ParseExact("12/05/2015", "dd/mm/yyyy", [System.Globalization.CultureInfo]::CurrentCulture)
    
    get-hotfix | ? {$_.installedon -gt $date}

    Friday, May 15, 2015 12:51 PM
  •  

    $date=[datetime]"12/05/2014"
    get-hotfix|?{$_.installedon -gt $date}

    Check $date to be sure PowerShell is set correctly.


    \_(ツ)_/

    Friday, May 15, 2015 1:50 PM
    Moderator
  • Thanks for the response...

    I've ran what you have suggested, unfortunately it still returns the same results. I like your approach though. I expanded the date range to 15/05/2013 and got 30 lines or so.

    J

    Friday, May 15, 2015 1:53 PM
  • Does using parseexact work? It sounds as though it isn't recognising the string as a datetime, try this - 

    $date = [datetime]::ParseExact("12/05/2015", "dd/mm/yyyy", [System.Globalization.CultureInfo]::CurrentCulture)
    
    get-hotfix | ? {$_.installedon -gt $date}

    No matter how you generate the date the system will make the $date object behave the same.  You are just trying to do an end run.  If the current culture is set correctly as stated then your suggestions is a no-op. 

    Think about it for a bit.

    It is either that PowerShell is not the correct version for MUI or the culture settings are wrong.  It is a slight possibility that there is a bug in WMI - but I don't think so.


    \_(ツ)_/

    Friday, May 15, 2015 1:54 PM
    Moderator
  • Running :

    $date=[datetime]"12/05/2014"
    get-hotfix|?{$_.installedon -gt $date}

    Then checking "$Date" is set to : 05 December 2014 00:00:00

    J

    Friday, May 15, 2015 1:57 PM
  • Hi JG,

    indeed, this is some lousy localization confusion on the Cmdlet's part (and just for reference: The dates the output does return are wrong, switching day with month). If you want to read the actual value returned (and it does return an en-US formatted date string!), you'll need to dig a bit deeper:

    $hotifx.psbase.Properties["InstalledOn"].Value

    Now why is this so painful?
    Well ... the return object has a script property that overwrites the native property. There was a reason for it, but the overwrite does not provide for localization.

    Options:

    • Filter it by using the syntax shown above (and parsing it)
    • Use Update-TypeData to fix the property (Add to profile to make this persistent)

    Cheers,
    Fred


    There's no place like 127.0.0.1

    Friday, May 15, 2015 2:01 PM
  • The time works correctly in "7"   and later.

    PS C:\scripts> $y[-1].Definition
    System.Object InstalledOn {get=if ([environment]::osversion.version.build -ge 7000)
                      {
                        # WMI team fixed the formatting issue related to InstalledOn
                        # property in Windows7 (to return string)..so returning the WMI's
                        # version directly
                        [DateTime]::Parse($this.psBase.properties["InstalledOn"].Value)
                      }
                      else
                      {
                        $orig = $this.psBase.properties["InstalledOn"].Value
                        $date = [datetime]::FromFileTimeUTC($("0x" + $orig))
                        if ($date -lt "1/1/1980")
                        {
                          if ($orig -match "([0-9]{4})([01][0-9])([012][0-9])")
                          {
                            new-object datetime @([int]$matches[1], [int]$matches[2], [int]$matches[3])
                          }
                        }
                        else
                        {
                          $date
                        }
                      };}


    \_(ツ)_/


    Friday, May 15, 2015 2:26 PM
    Moderator
  • Hi Fred - thanks for your reply...

    I'm going to go away and edit my script and see if i can make use of this. I'm pretty sure you've hit the nail on the head though.

    J

    Friday, May 15, 2015 2:34 PM
  • The time works correctly in "7"   and later.

    [...]


    \_(ツ)_/

    Hi JRV,

    actually, it doesn't. That comment refers to an initial error in the output. Their "solution" for Windows 7+ uses [DateTime]::Parse() which will use "dd/MM/yyyy" in my locale by default. However, WMI will return the en-US default "M/d/yyyy". For example, the WMI return on one of my hotfixes is "4/16/2015".

    The result is that on any en-US machine it will work flawlessly, on all others it will fail, unless you access the base data and force conversion from en-US to DateTime.

    Cheers,
    Fred


    There's no place like 127.0.0.1

    Friday, May 15, 2015 2:59 PM
  • This is what WMI returns:

    PS C:\scripts> ($x[0]|gm|select *)[-1].Definition
    System.Object InstalledOn {get=if ([environment]::osversion.version.build -ge 7000)
              {
              # WMI team fixed the formatting issue related to InstalledOn
              # property in Windows7 (to return string)..so returning the WMI's
              # version directly
              [DateTime]::Parse($this.psBase.properties["InstalledOn"].Value)
              }
              else
              {
              $orig = $this.psBase.properties["InstalledOn"].Value
              $date = [datetime]::FromFileTimeUTC($("0x" + $orig))
              if ($date -lt "1/1/1980")
              {
              if ($orig -match "([0-9]{4})([01][0-9])([012][0-9])")
              {
              new-object datetime @([int]$matches[1], [int]$matches[2], [int]$matches[3])
              }
              }
              else
              {
              $date
              }
              };}

    Which uses this:

    PS C:\scripts> $x[0].psbase.Properties['installedon'].Value
    9/6/2014
    PS C:\scripts> $x[0].psbase.Properties['installedon'].Value.GetType()

    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     True     String                                   System.Object

    Which would definitely break things.


    \_(ツ)_/


    Friday, May 15, 2015 3:18 PM
    Moderator
  • I'm really sorry - i think I'm missing something with how to make use of your advice.

    How can I  "Filter it by using the syntax shown above (and parsing it)"

    Thanks in advance

    J


    Friday, May 15, 2015 3:54 PM
  • Hi J,

    >> "Filter it by using the syntax shown above (and parsing it)"

    Please try the script below:

     Get-HotFix | where {$_.Properties["InstalledOn"].Value -gt "12/05/2015"}

    In addition, I follow this article, and get the desired result:

    PowerTip: Find Windows Hotfixes Installed After a Certain Date

    If there is anything else regarding this issue, please feel free to post back.

    Best Regads,

    Anna Wang


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. If you have feedback for TechNet Support, contact tnmff@microsoft.com

    Sunday, May 17, 2015 2:48 PM
    Moderator
  •  Thanks guys. For anyone else that stumbles across this page...

    This is what I ended up using:

    Get-HotFix -ComputerName . | Select-Object pscomputername,description,hotfixid,installedby, @{l="InstalledOn";e={ [DateTime]::Parse($_.psbase.properties["installedon"].value, $([System.Globalization.CultureInfo]::GetCultureInfo("en-US")))}} | Sort-Object InstalledOn -Descending | Format-list

    Found on page: http://powershell.com/cs/forums/t/12409.aspx 

    • Marked as answer by JG.UK Monday, May 18, 2015 2:43 PM
    Monday, May 18, 2015 2:43 PM