Confused with Powershell script get-content - arrays

Ask user to enter a name, Search name in the names array person.dat file. If the name is found print a table, If the name is not found, print an error message and ask user for another name.
persons.dat.
George Nelson,56,78000.00
Mary Nathaniel,65,66300.00
Rosy Ferreira,32,39000.00
Guessing on this part.
While ($true){
Write-Host $("1. Search by user name")
Write-Host $("2. List all:)
$input = (Read-Host("Enter an option (0 to quit)"))##user will input value
#if 1 is entered (Read-Host("Enter user name"))
#if 2 is entered Print all#
#if 0 is entered quit.#
try{ ? }
catch {
## If input is invalid, restart loop
Write-host " User does not exist"
continue
}
0{
Write-Host $("Thank you. Bye!")
This bottom part will print all 3 in a table.
$data = Get-Content "persons.dat"
$line = $null;
[String[]] $name = #();
[int16[]] $age = #();
[float[]] $salary = #();
foreach ($line in $data)
{ #Split fields into values
$line = $line -split (",")
$name += $line[0];
$age += $line[1];
$salary += $line[2];
}
Write-Host $("{0,-20} {1,7} {2,11}" -f "Name", "Age", "Salary")
Write-Host $("{0,-20} {1,7} {2,11}" -f "-----------", "---", "-----------")
for
($nextItem=0 ; $nextItem -lt $name.length; $nextItem++)
{
$val1n = $name[$nextItem];
$val2n = $age[$nextItem]
$val3n = $salary[$nextItem]
Write-Host $("{0,-20} {1,7} {2,11:n2}" -f $val1n,
$val2n, $val3n)
}

Here is one way you could do it, hopefully the inline comments help you understand the logic. Since the persons.dat file you're showing us is comma-delimited, we can convert it to an object using ConvertFrom-Csv, by doing this, you won't have a need to construct the output to screen like you are doing with those Write-Host statements.
# Convert the file into an object
$persons = Get-Content persons.dat -Raw | ConvertFrom-Csv -Header "Name", "Age", "Salary"
function ShowMenu {
# simple function to clear screen and show menu when called
Clear-Host
'1. Search by user name'
'2. List all'
}
:outer while($true) {
# clear screen and show menu
ShowMenu
while($true) {
# ask user input
$choice = Read-Host 'Enter an option (0 to quit)'
# if input is 0, break the outer loop
if(0 -eq $choice) {
'Goodbye'
break outer
}
# if input is not 1 or 2
if($choice -notmatch '^(1|2)$') {
'Invalid input!'
$null = $host.UI.RawUI.ReadKey()
# restart the inner loop
continue
}
# if we are here user input was correct
break
}
$show = switch($choice) {
1 {
# if choice was 1, ask user for a user name
$user = Read-Host "Enter user name"
# if user name exists in the `$persons` object
if($match = $persons.where{ $_.Name -eq $user }) {
# output this to `$show`
$match
# and exit this switch
continue
}
# if user name was not found
"$user was not found in list."
}
2 {
# if input was 2, output `$persons` to `$show`
$persons
}
}
# show the object to the host
$show | Out-Host
# and wait for the user to press any key
$null = $host.UI.RawUI.ReadKey()
}

Related

Interactive Picklist with JSON object in Powershell

Here is my issue - I have a Powershell script that calls a bunch of information from an API, that comes in as JSON.
As an example (not the actual output, but good enough for my issue):
{
"fruit":[
{
"Type": "Apple",
"ID": 1
},
{
"Type": "Bannana",
"ID": 2
}
]
}
The API that is called has a search variable that is specified by the user, depending on what they specify, the API could return No results, a single result or multiple results.
What I want to do is to present the user with a list of Fruit, based off of the type field and an option: e.g.:
Press 1 for Apples
Press 2 for Bannanas
Press 0 to enter a new search field
If there are more options then obviously Press X for XXXX until all the options are accounted for.
I suspect I will have to do some form of loop through the JSON list to populate a set of fields, - I've never had an interactive section like this in a PS Script.
So - in the end, this was what I did to fix it - thanks to the commentors who pointed me in the right direction:
$variablearray = #()
$i = 1
foreach($_ in $fruitnames){
New-Variable -Name "$i" -Value $_
$variablearray += $i
$i = $i +1
}
$optionsarray = #()
$optionsarray += $Zero
foreach($_ in $variablearray){
$word = Convert-NumbertoWords $_
$tmp2 = (get-variable -name $_).value
$tmp = echo $word[1].trim()
$tmp3 = New-Object System.Management.Automation.Host.ChoiceDescription "$tmp", "$tmp2"
New-Variable -Name $tmp -Value $tmp3
$optionsarray += $tmp3
}
#Combine the options array to an actual options object
$options = [System.Management.Automation.Host.ChoiceDescription[]]($optionsarray)
#prompt the user for the choice
$title = 'Select the Fruit'
$message = 'Hover over each option to check what the description is'
$result = $host.ui.PromptForChoice($title, $message, $options, 0)
}
It loops through all the JSON Elements, creates a set of variables (this is needed for other parts of the script and for ease of use) and then creates an options array and then prompts the user for input.

How to compare an array of numbers with user input?

I have created 3 arrays, which store data from a separate file called household.dat, arr1 holds the ID, arr2 holds the income, and arr3 holds family members. The user is asked to enter an existent id (one that exists in the household file). If the id exists, I have to print the information related to that specific ID. The problem starts when I try to compare the user's input with the already stored id.
This is what I have so far.
$myarr contains the first set of numbers in the first column which is the ID
$myarr1 contains the second set of numbers in the second column, which is the income
$myarr2 contains the third set of numbers in the third column which is the members
10041,12180.00,4
15298,89254.00,3
10562,13240.00,3
13256,19800.00,2
47742,67189.00,4
14830,22458.00,8
19000,17000.00,2
21132,18125.00,7
23541,15623.00,2
82772,56878.00,2
32100,3200.00,6
67733,98113.00,5
36002,6500.00,5
37734,45144.00,4
65410,11970.00,2
47352,8900.00,3
62159,10000.00,2
92803,6200.00,1
"{0,25:n3}" -f "Household Statistics"
write-output "--------------------------------"
write-output "1. Search by Household ID"
write-output "2. List all"
$option = read-host "Enter a option (0 to quit)"
$myarr = #()
$myarr1 = #()
$myarr2 = #()
$id = #()
if($option -eq 1)
{
$id = Read-Host -Prompt "Enter Household ID "
foreach ($line in $file)
{
$line = $line -split (",")
$myarr = $line[0]
$myarr1 = $line[1]
$myarr2 = $line[2]
if ($myarr -contains $id)
{
write-output "--------------------------------"
write-host "Statistics for household" $id
write-output "--------------------------------"
"{0,-11} {1,10} {2,15}" -f "Household ID", "Income",
"Members"
}
elseif ($myarr -notcontains $id)
{
""
write-output "Sorry, entered Household ID not found"
break;
""
}
}
If you're not reading from a file as CSV, but somehow created 3 (same-length) arrays, you can start your code by combining the array values into workable objects like this:
$data = for ($i = 0; $i -lt $myarr.Count; $i++) {
[PsCustomObject]#{
ID = $myarr[$i]
Income = $myarr1[$i]
Members = $myarr2[$i]
}
}
However, reading your question a couple of times over, and looking at the examples you give for the 3 arrays, it seems to me that your file household.dat is in fact a CSV file without headers.
Instead of reading that file with Get-Content and then loop over the lines, manually splitting them on the comma as in your code, you should use Import-Csv, so you will obtain an array of objects where each object has both the 'ID', the 'Income' AND the corresponding 'Members' properties, nicely packed together.
In that case just do:
$data = Import-Csv -Path 'X:\somewhere\household.dat' -Header ID, Income, Members
Then your code would be much simpler like:
# loop over the records in the $data
$id = Read-Host -Prompt "Enter Household ID"
# see if you can find a matching record
$record = $data | Where-Object { $_.ID -eq $id }
if ($record) {
Write-Host "--------------------------------"
Write-Host "Statistics for household $id"
Write-Host "--------------------------------"
"{0,-11} {1,10} {2,15}" -f $record.ID, $record.Income, $record.Members
}
else {
""
Write-Host "Sorry, entered Household ID '$id' not found"
""
}

Can I convert comma-separated string back to AD value objects?

So I'm trying to write a script that will generate an AD report based on parameters chosen by the user, and it's caused me a lot more headache than I expected. Here's an excerpt of what I'm trying to do:
#import the ActiveDirectory Module
Import-Module ActiveDirectory
#report parameter variables
$firstname = {givenname}
$lastname = {surname}
$displayname = {DisplayName}
$logonname = {sAMAccountName}
#set array initially to number of possible parameters
$inputarray = (0..3)
#display menu
cls
Write-Host "Please select the parameters you would like in your report:"
Write-Host "Enter q when finished"
Write-Host `n
Write-Host " 1) First Name"
Write-Host " 2) Last Name"
Write-Host " 3) Display Name"
Write-Host " 4) Logon Name"
Write-Host `n
#read in selections from user while input isn't Q, and not bigger than array
#bounds
for ($i=0; (($i -le 3) -and ($inputarray[$i] -ne 'q')); $i++){
$selection = ($i + 1)
$inputarray[$i] = Read-host "Enter report parameter $selection"
#exit loop for quit selection
if ($inputarray[$i] -eq 'q'){
break
}
switch ($inputarray[$i])
{
"1" { $result = $firstname }
"2" { $result = $lastname }
"3" { $result = $displayname }
"4" { $result = $logonname }
}
$inputarray[$i] = $result
}
$arraylen = $i
$test = ''
for ($x=0; $x -lt $arraylen; $x++){
if($x -lt ($arraylen -1)){
$test = ($test + $inputarray[$x] + ',')
}
else{
$test = ($test + $inputarray[$x])
}
}
Get-ADUser -searchbase "my targeted OU" -Properties * -Filter * |
Select-Object $test |
Export-Csv -Path "export path here.csv" -NoTypeInformation
I thought creating a string from the array with comma separated values would work the same as typing them in (like Select-Object givenname,surname,lastlogin) but that clearly isn't working. Any ideas how to change it back from a string value to individual objects, so maybe it will accept it?
1st problem: Statements such as $firstname = {givenname} assign a script block ({...}) to the variable, which is not your intent; instead, you're looking to assign property names as strings, e.g., $firstname = 'givenname'.
2nd problem: You're building variable $test as a string, whereas what you need to pass to Select-Object is an array of strings (property names), so you can just use $inputArray directly.

How to show only Read-Host value from a text file array?

I have a text file array JobTitle.txt which looks like this:
Sales Co-Worker, TSALES, TSALSK
Business Navigator, BNOM, BNOMD
And I wanted to write a code that would read the user's input and present the second and the third value from the same line. Here's what I wrote:
$jobtitledb = Get-Content C:\Users\Username\Desktop\Scripts\JobTitle.txt
$jobtitleinput = Read-Host 'Input the job title'
foreach ($data in $jobtitledb) {
$jobtitleinput, $basic, $extended = $data -split ','
Write-Host "Basic template is: "$basic
Write-Host "Extended template is: "$extended
}
I can't seem to figure out how to make it return desired line only. For clarification, when I input Sales Co-Worker I want the program to return:
Basic template is: TSALES
Extended template is: TSALSK
You just need an if statement that checks to make sure your input was the same as the jobtitle its reading in on each line.
$jobtitledb = Get-Content C:\Users\Username\Desktop\Scripts\JobTitle.txt
$jobtitleinput = Read-Host 'Input the job title'
foreach($data in $jobtitledb) {
$jobtitle, $basic, $extended = $data -split ','
If ($jobtitle -eq $jobtitleinput) {
Write-host "Basic template is: "$basic
Write-host "Extended template is: "$extended
}
}
Also I think when you were reading each line you were assigning the jobtitle to the same variable as the user input, so you should change that as well. Above code should work.
Here's an annotated script that should fix your problem. It's mostly the same as the original except where I changed it to store the job tile from the record in $jobtitle instead of $jobtitleinput and added an if statement. Also added a $jobnotfound variable and code to print the appropriate message
$jobtitledb = Get-Content C:\Users\Username\Desktop\Scripts\JobTitle.txt
$jobtitleinput = Read-Host 'Input the job title'
$jobnotfound = $ftrue
foreach($data in $jobtitledb)
{
# Store the job title from the record in $jobtitle instead of
# overwriting $inputjobtitle
$jobtitle, $basic, $extended = $data -split ','
# check the $jobtitle from record against the $jobtitleinput
if ($jobtitle -match $jobinputtitle)
{
Write-host "Basic template is: "$basic
Write-host "Extended template is: "$extended
$jobnotfound = $false
break
}
}
if ($jobnotfound)
{
Write-Host "No job matching '$jobinputtitle' was found."
}
I added an "else" statement, else { Write-Host 'Given job title does
not exist' } But it runs once for each line. How to make it return
only 1 line of "Given job title does not exist"?
I can't post comments yet, however you should just be able to use break within your else statement to exit the foreach loop.
---------- Edit ----------
The following should provide the desired output.
$jobtitledb = Get-Content C:\Users\Username\Desktop\Scripts\JobTitle.txt
$jobtitleinput = Read-Host 'Input the job title'
$found = $false
foreach($data in $jobtitledb)
{
$jobtitle, $basic, $extended = $data -split ','
If ($jobtitle -eq $jobtitleinput) {
Write-host "Basic template is: "$basic
Write-host "Extended template is: "$extended
$found = $true
break
}
}
if(!$found)
{
Write-Host "Given job title does not exist"
}

Powershell Array

I’m trying to get multiple users first and last name to be converted into a format: first initial+ last name while using a GUI input box. My code is wrong and it keeps the first array letter and won’t remove it to allow the other inputs to do the same task. I tried the Remove to help remove the fixed size array. Didn’t work. I read that I must create another array to remove from the first array. This is where I’m stuck. How do I make the second array delete the first entry while keeping the same variables if possible - I want to enter X number of names into the input box and run other other task for each user.
right now the results are the following:
jblank
jeric
jbob
Im trying to get
jblank,enewnew,bmo
help please. thank you
Add-Type –assemblyName Microsoft.VisualBasic
Add-Type –assemblyName System.Windows.Forms
$User = "joe blank, eric newnew, bob mo" #
[Microsoft.VisualBasic.Interaction]::InputBox("Enter Employee name or
names.`nSeparate with a comma (,) or semi-colon (;).`n ** Do not add
quotation marks **", "Search book")
If (-Not [System.String]::IsNullOrEmpty($User)) {
[string[]]$Username = $User -split ",|;"
ForEach ($User in $Username) {
#Write-host $User -ForegroundColor Yellow
$Fname = $User.Split(" ")[0].trim()
$Lname = $User.Split(" ")[1].trim()
#initials
$In = $FName
$InRM = $In.Remove(1)
$unID = $InRM+$LName # intials done
$newID = #()
foreach ($u in $User)
{
if ($User -ne 0)
{
Write-Host "Remove [0] here or something like that eq to $unID again"
}
}
Write-Host $unID -foregroundcolor "green"
## Do more stuff here for each user ##
Do you think at something like that?
$User = "joe blank, eric newnew, bob mo"
#define arry for later
$SortUser = #()
#split users from textbox
$Users = #($User.Split(","))
#loop users
foreach($i in $Users){
if($i.Substring(0,1) -eq " "){
#remove space which make problems
$i = $i.Remove(0,1)
}
$Split = $i.Split(" ")
$First = $Split[0]
$Last = $Split[1]
$FirstLetter = $First.Remove(1,$First.Length - 1)
#Add all informations to object
$obj = New-Object PSCustomObject
$obj | Add-Member -type NoteProperty -name First -Value $First
$obj | Add-Member -type NoteProperty -name Last -Value $Last
$obj | Add-Member -type NoteProperty -name Username -Value "$FirstLetter.$Last"
#fill all objects in one array
$SortUser += $obj
}
$SortUser
Result:
First Last Username
----- ---- --------
joe blank j.blank
eric newnew e.newnew
bob mo b.mo

Resources