Concatenate CSV results into a single variable with PowerShell - powershell

I'm trying to deploy our company URLs in Google Chrome as "Managed Bookmarks" using PowerShell. In order to accomplish the same thing using IE favorites I created a CSV file with 2 columns containing a Name and URL respectively. I import that CSV then I have a foreach statement that will go through each line and create a .url file in the user's favorites. To minimize effort for my staff I want to use this same CSV file for the Chrome Bookmarks so we only have one file to maintain. Then it wouldn't be necessary for us to modify and redeploy the script, and we could publish the CSV file on a network share to be updated as needed.
Chrome has a registry value that allows me to do what I need. Using 3 search engines as an example, I know how to "hard code" this and make it work.
$PolicyPath = 'Registry::HKEY_LOCAL_MACHINE\Software\Policies'
$GoogleKey = 'Google'
$ChromeKey = 'Chrome'
$ManagedBookmarks = '[ { "name": "Bing", "url": "http://www.bing.com" }, { "name": "Google", "url": "http://www.google.com" },{ "name": "Yahoo", "url": "http://www.yahoo.com" } ]'
Set-ItemProperty -Path "$($PolicyPath)\$($GoogleKey)\$($ChromeKey)" -Name 'ManagedBookmarks' -Value "$ManagedBookmarks" -Type String
Is there a way to do a foreach and concatenate the results into a single variable? That will result in the following format:
$ManagedBookmarks = "[ { "name:" "$($line.name)", "url": "$($line.url)"}, { "name:" "$($line+n.name)", "url": "$($line+n.url)"} ]"

If you have a CSV (call it csv.csv) file like the following, you can just import the CSV to create an object array and then convert the whole thing to a JSON object.
Name,URL
Bing,http://www.bing.com
Google,http://www.google.com
Yahoo,http://www.yahoo.com
$ManagedBookmarks = Import-Csv csv.csv | ConvertTo-Json
Per LotPings Recommendation, if you dislike the line feeds and/or carriage returns and extra spacing in that output, you can use the -Compress switch.
$ManagedBookmarks = Import-Csv csv.csv | ConvertTo-Json -Compress

Related

Use Powershell to find and compare text in file to a folder name

My apologies, but unfortunately my Powershell scripting is quite poor, however I'm trying to muddle on with this... The below is actually for a Nagios check, hence the defining the OK, WARNING etc
Summary
I have 2 small text files with specific text within that I need to check for a folder existing with the corresponding name.
In File 1 below, note the section that states "prod" on line 18, against this I am interested in the apples, pears and bananas data (that which is a date format, plus other text) within the speech marks, so for bananas it would be 20220817-1-64 only.
The position within the text file of the "prod" line and subsequent data I'm
interested in can't be guaranteed.
The data against apples, pears etc will change over time
file1.txt:
{
"default": "prod",
"pre": {
"apples": "20220711-0",
"pears": "20220711-0",
"bananas": "20220711-1-64"
},
"test": {
"apples": "20220920-0",
"pears": "20220920-0",
"bananas": "20220920-1-64"
},
"new": {
"apples": "20220910-0",
"pears": "20220910-0",
"bananas": "20220910-1-64"
},
"prod": {
"apples": "20220817-0",
"pears": "20220210-0",
"bananas": "20220817-1-64"
},
"old": {
"apples": "20220601-0",
"pears": "20220601-0",
"bananas": "20220601-1-64"
}
}
File 2 has a similar principal, I am only interested in 20220923-0 next to the "prod" line (again, position within the file can't be guaranteed and the data will change over time)
File2.txt:
{
"default": "prod",
"pre": "20220917-0",
"test": "20220926-0",
"new": "20220924-0",
"prod": "20220923-0"
}
Each of the values would need to be compared against a directory, to see if a folder of the same name exists. If it matches, the result would be OK, if different then result in a WARNING, if missing the result would be CRITICAL.
What I have tried
Defining the result and folder to check against is straight forward enough:
# Result
$OK=0
$WARNING=1
$CRITICAL=2
# Folders to check
$apples_folder = (Get-Childitem c:\folder_path\apples\*).Name
$pears_folder = (Get-Childitem c:\folder_path\pears\*).Name
However the main part I'm struggling with is picking out the relevant text from the text file(s) against the prod line(s)
From what I have gathered, I suspect using regex or possibly grep commands may hold the answer, but I can't quite get my head around it.
Any pointers in the right direction would be appreciated.
Continuing from my comment, you can parse File1.txt as JSON, assuming that what you gave us as example is missing the final closing bracket '}' as a result of posting it here and that the json in the actual file is complete.
To work with that file type, you can do
$json = Get-Content -Path 'X:\somewhere\File1.txt' -Raw | ConvertFrom-Json
$prodFolder = $json.prod.bananas
# next test if you can find a folder with that name and do whatever you need to do then
if (Test-Path -Path "c:\folder_path\prod\$prodFolder" -PathType Container) {
"OK"
}
else {
"CRITICAL"
}
For File2.txt, things are quite different because that is a strange format..
What you can do is convert the data in there into a Hashtable using the ConvertFrom-StringData cmdlet.
In PowerShell 5.x you need to replace the colons that separate the names from their values into an equal sign (=)
$data = (Get-Content -Path 'X:\somewhereElse\File2.txt' -Raw) -replace '^(.*?):(.*)','$1=$2' -replace '[", ]' | ConvertFrom-StringData
$prodFolder = $data.prod
# next test if you can find a folder with that name and do whatever you need to do then
if (Test-Path -Path "c:\folder_path\prod\$prodFolder" -PathType Container) {
"OK"
}
else {
"CRITICAL"
}
In PowerShell 7.x you do not have to replace the colons:
$data = (Get-Content -Path 'X:\somewhereElse\File2.txt' -Raw) -replace '[", ]' | ConvertFrom-StringData -Delimiter ':'

Powershell get-content command

I am trying to return only key from the text file having below content
{
"expires": "2018-02-24T19:40:35.000Z",
"id": "xtysdasdagsweasdasvfdsgsdfcxaxasdasrgdascasdasdasxacasdgshgsfdfgasdasdsaedasdasdasfeasdfasdasdasd==",
"testvalue1": "test_tenant"
}
above mentioned "id" is token which keep getting change everyday.
my final out put should only content id value without "" something like below.
xtysdasdagsweasdasvfdsgsdfcxaxasdasrgdascasdasdasxacasdgshgsfdfgasdasdsaedasdasdasfeasdfasdasdasd==
I have tried with '''get-content -path c:..\filname.txt | select-string "id"''' but it does not return only key as mentioned above.
it returns full line
"id": "xtysdasdagsweasdasvfdsgsdfcxaxasdasrgdascasdasdasxacasdgshgsfdfgasdasdsaedasdasdasfeasdfasdasdasd==",
How to select only specific output I am referring?
Get-Content reads the file off disk, but you need to convert the resulting JSON string to an object you can interact with to get the id value:
# Read from disk and convert from JSON
$data = Get-Content -Path C:\path\to\filname.txt |ConvertFrom-Json
# Now we can dereference the `id` property value alone
$data.id

Using a wildcard to replace CSV cell contents with PowerShell

I'm trying to get PowerShell to manipulate some CSV data.
The column I’m trying to manipulate in my CSV contains stock levels as text, containing mostly "High", "Good", "Medium", "Low" and "Out Of Stock" which I want to convert to a numerical format before importing the CSV to the website at the end of the day.
My code currently is:
#Declare Stock Level Words To Value
$StockLevelWordToValue = #{
"High" = "70"
"Good" = "50"
"Medium" = "30"
"Low" = "10"
"Out Of Stock" = "0"
}
# import the CSV file
$csv = Import-Csv "C:\temp\temp.csv";
# for each row, replace the Stock Level Word field with a value
foreach($row in $csv) {
$row."Stock Level" = $StockLevelWordToValue[$row."Stock Level"];
}
# export the modified CSV
$csv | Export-Csv "C:\temp\temp2.csv" -NoTypeInformation;
The problem I have is in my "Stock Level" column, some of the entries are like "Good: Last update August 2019" or “High: Last update March 2019”
Currently, when running this code, there is no value returned for these entries and the cell is blank.
I was hoping a wildcard would work like:
"Good*" = "50"
But that returns a blank cell too.
How can check a cell "contains" a word and returns a numerical value, no matter what other words are in that cell?
You can use Select-String to check the value of your attribute by patterns like "High*". This will return null if doesn't find any, true if there is a string matching this pattern.
foreach($row in $csv) {
If ($row."Stock Level" | Select-String "High*) {
$row."Stock Level" = $StockLevelWordToValue["High"];
}
}

Use a for loop for list and set element to environment variable then get value

I'm not familiar with powershell at all and only need it for a few commands. I was hoping that someone could assist me. I have a json file named optionsConfig.json that reads like so,
{
"test1": ["options_size", "options_connection", "options_object"],
"test2":["options_customArgs", "options_noUDP", "options_noName"]
}
In my powershell file, I have one line so far and this is to get the content of the json file.
$rawData = Get-Content -Raw -Path "optionsConfig.json" | ConvertFrom-Json
I had planned on having an environment variable on my system named test that would have the value of test1 or test2 and from that, I would look at the elements of the list in the associated value in the json file. With these elements from the list, I would assume that they are also environment variables and I would want to get their values. ( a list comprehension in python would be perfect here).I'm a python guy so I am not quite certain how to show this in powershell but say I did env = getEnvironmentVariable(test) and that equals test1. I would then say something like for i in $rawData.env
return getEnvironmentVariable(i)
I pretty much want another list or new json object with the values for the assumed environment variables that we get from the original json object.
Is there a way that I can do this in powershell? It would help a lot if anyone could assist. I apologize if I wasn't clear with anything. Thanks
(edit) I see that $rawData.Get-ChildItem Env:test does not work. Is there someone to write something like this in order to get the correct list from json file?
Also setting a new variable like so $var1 = Get-ChildItem Env.tool and doing $rawData.$test.value has no effect either.
# Sample values: make environment variable 'test' ($env:test)
# point to property 'test1'
$env:test = 'test1'
# Provide sample values for the environment-variable names listed
# in the 'test1' property.
$env:options_size = 'size1'
$env:options_connection = 'conn1'
$env:options_object = 'obj1'
# Read the JSON file into a custom object.
$configObj = Get-Content -Raw optionsConfig.json | ConvertFrom-Json
# Retrieve the environment variables whose
# names are listed in the $env:test property ('test1' in this example),
# as name-value pairs.
Get-Item -Path env:* -Include $configObj.$env:test
The above yields an array of [System.Collections.DictionaryEntry] instances each representing an environment variable's name and value:
Name Value
---- -----
options_connection conn1
options_object obj1
options_size size1
To convert the above to JSON:
Get-Item -Path env:* -Include $configObj.$env:test |
Select-Object Name, Value | ConvertTo-Json
Note: The seemingly redundant Select-Object call is necessary to strip additional properties that PowerShell adds behind the scenes, which would otherwise show in the resulting JSON.
If you wanted to rename the properties in the resulting JSON, you'd need Select-Object anyway, using calculated properties.
This yields:
[
{
"Name": "options_connection",
"Value": "conn1"
},
{
"Name": "options_object",
"Value": "obj1"
},
{
"Name": "options_size",
"Value": "size1"
}
]
I don't see a problem, just set and use $ENV:test
$rawdata = Get-Content .\optionsconfig.json | convertfrom-json
$Env:Test="test1"
$rawdata.$ENV:Test
$Env:Test="test2"
$rawdata.$ENV:Test
Sample output
options_size
options_connection
options_object
options_customArgs
options_noUDP
options_noName

CSV input, powershell pulling $null value rows from targeted column

I am trying to create a script to create Teams in Microsoft Teams from data in a CSV file.
The CSV file has the following columns: Team_name, Team_owner, Team_Description, Team_class
The script should grab Team_name row value and use that value to create a variable. Use that variable to query if it exists in Teams and if not, create it using the data in the other columns.
The problem I am having is my foreach loop seems to be collecting rows without values. I simplified the testing by first trying to identify the values and monitoring the output.
Here is the test script
$Team_infocsv = Import-csv -path $path Teams_info.csv
# $Team_infocsv | Foreach-object{
foreach($line in $Team_infocsv){
$owner = $line.Team_owner
Write-Host "Team Owner: $owner"
$teamname = $line.Team_name
Write-Host "Team Name: $teamname"
$team_descr = $line.Team_Description
Write-Host "Team Description: $team_descr"
$teamclass = $line.Team_class
Write-Host "Team Class: $teamclass"
}
I only have two rows of data but yet returned are the two lines as requested with extra output (from rows) without values.
There's no problem with your code per se, except:
Teams_info.csv is specified in addition to $path after Import-Csv -Path, which I presume is a typo, however.
$path could conceivably - and accidentally - be an array of file paths, and if the additional file(s) has entirely different columns, you'd get empty values for the first file's columns.
If not, the issue must be with the contents of Teams_info.csv, so I suggest you examine that; piping to Format-Custom as shown below will also you help you detect the case where $path is unexpectedly an array of file paths:
Here's a working example of a CSV file resembling your input - created ad hoc - that you can compare to your input file.
# Create sample file.
#'
"Team_name","Team_owner","Team_Description","Team_class"
"Team_nameVal1","Team_ownerVal1","Team_DescriptionVal1","Team_classVal1"
"Team_nameVal2","Team_ownerVal2","Team_DescriptionVal2","Team_classVal2"
'# > test.csv
# Import the file and examine the objects that get created.
# Note the use of Format-Custom.
Import-Csv test.csv test.csv | Format-Custom
The above yields:
class PSCustomObject
{
Team_name = Team_nameVal1
Team_owner = Team_ownerVal1
Team_Description = Team_DescriptionVal1
Team_class = Team_classVal1
}
class PSCustomObject
{
Team_name = Team_nameVal2
Team_owner = Team_ownerVal2
Team_Description = Team_DescriptionVal2
Team_class = Team_classVal2
}
Format-Custom produces a custom view (a non-table and non-list view) as defined by the type of the instances being output; in the case of the [pscustomobject] instances that Import-Csv outputs you get the above view, which is a convenient way of getting at least a quick sense of the objects' content (you may still have to dig deeper to distinguish empty strings from $nulls, ...).