I'm getting the following error message:
The variable '$dateTime' cannot be retrieved because it has not been set.
The error is generated by the line [DateTime]$dateTime in this code:
[string]$registryEntry = Read-Registry -path $SCRIPT_KEY -name $key
[DateTime]$dateTime
if ($null -ne $registryEntry) {
$dateTime = [DateTime]$registryEntry
}
return $dateTime
But the error message makes no sense: I’m not trying to retrieve the $dateTime variable, I’m just declaring it.
I have to return a DateTime object, or $null if it’s undefined. FYI, the registry entry is the string “19 Jul 2023 05:52”
How do I make this work?
$psVersionTable:
Name Value
---- -----
PSVersion 7.3.6
PSEdition Core
GitCommitId 7.3.6
OS Microsoft Windows 10.0.19045
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
To add to Mathias R. Jessen's helpful answer:
I’m not trying to retrieve the
$dateTime
variable, I’m just declaring it.
PowerShell has no concept of mere variable declarations (the only exceptions are parameter variables - see the relevant section of about_Functions
).
You can only "declare" a variable by implicitly creating it via assigning a value to it. (If the variable already exists, it will be updated.)
Since you want to use a type constraint, i.e. to limit the values the variable can hold to a given type, the value you assign must be of that type or convertible to it; in the simplest case:
[datetime] $dateTime = 0
Using [int]
value 0
has the same effect as [datetime]::MinValue
, as shown in Mathias' answer, given that 0
can be converted to the latter, due to PowerShell's flexible automatic type conversions (see this answer).
If you either use no type constraint or you use a type constraint with a .NET reference type, you can use $null
for initialization; e.g.:
# No type constraint, same as [object]
$newVar = $null
# .NET reference-type type constraint
[regex] $newVar = $null
if $null
is allowed as a value in a given situation, you can also use the following single-statement idiom for initializing a variable with varying values, so as to guarantee the variable's existence, based on using an if
statement as an expression; it wouldn't work with [datetime]
, so I'm omitting the type constraint here:
# Assigns the output from the `if` statement.
$dateTime =
if ($null -ne $registryEntry) {
[datetime] $registryEntry
}
That is, the if
statement's output becomes the value of $datetime
, which means that if $null -ne $registryEntry
is true, [datetime] $registryEntry
is assigned, and $null
otherwise.[1]
Note that a PowerShell variable without a type constraint is free to not only be initialized with a value of an type (including $null
), but to also later be updated with a value of any other type.
As an aside:
As for what you tried:
In isolation, [DateTime]$dateTime
does the following:
It is a type cast, i.e. it tries to convert an existing $dateTime
variable to type [datetime]
and outputs the result:
That is, you are trying to retrieve the value of variable $dateTime
If $dateTime
does not exist yet...
... and you have Set-StrictMode
-Version 1
or higher in effect, you'll get the error you saw.
... otherwise, given that referencing non-existent variables defaults to $null
, your cast will be the equivalent of [datetime] $null
, which fails with Cannot convert null to type "System.DateTime"
In the event that such a cast succeeds its result is sent to the success output stream, which - in the absence of assigning it to a variable or passing it to a command - prints to the display by default, due to PowerShell's implicit output behavior, explained in the bottom section of this answer.
[1] Strictly speaking, it is the "Automation null" value that is assigned, which is an "enumerable null" that behaves like $null
in expression contexts, and like an empty enumerable in enumeration contexts - see this answer for details.