Force Imported Value as Integer

Viewed 78

I'm trying to save values between instances of the script running.

I'm doing that by reading a text file at the beginning of the script, and then overwriting that file with the new values at the end of the script.

tracker.txt:

 x=1
 y=4
 z=3

I'm reading the script using:

 Get-Content "$Root\tracker.txt" | Foreach-Object{
      $Position = $_.Split("=")
      New-Variable -Name $Position[0] -Value $Position[1]
      }

Unfortunately my $x $y and $z variables are being interpreted as a string instead of an integer.

Looking up New-Variable parameters, it doesn't seem like I can specify the value type.

Also I tried:

  New-Variable -Name $Position[0] -Value [int]$Position[1]

And:

  New-Variable -Name $Position[0] -Value ($Position[1] + 0)

But both did not work as expected.

How can I set these variables as an integer? I'm trying to use them later in a loop and that keeps failing because the variable can't be a string.

3 Answers

In order to save values, consider using Powershell's own object serialization. That is, Export-Clixml and Import-Clixml cmdlets. When an object is serialized, its contents are written on a file. In addition to values, data types are there too.

Handling multiple variables is easier, if those are stored in a collection such as a hash table. Like so,

# Save some values in a hash table
$myKeys =@{ "a" = 1; "b" = 2 }
$myKeys["a"]
1
# Check variable a's type. Int32 is as expected
$myKeys["a"].gettype()

IsPublic IsSerial Name                             BaseType
-------- -------- ----                             --------
True     True     Int32                            System.ValueType

# Serialize the hash table    
Export-Clixml -Path keys.xml -InputObject $myKeys

# Create a new hash table by deserializing    
$newKeys = Import-Clixml .\keys.xml

# Check contents
$newkeys["a"]
1

# Is the new a also an int32? Yes, it is
$newkeys["a"].gettype()

IsPublic IsSerial Name                             BaseType
-------- -------- ----                             --------
True     True     Int32                            System.ValueType

The keys.xml is, as expected an XML file. Check out its contents with, say, Notepad to see how the objects are stored. When working with complex objects, -Depth switch needs to be used. Otherwise, serialization saves only two levels of nesting, and that'll break complex objects.

To answer your specific question, you can force it like this.

@'
var1=1
var2=2
'@ | out-file "$Root\tracker.txt"

Get-Content "$Root\tracker.txt" | Foreach-Object{
    $Position = $_.Split("=")
    New-Variable -Name $Position[0] -Value ([int]$Position[1])
}

$var1.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                           
-------- -------- ----                                     --------                                                                                                                           
True     True     Int32                                    System.ValueType   

However I really like this approach.

Create a template

$template = @'
{name*:var1}={[int]value:1}
{name*:var2}={[int]value:2}
'@

Now use ConvertFrom-String and assign to $data

@'
test1=1
test2=2
test3=3
test4=4
test5=5
'@ | ConvertFrom-String -TemplateContent $template -OutVariable data

Let's create our variables now. Very easy to read.

$data | foreach {New-Variable -Name $_.name -Value $_.value}

Get-Variable test*

Name                           Value                                                                                                                                         
----                           -----                                                                                                                                         
test1                          1                                                                                                                                             
test2                          2                                                                                                                                             
test3                          3                                                                                                                                             
test4                          4                                                                                                                                             
test5                          5   

And most importantly, they are int.

$test1.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                          
-------- -------- ----                                     --------                                                                                                          
True     True     Int32                                    System.ValueType 

Putting it all together and pulling from a file

$template = @'
{name*:var1}={[int]value:1}
{name*:var2}={[int]value:2}
'@

Get-Content "$Root\tracker.txt" -raw | 
    ConvertFrom-String -TemplateContent $template |
        foreach {New-Variable -Name $_.name -Value $_.value}

I will use this:

(Get-Content tracker.txt) | foreach {
  invoke-expression "[int]`$$($_.split("=")[0])=$($_.split("=")[1])"
}

It will create three variables with type int32.

Related