Powershell envrionment variable inheritance - powershell

guys..i'm not familiar with PS and at beginning it was a simple question,but it's not so simple for me. (Sorry)
I need to take one environment variable as a string to another env. variable
something like this sketch "$env:$env:var"
I've tried (of course not working,but helps to understand):
$env:admin1 = "123456"
$env:user = "admin1"
$password = $env:"${env:user}"
Write-Host $password
Is it possible in powershell?
Thank you!

It's not possible the way you're doing it, but you can query the environment and match the variable name from a variable a number of different ways. Here's one:
$appData = 'APPDATA'
$value = (Get-ChildItem Env: | ? { $_.Name -eq $appData }).Value
$value # Output

Related

Powershell setting variables in foreach-object by getting contents of a batchfile

Good day,
Could someone help me with setting some variables after filtering some records from a batchfile in powershell please?
My Batch file (config.bat) looks like this :
---------
set FILENAME=OIMSX4455
set USR=AJ34
set DOCTYPE=WORD
set YEAR=2019
---------
My Powershell code resembles the below although I'm unsure how to set the variables ie (getting the values "WORD" and "AJ34" into $doc and $user
$vars = "c:\temp\config.bat"
get-content $vars | select-string -pattern ("set DOCTYPE=","set USR=")
foreach-object {
$doc=<should equal WORD>
$user=<should equal AJ34>
}
As my config file changes and has several values, I'm only interested in the values what comes after = sign for set DOCTYPE= & set USR= i.e WORD and AJ34 in this example
On another day the config values will change which is why i need to read them again into my powershell variables. Apologies in advance for any mistakes etc
Thanks
The easiest way I think is by using regex on a line-by-line comparison with switch:
$user, $doc = $null
switch -Regex -File 'c:\temp\config.bat' {
'^set USR\s*=\s*(.*)' { $user = $matches[1] }
'^set DOCTYPE\s*=\s*(.*)' { $doc = $matches[1] }
}
Write-Host "user: $user`tdoc: $doc"
Result:
user: AJ34 doc: WORD

powershell hashtable dynamic key

I would like to ask you about dynamic nested keys in hashtables (powershell).
I 've already done some research and I can't find an answer.
# I got this hash structure, works fine
$Hashtable = #{}
$Hashtable.Maincategory = #{}
$Hashtable.Maincategory.Subcategory = #{}
$Hashtable.Maincategory.Subcategory.MyProperty = #{ 'property' = 'value'}
$Hashtable.Maincategory.Subcategory.MyProperty
Name Value
---- -----
property value
# I want dynamic path to my property
$MainAndSubCategory = [string]'Maincategory.Subcategory'
$Hashtable.$MainAndSubCategory.MyProperty # doesn't work
$Hashtable."$MainAndSubCategory".MyProperty # doesn't work
$Hashtable."$($MainAndSubCategory)".MyProperty # doesn't work
$Hashtable."$(Get-Variable -Name 'MainAndSubCategory' -ValueOnly)".MyProperty # doesn't work
I would appreciate advice, thanks in advance.
It is possible to build a string, then execute it using Invoke-Expression. Note that the initial $ character is escaped.
$Hashtable = #{}
$Hashtable.Maincategory = #{}
$Hashtable.Maincategory.Subcategory = #{}
$Hashtable.Maincategory.Subcategory.MyProperty = #{ 'property' = 'value'}
$Hashtable.Maincategory.Subcategory.MyProperty
$MainAndSubCategory = 'Maincategory.Subcategory'
Invoke-Expression -Command "`$Hashtable.$MainAndSubCategory.MyProperty"
One thing to be careful about is that anything that could set the value of the string would be able to inject unwanted code.
this will work, but I'm not sure, if this is a solution, you are looking for
$Hashtable.$(($MainAndSubcategory -split '\.')[0]).$(($MainAndSubcategory -split '\.')[1]).myproperty
It is the same as put maincategory and subcategory keys into the separate variables

Best practice to use string data from a file

What is the best practice to create a text-based database for a PowerShell script?
What I really mean exactly?
I have a PowerShell script which use an url. This address may be used in other PS scripts, but I would be pretty happy if a quite simple practice is exists to solve to store this URL (or more) in a file, and the scripts use form this content, what I only have to define, which variable, line should be used, like this:
SharePointUrl = "..."
CcUrl = "..."
And in the script:
$SPUrl = DataFile.SharePointUrl ...
Something like this.
Not sure if I understand your question correctly. Are you looking for something like this?
$SharePointUrl = 'http://www.example.org/...'
New-Object -Type PSObject -Property #{'URL'=$SharePointUrl} |
Export-Csv 'C:\path\to\some.csv' -NoType
$DataFile = Import-Csv 'C:\path\to\some.csv'
$SPUrl = $DataFile.URL
Edit: After re-reading your question it seems you have an input file with key=value pairs. That can be processed like this:
$DataFile = Get-Content 'C:\path\to\data.txt' -Raw | ConvertFrom-StringData
$SPUrl = $DataFile.SharePointUrl
Another option is to write the configuration to a second PowerShell script:
# as variables
$SharePointUrl = "..."
$CcUrl = "..."
# or as a hashtable
$DataFile = #{
SharePointUrl = "..."
CcUrl = "..."
}
and dot-source that script in your original script.
. 'C:\path\to\config.ps1'

Powershell to read some strings from each line

I have a requirement like:
Have a text file containing the following in the following pattern
172.26.xxy.zxy:Administrator:Password
172.26.xxy.yyx:Administrator:Password
172.26.xxy.yyy:Administrator:Password
172.26.xxy.yxy:Administrator:Password
I need my powershell script to read each word and use that word whereever required. For example,
foreach(something)
{
I want the IP's(172.26.---.---) to read and store the value as a variable.
I want to store the two words after **:** in seperate variables.
}
How can this be done? I know to read an entire file or get some specific string. But I need the same to be done on each line.Any help would be really appreciated.
Something like this? You can just split on the : and then store your variables based on the index
$contents = Get-Content C:\your\file.txt
foreach($line in $contents) {
$s = $line -split ':'
$ip = $s[0]
$user = $s[1]
$pass = $s[2]
write-host $ip $user $pass
}
minor edit: "t" missing in content.
You can write a regular expression to replace to remove the parts you do not need
$ip_address= '172.26.xxy.zxy:Administrator:Password' -replace '^(.+):(.+):(.+)$','$1'
$user= '172.26.xxy.zxy:Administrator:Password' -replace '^(.+):(.+):(.+)$','$2'
$pwd= '172.26.xxy.zxy:Administrator:Password' -replace '^(.+):(.+):(.+)$','$3'
I think the more generic and pure Powershell way would be something like this:
Select-String "(.*):(.*):(.*)" c:\file.txt |
Select #{Name="IP"; Expression = {$_.Matches.Groups[1]}},
#{Name="User"; Expression = {$_.Matches.Groups[2]}},
#{Name="Password"; Expression = {$_.Matches.Groups[3]}}
The Output would be then an array of objects each having three properties IP, User and Password. So you can now use them for your purposes, or just add more commands at the end of the pipe.

Powershell: Force variable expansion

How can I force string variable expansion?
I need to read a string with one or more variable names in it (a template) and then expand it after I read the file. The key is that I must read the contents of the file before I declare the variables that will be used in the expansion. I've tried several ways but I can't get it to work.
It's not an option to read the file after $environment is defined.
Contents of name.txt:
$environment-RPT-INT
#example 1
$name = gc "c:\temp\name.txt"
$environment = "9065DEV"
$expanded = $ExecutionContext.InvokeCommand.ExpandString($name)
$expanded
#example 2
$name = gc "c:\temp\name.txt"
$environment = "9065DEV"
$expanded = $expanded = Invoke-Expression "`"$template`""
$expanded
#example 3
$name = gc "c:\temp\name.txt"
$environment = "9065DEV"
$name = $name.Clone()
$expanded = $ExecutionContext.InvokeCommand.ExpandString($name)
$expanded
Any help is appreciated.
Updated: Example 1 is now working for me.
It looks like you've found some possible solutions, but I'll suggest another that is in my opinion a bit smarter and more robust.
Instead of requiring variable names in your text file, why not use format specifiers. For example, the contents of name.txt:
{0}-RPT-INT
And in your script:
$name = gc "c:\temp\name.txt"
$environment = "9065DEV"
$expanded = $name -f $environment
$expanded
This way, you can rename the variable w/o changing any of your text files. As a bonus, if your text file comes from unknown sources, your script is vulnerable to code injection. For example, say you are given a text file with these contents:
$(rm -whatif -recurse -force c:\)-RPT-INT
Then ExpandString or Invoke-Expression will happily execute that code.
Your Invoke-Expression example is pretty close. Instead of using $template though, you need to use $name.
#example 2
$name = gc 'c:\temp\name.txt';
$environment = '9065DEV';
$expanded = Invoke-Expression -Command "`"$name`"";
$expanded;
If you are willing to store your Setting/Values in a CSV, I wrote a module to pull values from a CSV, put it into a HereString... any variables you put into the CSV become fully expanded inside the Here-String. That way, you can normally address the field names and values.
I might be able to change this to also work with traditional INI's if anyone is interested.
https://github.com/Inventologist?tab=repositories
Look for: HereStringFromCSV
There is a function called ExpandString predefined in powershell. It's inside $ExecutionContext, as follows.
$mystring = #'
This is a here string with some embedded variables.
Here is variable foo -- $foo
Here is variable bar -- $bar
Here is variable bletch -- $bletch
'#
#This displays the here string as is.
$mystring
#now define foo, bar and bletch
$foo = 5
$bar = Get-Date
$bletch = "George Washington"
#now run the here string through Expandstring.
$ExecutionContext.InvokeCommand.ExpandString($mystring)