Reputation: 89
I'm getting all installed software on my computer, and print result to a HTML table. But a lot of dates have yyyyMMdd
format, but I would like yyyy-MM-dd
format.
Windows 10
Powershell version - 5.1.17
$Soft = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*;
#$Soft64 = Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*;
$InstallDate = $Soft | Select-Object InstallDate;
for ($i = 0; $i -lt $InstallDate.Length; $i++) {
if ($InstallDate[$i] -match '-') {
$InstallDate[$i]
} else {
$InstallDate = [DateTime]::ParseExact($InstallDate[$i], 'yyyyMMdd', $null)
$InstallDate.ToString('yyyy-MM-dd')
}
}
One date on list is with a good format (2019-04-01
) or they are empty/null, and after execute script I'm getting this result:
InstallDate ----------- 2019-04-01
But dates which don't contain -
, e.g. 20190319
, throw errors:
Cannot find an overload for "ParseExact" and the argument count: "3". At C:\Users\xxx\Desktop\xxx\ForLoopTest.ps1:12 char:9 + $InstallDate = [datetime]::ParseExact($InstallDate[$i], 'yyyy ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest Cannot find an overload for "ToString" and the argument count: "1". At C:\Users\xxx\Desktop\xxx\ForLoopTest.ps1:13 char:9 + $InstallDate.ToString('yyyy-MM-dd') + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest
Upvotes: 0
Views: 1162
Reputation: 200293
You need to remove empty InstallDate
results from the data you're parsing, and then expand the property, as @arco444 pointed out. Also, your loop currently assigns a parsed date back to the array variable over which your loop iterates, thus destroying all other values in that array.
Using InvariantCulture
instead of $null
, as @Moerwald suggested, is recommended, but not the cause of the issue. Another (performance-)optimization would be using the Contains()
string method instead of the -match
operator.
Something like this should do what you want:
$reg = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
$culture = [Globalization.CultureInfo]::InvariantCulture
$Soft = Get-ItemProperty $reg
$InstallDate = $Soft |
Where-Object { $_.InstallDate } |
Select-Object -Expand InstallDate
for ($i = 0; $i -lt $InstallDate.Length; $i++) {
if ($InstallDate[$i].Contains('-')) {
$InstallDate[$i]
} else {
$d = [DateTime]::ParseExact($InstallDate[$i], 'yyyyMMdd', $culture)
$d.ToString('yyyy-MM-dd')
}
}
Pipelining the entire processing is also a possibility:
$reg = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
$culture = [Globalization.CultureInfo]::InvariantCulture
Get-ItemProperty $reg | Where-Object {
$_.InstallDate
} | Select-Object -Expand InstallDate | ForEach-Object {
if ($_.Contains('-')) {
$_
} else {
[DateTime]::ParseExact($_, 'yyyyMMdd', $culture).ToString('yyyy-MM-dd')
}
}
Upvotes: 3
Reputation: 11254
You need to add a FormatProvider to specify culture when using ParseExact
:
$dt = [datetime]::ParseExact("20190319", "yyyyMMdd", [System.Globalization.CultureInfo]::InvariantCulture)
$dt.ToString("yyyy-MM-dd")
2019-03-19
ParseExact
throws an exception, therefore $InstallDate
is invalid and you call ToString
on it. You can add an additional $null
check:
$dt = [datetime]::ParseExact("20190319", "yyyyMMdd", [System.Globalization.CultureInfo]::InvariantCulture)
if ($dt) {
$dt.ToString("yyyy-MM-dd")
}
Hope that helps
Upvotes: 0