What am I not getting about [DateTime]::ParseExact()? - powershell

$timeinfo = "01-‎06‎-2017 ‏‎12:34"
$template = "dd-MM-yyyy HH:mm"
[DateTime]::ParseExact($timeinfo, $template, $null)
results in:
Exception calling "ParseExact" with "3" argument(s): "String was not recognized
as a valid DateTime."
At line:3 char:1
+ [DateTime]::ParseExact($timeinfo, $template, $null)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
I can't tell what is wrong here? Why is my string not a valid datetime when I specify in the template how it should read it?

You have some strange characters in your $timeinfo variable. When copying and pasting, I am getting this:
You can see this by pressing the right or left arrow and going through the string; it pauses at the odd character.
Changing to $timeinfo = "01-06-2017 12:34", your code works as expected. Copy and paste this string to test.
Edit - Using a Unicode converter, it looks like this is LRM control character

You probably copy and paste the code because there are incorrect characters in the $timedate, try copy and paste this:
$timeinfo = "01-06-2017 12:34"
$template = "dd-MM-yyyy HH:mm"
[DateTime]::ParseExact($timeinfo, $template, $null)

Related

PowerShell - Add-Content- Unable to add multiple vars to a file

I'm trying to add an expression to a log file which contains Date,Time some data separated by ";". Unfortunately I get an error every time I change the position of the items in the -value brackets.
Whats seems to be wrong?
This is the code :
Add-Content -path C:\...\outlog.txt -Value($Date + ';' + $Time + ';Checked;' + $strFileName)
This is the error :
Cannot convert argument "1", with value: ";", for "op_Addition" to type "System.TimeSpan": "Cannot convert
value ";" to type "System.TimeSpan". Error: "String was not recognized as a valid TimeSpan.""
At C:\...\Untitled1.ps1:8 char:64
+ ... \outlog.txt -Value($($Date + ';' + $Time + ';'+ $str))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Try this -
Add-Content -path C:\...\outlog.txt -Value("$Date; $Time; Checked; $strFileName")
If you look at get-help Add-Content -full, and look at the -value parameter, you will see -
-Value <Object[]>
Specifies the content to be added. Type a quoted string, such as "This data is for internal use only", or
specify an object that contains content, such as the DateTime object that Get-Date generates.
You cannot specify the contents of a file by typing its path, because the path is just a string, but you can
use a Get-Content command to get the content and pass it to the Value parameter.
Required? true
Position? 1
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? false
It says that it expects a quoted string or an object that contains content. It was missing in your case and hence the + operator was trying to add $date and time.

Trouble with [datetime]::parseexact

I know I must be missing something simple, but I've stared at it for a while and can't seem to see it.
I have the following powershell code
.".\Get-FileMetaDataReturnObject.ps1"
$BaseDirectory = "C:\Users\me\Desktop\Photo Test"
$Folders = get-childitem -path $BaseDirectory -Directory
foreach ($folder in $folders)
{
Write-Host "Folder name:$($folder.Name)"
$picture = Get-ChildItem -Path "$BaseDirectory\$($folder.Name)\"
$picMetaData = Get-FileMetaData -folder "$BaseDirectory\$($folder.Name)\"
$picDate = $picMetaData | Select 'Date Taken'
$picDateTaken = $picDate[0].'Date taken'
Write-Host $picDateTaken
$dateTime = [datetime]::parseexact($picDateTaken, "M/d/yyyy h:mm tt", [System.Globalization.CultureInfo]::InvariantCulture)
$dateStr = $dateTime.ToString('yyyy-MM-dd')
Write-Host $dateStr
}
When I run it I get the following error
Folder name:Deruta - Umbria, September 4, 2012
‎9/‎4/‎2012 ‏‎4:12 PM
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
At C:\Users\me\Desktop\Picture Folder Rename\PhotoFolderRename.ps1:18 char:5
+ $dateTime = [datetime]::parseexact($picDateTaken, "M/d/yyyy h:mm ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
The meta data script is found here
I'm really not sure what I've screwed up with the date time parsing, so any help would be appreciated.
Comparing "9/‎4/‎2012 ‏‎4:12 PM".Length (20) with "9/4/2012 4:12 PM".Length (16) shows us something fishy is going on, and indeed this string is not what it appears to be; there are U+200E LEFT-TO-RIGHT MARK and U+200F RIGHT-TO-LEFT MARK control characters in there, which are invisible (or not, depending on your console settings). Replacing these out will make the string parseable:
$picDateTaken = $picDateTaken -replace "\u200e|\u200f", ""
Replacing control characters in general would be more involved, and I'm not sure if there isn't a better/more general way to get the metadata in an invariant format, but as long as you know exactly what you're dealing with this is good enough.

Error parsing DateTime

I am trying to parse "time" strings for comparison purposes
$Test2 =[datetime]::Parse("24/09/2015 05:41:27",[Globalization.cultureinfo]::GetCultureInfo("en-US"))
$Test2
$Test =[datetime]::Parse("23/09/2015 05:41:27",[Globalization.cultureinfo]::GetCultureInfo("en-US"))
$Test
if($Test2 -gt $Test)
write-host comparison works
I get the following error:
Exception calling "Parse" with "2" argument(s): "String was not recognized as
a valid DateTime."
At C:\Users\Desktop\ne.ps1:1 char:1
+ $Test =[datetime]::Parse("23/09/2015
05:41:27",[Globalization.cultureinfo]::GetC ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
The en-US culture uses the month-day-year format, so you'll want to either:
Switch the culture you're using
Change the format of the input string
Here is a code sample:
### Change the date/time input string
[datetime]::Parse("09/23/2015 05:41:27")
### Use the Great Britain culture
[datetime]::Parse("23/09/2015 05:41:27", [cultureinfo]::GetCultureInfo('en-GB'))
Since / is a culture-sensitive date separator character, another options would be:
set CultureInfo.InvariantCulture:
[datetime]::Parse("24/09/2015 05:41:27",[Globalization.cultureinfo]::CultureInfo.InvariantCulture)
or utilize DateTime.ParseExact method:
[datetime]::ParseExact("23/09/2015 05:41:27","dd/MM/yyyy HH:mm:ss",[Globalization.cultureinfo]::GetCultureInfo("en-US"))

PowerShell ValidateLength with Read-Host

I am trying to use ValidateLength declaration with Read-Host, however I cannot get it to work. If I use it without Read-Host it works flawless. Here are some basic examples:
[ValidateLength(1,3)]$test = '123'
[ValidateLength(1,3)]$test1 = Read-Host
123
Attribute cannot be added because it would cause the variable test1 with value
123 to become invalid.
At line:1 char:1
+ [ValidateLength(1,3)]$test1 = Read-Host
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ValidationMetadataExcepti
on
+ FullyQualifiedErrorId : ValidateSetFailure
Is it possible to use ValidateLength declaration with Read-Host?
Declare your Read-Host as a string (since ValidateLength can not accept anything except a string) and the problem is solved.
[ValidateLength(1,3)]$test1 = [String](Read-Host "Input")
I am not sure why you have to cast a type on it, but it solves the problem.

Weird PowerShell Exec Output Capture Behavior

I'm writing a simple PowerShell script that handles the output of mkvinfo. It captures the output of mkvinfo, stores in a variable $s and does some post-processing on $s. The strange part is while $s has content, I can't extract a substring from it.
The error message I'm getting was:
Exception calling "Substring" with "1" argument(s): "startIndex cannot be larger than length of string.
Parameter name: startIndex"
This is a sample code:
$filePath = $folder + $file.name
$mkvinfoExe = "C:\mkvinfo.exe"
$s = & $mkvinfoExe $filePath
$s | out-host
$s.Substring($s.Length-1) | out-host
Are you sure $s is a string and not an array? If it is an array, $s.Length will be the number of elements in the array and you could get the error that you are getting.
For example:
PS > $str = #("this", "is", "a")
PS > $str.SubString($str.Length - 1)
Exception calling "Substring" with "1" argument(s): "startIndex cannot be larger than length of string.
Parameter name: startIndex"
At line:1 char:1
+ $str.SubString($str.Length - 1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
Just found out because mkvinfo outputs multiple lines, $s is actually a String array (or List?). Switching to $s[0].Substring($s[0].Length-1) solves it.