Dynamic variable and value assignment in powershell - variables

How can I declare variables and assign values to them at run time.
Reason: I am fetching these variables values from sql server and these variable values are configurable in nature
Code which I have tried till now
[array]$varArray = #($($ServerName),$($HostName))
foreach($varname in $varArray)
{
$varname = "some test value"
}
Write-Host $ServerName
Write-Host $HostName

The simplest way of using dynamically named variables would be a dictionary:
$vars = #{} # create empty dictionary
# add key/value pairs to dictionary:
$vars["foo"] = 23
$vars["bar"] = "foobar"
$vars["baz"] = Get-Content C:\sample.txt
Another way would be to declare variables on the fly:
$name = "foo"
$value = "bar"
New-Variable $name $value
echo $foo
Or you could create a custom object and add properties as Kyle C suggested. That approach is similar to a dictionary, although technically different.

You could try adding a NoteProperty to the object.
$varname | Add-Member -type NoteProperty -name TestProperty -value "some test value" -PassThru
Also see this for what types of objects you can add a member to: What objects are suitable for Add-Member?

Related

TCL regsub to variable?

I'm setting up macros, Set, and Say. Defined in procedures.
proc Set {key value args} {
set ::$key $value
set "::key2" "$key"
}
proc Say {key} {
puts $key
}
proc Say2 {key} {
set key3 [regsub "\%" $key "\$"]
puts $key3
eval puts $key3
}
Which allows me to execute the following:
Set "test" "this should display this test text"
Say $key2 ;#should display the key "test" which is what we just set
Say $test ;#presents the value of the key test
Output
% Set "test" "this should display this test text"
test
% Say $key2 ;#should display the key "test" which is what we just set
test
% Say $test ;#presents the value of the key test
this should display this test text
So now lets say I want to reassign the variable $ to %
Set "mouse" "squeak" ;#set key mouse with value string of "squeak"
Say $mouse ;#displays the value as set above correctly
Say2 %mouse ;#start using our own characters to represent variables - switch the % for a $ and then output
However I then get when using eval,
can't read "mouse": no such variable
Output
% Set "mouse" "squeak" ;#set key mouse with value string of "squeak"
mouse
% Say $mouse ;#displays the value as set above correctly
squeak
% Say2 %mouse ;#start using our own characters to represent variables
$mouse
can't read "mouse": no such variable
I'm finding this weird because we set it above, we can recall the value using the standard $ And I can prove that the regsub in Say2 is working as it should replacing % with $.
%mouse becomes $mouse which is a valid variable.
Eval $mouse outputs with no such variable
Am I missing something?
Thanks
The issue is with the proc:
proc Say2 {key} {
set key3 [regsub {%} $key {$}]
puts $key3
eval puts $key3 ;# here
}
$mouse does not exist in this proc. It was not passed as a parameter, nor was it created with set. It exists however in the global namespace. One way to reach for it is to use uplevel in this case:
proc Say2 {key} {
set key3 [regsub {%} $key {$}]
puts $key3
uplevel puts $key3
}
Another option I often use is upvar to bring the variable inside (though in this case, we don't want the $ anymore):
proc Say2 {key} {
set key3 [regsub {%} $key {}]
puts $key3
upvar $key3 var
puts $var
}
PS: I also went ahead and removed some backslashes since they aren't really needed in that scenario.

PowerShell Change Variable in ScriptBlock

I'm trying to change a variable inside a ScriptBlock.
What am I doing wrong?
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load($reader)
$Window.Add_SourceInitialized( {
$timer = new-object System.Windows.Threading.DispatcherTimer
$timer.Interval = [TimeSpan]"0:0:0.25"
$timer.Add_Tick( $updateBlock )
$timer.Start()
} )
$count = 0
$updateBlock = { Write-Host $count; $count++; Write-Host $count}
The Output is a repeating sequence of 0 and 1. So how do I access the variable and not only a copy of it?
When you modify $count inside the scope of the ScriptBlock, a local copy is created, and the original $Count variable in the parent scope is left untouched.
There are a few ways to modify $count in the parent scope, either with an explicit scope qualifier:
$updateBlock = { Write-Host $count; $script:count++; Write-Host $count}
Or by retrieving the variable with Get-Variable and the relative -Scope parameter (-Scope 1 refers to the immediate parent scope):
$updateBlock = { Write-Host $count; (Get-Variable -Scope 1 -Name count).Value++; Write-Host $count}
Or (as pointed out by #PetSerAl), use the [ref] keyword:
$updateBlock = { Write-Host $count; ([ref]$count).Value++; Write-Host $count}

Emulating a class with methods in a module

I am using PowerShell 2.0 (can't upgrade) and I am writing a series of scripts that uses some information from Active Directory. Coming from an OOP languages like C++, I want to emulate a class in PowerShell 2.0, but I know that they only have the class statement in 5.0, and I don't want to use C# to embed classes because I already have a functions (which will be my methods) written in Powershell..
I read this: Powershell. Create a class file to hold Custom Objects?
And I am able to do a function creating a PSObject with "members", but not sure how to make it work with methods so that I can just load the function in my scripts to have a cleaner code.
This is what I have so far:
function New-User {
param($user,
$headers = #("header1","header2","header3","header4") )
$new_user = New-Object -TypeName PSObject
foreach ($header in $headers){
$new_user | Add-Member -membertype NoteProperty -name $header -value $user.$header
}
$new_user | Add-Member -membertype NoteProperty -name "othermember" -value ""
$new_user.PSObject.Typenames.Insert(0,"AD-User")
# Add methods here! for example:
$new_user | Add-Member -membertype METHOD -name "othermember" -value MYDEFINED_FUNCTION($new_user.header1)
return $new_user
}
How I can do this so that I just have this function loaded in my script?
Thanks!
ScriptMethods could fill the gap you are looking for here. Assuming the object has a property for firstname and lastname you could do something like this.
$new_user | Add-Member -membertype ScriptMethod -name samaccountname -value {$this.firstname.substring(0,1) + $this.LastName}
Then with the returned object you can call the scriptmethod samaccountname
$matt = New-Object -TypeName psobject -Property #{
firstname = "matt"
lastname = "bagel"
}
$new = new-user $matt "firstname","lastname"
$new.samaccountname()
Which would return "mbagel". This was tested on 2.0.
So if you wanted to use a function in the method that is just a matter of making sure it is sourced ahead of the time it is called.
function Get-AccoutName{
param(
[string]$firstname,
[string]$lastname
)
$firstname.substring(0,1) + $lastname
}
.....
other code you have
.....
$new_user | Add-Member -membertype ScriptMethod -name samaccountname -value {Get-AccoutName $this.firstname $this.LastName}
If you want these things available all the time then you just need to load them into a PowerShell profile.

Value not storing in powershell variable

I am calling a PS function while passing it a string and a datatable variable. I want to extract all items in the datatable and store them in an object.
Here is my code from my script:
Function myFunc
{
param ($id, $dt)
$data = $dt | where-object ($_.ID -eq $ID)
}
$myVar = myFunc -id "stringID" -dt myDataTable
When this runs my data variable stays empty.
I have a breakpoint placed at the end of my project so I can try and play with the values. When I try and re-create the issue it works:
[DBG]: PS C:\WINDOWS\system32>> $abc = $myDataTable | where-object {$_.ID -eq $ID}
[DBG]: PS C:\WINDOWS\system32>> $abc
ID : //info here
Location : //info here
Managedr : //info here
It just will not work in my actual script.
The function runs in it's own scope, and the scope and all variables created in the scope are disposed when the function exits. Functions should return data, which you assign to variables in the local scope, like this:
Function myFunc
{
param ($id, $dt)
$myDataTable | where-object ($_.ID -eq $ID)
}
$myVar = myFunc -id "stringID" -dt myDataTable

How to pass the parameter in SQL query from PowerShell

I have this code in PowerShell, that executes SQL query to UPDATE my table:
$Connection=new-object data.sqlclient.sqlconnection "server=server;database=mydb;trusted_connection=true;"
$Connection.open()
For ( $i = 0; $i -le $ActID.Length; $i ++ ) {
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.Connection = $Connection
$cmd.CommandText =
"
update Table
set Note = #PATH
"
$cmd.Parameters.Add("#PATH", $ActID[$i].Values) | Out-Null
$cmd.ExecuteNonQuery()
}
I tried to update the table with the variable defined in this string:
$cmd.Parameters.Add("#PATH", $ActID[$i].Values) | Out-Null
But when I execute the script the error log says that there is no value passed in $ActID[$i]
Are there other methods to pass parameters (variables) in powershell queries?
What could be the mistake:
$i -le $ActID.Length;
it should be probably
$i -lt $ActID.Length;
You could also use piping which simplifies the code:
$actId | % { ..... $cmd.Parameters.Add("#PATH", $_.Values) | Out-Null .... }
Besides that the property you use is Values - is it really what you wanted? Values looks like a collection of something. Maybe you wanted to use a single value.