Value not storing in powershell variable - variables

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

Related

Extract values into variables from filename in Powershell

I have a Powershell script to read .sql files from a specific folder and run them against a database depending on the name of the filename.
The filenames are always the same: myDatabase.script.SomeRandomCharacters.csv
There can be many files which is why the script has a foreach loop.
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][ValidateSet('dev')][String]$serverName,
[parameter(Mandatory = $true)][String]$databaseName,
)
$dir = Split-Path $MyInvocation.MyCommand.Path
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" } | Where-Object { $_.Name -like "$databaseName*" }
foreach ($s in $scripts) {
$script = $s.FullName
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -InputFile $script
}
The issue here is that if I would have 2 databases "myDatabase" and "myDatabase2", running the script with the former input would run the latter as well since the Where-Object filtering uses an asterisk.
I can't figure out how to modify the script so that I get the absolute value of whatever is before the first fullstop in the filename. What I would also what to do is to validate the value between the first and second fullstops, in the example filename it is script.
Any help is appreciated!
Use the database names to construct a regex pattern that will match either:
param(
[Parameter(Mandatory = $true)][ValidateSet('dev')][String]$ServerName,
[Parameter(Mandatory = $true)][String[]]$DatabaseNames,
)
# Construct alternation pattern like `db1|db2|db3`
$dbNamesEscaped = #($DatabaseNames |ForEach-Object {
[regex]::Escape($_)
}) -join '|'
# Construct pattern with `^` (start-of-string anchor)
$dbNamePattern = '^{0}' -f $dbNamesEscaped
# Fetch scripts associated with either of the database names
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" -and $_.Name -match $dbNamePattern }
# ...
You can use the StartsWith function to fix your filter:
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" } | Where-Object { $_.Name.StartsWith("$($databaseName).") }

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}

Dynamic variable and value assignment in powershell

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?

Powershell variable not passed into filter

I need to create scirpt which add users from list (containing user Display name) to group
Problem I encountered is :
when I issue command :
PS C:\Users\pskwarek> foreach ($a in $csv) {(get-aduser -f "DisplayName -like 'Piotr Skwarek'").samaccountname}
pskwarek
pskwarek
but if I use $a variable it doesnt work :
PS C:\Users\pskwarek> foreach ($a in $csv) {(get-aduser -f "DisplayName -like '$a.name'").samaccountname}
next step I would like to pass it to :
Add-adgroupMember -identity "groupname" -member samaccountname
but I can't make that single step
edit
PS C:\Users\pskwarek> $csv
Name
----
Piotr Skwarek
Renata Skwarek
You need to put $a.name in a subexpression:
foreach ($a in $csv)
{
$user = Get-ADUser -Filter "DisplayName -like '$($a.name)'"
Add-ADGroupMember groupname -Members $user
}
foreach ($a in $csv)
{
$sb = [scriptblock]::create("DisplayName -like '*$a*'")
(get-aduser -f $sb).SamAccountName
}
Try this:
foreach ($a in $csv) {(get-aduser -f ("DisplayName -like '{0}'" -f $a.name)).samaccountname}
You cannot use members of a variable directly in a string as you did.
Using string formatting (the '-f' syntax I proposed) always works.
Another solution would be to use a temporary variable to store $a.name
Try this:
$csv | % { Add-ADGroupMember -Identity "Groupname" -Member $_.Name }

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.