I have the csv file with the following values:
User,TimeStamp
Pinky,11/4/2015 5:00
Brain,
Leo,never
Don,unspecified
I want to ensure this file for the TimeStamp column either has a date, or a $null value. To do this I am using the following code:
Function HealthCheckTimeStampColumn
{
Param ($userInputCsvFileWithPath)
Write-Host "Checking if TimeStamp column has invalid values..."
Import-Csv $userInputCsvFileWithPath | %{
if ($_.TimeStamp)
{
Try
{
([datetime]$_.TimeStamp).Ticks | Out-Null
}
Catch [system.exception]
{
$Error.Clear()
$invalidValue = $_.TimeStamp
Write-Error "Invalid Value found `"$_.TimeStamp`"; Value expected Date or `"`""
Exit
}
}
}
Write-Host "All values were found valid."
Write-Host "TimeStamp Healthcheck Column Passed"
Write-Host ""
}
With this code, I get this error:
Invalid Value found "Cannot convert value "never" to type "System.DateTime". Error: "The string was not recognized as
a valid DateTime. There is an unknown word starting at index 0.".TimeStamp"; Value expected Date or ""
At C:\Scripts\Tests\TestTime.ps1:247 char:42
+ Import-Csv $userInputCsvFileWithPath | %{
+ ~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
If I try this line of code Instead:
Write-Error "Invalid Value found `"$invalidValue`"; Value expected Date or `"`""
I get this error:
Invalid Value found ""; Value expected Date or ""
At C:\Scripts\Tests\TestTime.ps1:247 char:42
+ Import-Csv $userInputCsvFileWithPath | %{
+ ~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
The error I am expecting to see is this:
Invalid Value found "never"; Value expected Date or ""
At C:\Scripts\Tests\TestTime.ps1:247 char:42
+ Import-Csv $userInputCsvFileWithPath | %{
+ ~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
Can anyone tell me what I am doing wrong?
You don't really need a try/catch block for this one either. They are good for unexpected and unavoidable errors. However looking about_Type_Operators you will see -as and -is which handle this situation rather gracefully.
-is : Returns TRUE when the input is an instance of the specified .NET Framework type.
-as : Converts the input to the specified .NET Framework type.
When -as encounters a string or something that is not castable to [datetime] it will return a null. More importantly it will not error. I propose that you check all values for non nulls and invalid date times. Capture all of those in a variable. Then check if the variables has any values. Print all at once! and then exit if you want. I also second what user2460798's answer said about the use of exit.
Function HealthCheckTimeStampColumn{
Param ($userInputCsvFileWithPath)
$badRows = Import-Csv $userInputCsvFileWithPath |
Where-Object{-not [string]::IsNullOrEmpty($_.TimeStamp) -and ($_.TimeStamp -as [datetime]) -eq $null}
if($badRows){
$badRows | ForEach-Object{
Write-Host "'$($_.Timestamp)' is not a valid datetime" -ForegroundColor Red
}
Write-Error "$($badRows.Count) Invalid Value(s) found"
} else {
"All values were found valid.","TimeStamp Healthcheck Column Passed","" | Write-Host
}
}
Turning PerSerAl's observation into an answer:
$_ changes meaning from when it is in the foreach-object loop (but outside catch block) to when it is in catchblock. In the first case it is the current object (row), which apparently has the value "never" for its timestamp. But in the catch block it is the errorrecord that was generated as a result of the error. So to fix:
Function HealthCheckTimeStampColumn
{
Param ($userInputCsvFileWithPath)
Write-Host "Checking if TimeStamp column has invalid values..."
Import-Csv $userInputCsvFileWithPath | %{
$row = $_
if ($_.TimeStamp)
{
Try
{
([datetime]$_.TimeStamp).Ticks | Out-Null
}
Catch [system.exception]
{
$Error.Clear()
$invalidValue = $_.TimeStamp
Write-Error "Invalid Value found `"$row.TimeStamp`"; Value expected Date or `"`""
Exit
}
}
}
Write-Host "All values were found valid."
Write-Host "TimeStamp Healthcheck Column Passed"
Write-Host ""
}
BTW, if you want to process the whole file you'll need to remove exit from the catch block.
Related
My script is throwing an error like so:
ConvertFrom-StringData : Data item 'a3512c98c9e159c021ebbb76b238707e' in line 'a3512c98c9e159c021ebbb76b238707e = My
Pictures/Tony/Automatic Upload/Tony’s iPhone/2022-10-08 21-46-21 (2).mov' is already defined.
At P:\scripts\code\pcloud_sync.ps1:66 char:179
+ ... ace '^[a-f0-9]{32}( )', '$0= ' -join "`n") | ConvertFrom-StringData
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [ConvertFrom-StringData], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand
I want to catch this error by the "is already defined" text and then run a separate command if this is caught before the script reruns the code - possible?
You can use $_.Exception.Message attribute to get the exception message as string and then use -match statement to check if it's follows particular pattern.
$Here = #'
Msg1 = The string parameter is required.
Msg2 = Credentials are required for this command.
Msg1 = The specified variable does not exist.
'#
try {
ConvertFrom-StringData -StringData $Here
} catch {
if($_.Exception.Message -match "is already defined") {
Write-Output "Do Something"
}
}
Line 2 in the script below generates -
"Cannot convert value "System.Object[]" to type
"System.Xml.XmlDocument". Error: "'→', hexadecimal value 0x1A, is an
invalid character. Line 39, position 23."
At line:1 char:8
+ [xml]$x <<<< = Get-Content 4517.xml
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException"
What exception should be specified on line 4 (of the script) to catch the aforementioned error?
try {
[xml]$xml = Get-Content $file # line 2
}
catch [?] { # line 4
echo "XML parse error!"
# handle the parse error differently
}
catch {
echo $error
# some general error
}
Thanks for looking (and answering)
Adrian
Here is a way to discover yourself the full type name of an Exception, the result here gives System.Management.Automation.ArgumentTransformationMetadataException as given by #Adrian Wright.
Clear-Host
try {
[xml]$xml = Get-Content "c:\Temp\1.cs" # line 2
}
catch {
# Discovering the full type name of an exception
Write-Host $_.Exception.gettype().fullName
Write-Host $_.Exception.message
}
System.Management.Automation.ArgumentTransformationMetadataException
I am not able to get the correct report with the below part of code.
Here's what I am doing:
Importing .csv file into variable which contains UserName, LastSucessSync (date), Model.
With below foreach loop this will format the .html report and provide the values Green or Red.
Issue is, when Date is blank in .csv file it still shows GREEN or some times RED.
It also throws the below error:
Cannot convert value "" to type "System.DateTime". Error: "String was not
recognized as a valid DateTime."
At C:\MobileStats.ps1:87 char:4
+ if([datetime]$Entry.LastSuccessSync -lt (Get-Date).AddDays(-14) -or $Entry.LastS ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider
Rest of all is fine. Just I want to mark it as RED when date is blank or 14 days before.
PowerShell Code:
foreach ($Entry in $Result) {
if ([datetime]$Entry.LastSuccessSync -lt (Get-Date).AddDays(-14) -or $Entry.LastSuccessSync -like "") {
$Cdrivecolor="RED"
} else {
$Cdrivecolor="Green"
}
Import-Module SQLite
mount-sqlite -name places -data (resolve-path C:\Users\malware_win7x86\Desktop\places.sqlite)
$places = Get-ChildItem places:\moz_places
foreach ($entry in $places)
{
[datetime]$origin = '1970-01-01 00:00:00'
$visited = $entry.last_visit_date
if ($visited) {
$vtime = $origin.AddSeconds($visited)
} else {
$vtime = 'testing'
}
write-host ""
$entry.url,
$entry.visit_count,
$vtime
}
Reference: Convert Unix time with PowerShell
I'm curious on how to handle entries with no data.
For example, here is some output from that script:
http://sysforensics.org/
1
Exception calling "AddSeconds" with "1" argument(s): "Value to add was out of range.
Parameter name: value"
At line:7 char:28
+ $vtime = $origin.AddSeconds <<<< ($visited)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Any ideas on this?
Thanks
That error looks like you're giving AddSeconds an argument that is either too big or too small, rather than missing data. Calling AddSeconds with either $null or 0 will return the original date unchanged.
That being said—and I can't be sure, since you haven't provided the actual integer that you're trying to convert—I had the same problem until I realized that the data I was receiving was in milliseconds, not seconds. You can either use AddMilliseconds instead, or divide the number by 1000 before using AddSeconds if you don't care about the loss of precision.
Credit to this answer for pointing me in the right direction.
In that case you'd just skip the method call and substitute a default value, e.g.:
if ($visited) { # or maybe $ivisited -is [int] or whatever your criterion is
$vtime = $origin.AddSeconds($visited)
} else {
$vtime = $null
}
Line 2 in the script below generates -
"Cannot convert value "System.Object[]" to type
"System.Xml.XmlDocument". Error: "'→', hexadecimal value 0x1A, is an
invalid character. Line 39, position 23."
At line:1 char:8
+ [xml]$x <<<< = Get-Content 4517.xml
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException"
What exception should be specified on line 4 (of the script) to catch the aforementioned error?
try {
[xml]$xml = Get-Content $file # line 2
}
catch [?] { # line 4
echo "XML parse error!"
# handle the parse error differently
}
catch {
echo $error
# some general error
}
Thanks for looking (and answering)
Adrian
Here is a way to discover yourself the full type name of an Exception, the result here gives System.Management.Automation.ArgumentTransformationMetadataException as given by #Adrian Wright.
Clear-Host
try {
[xml]$xml = Get-Content "c:\Temp\1.cs" # line 2
}
catch {
# Discovering the full type name of an exception
Write-Host $_.Exception.gettype().fullName
Write-Host $_.Exception.message
}
System.Management.Automation.ArgumentTransformationMetadataException