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

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"
}

Related

Confused with Powershell script get-content

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()
}

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.

Powershell Looping through eventlog

I am trying to gather data from eventlogs of logons, disconnect, logoff etc... this data will be stored in a csv format.
This is the script i am working which got from Microsoft Technet and i have modified to meet my requirement. Script is working as it should be but there is looping going on which i can't figure out how it should be stopped.
$ServersToQuery = Get-Content "C:\Users\metho.HOME\Desktop\computernames.txt"
$cred = "home\Administrator"
$StartTime = "September 19, 2018"
#$Yesterday = (Get-Date) - (New-TimeSpan -Days 1)
foreach ($Server in $ServersToQuery) {
$LogFilter = #{
LogName = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'
ID = 21, 23, 24, 25
StartTime = (Get-Date).AddDays(-1)
}
$AllEntries = Get-WinEvent -FilterHashtable $LogFilter -ComputerName $Server -Credential $cred
$AllEntries | Foreach {
$entry = [xml]$_.ToXml()
$Output += New-Object PSObject -Property #{
TimeCreated = $_.TimeCreated
User = $entry.Event.UserData.EventXML.User
IPAddress = $entry.Event.UserData.EventXML.Address
EventID = $entry.Event.System.EventID
ServerName = $Server
}
}
}
$FilteredOutput += $Output | Select TimeCreated, User, ServerName, IPAddress, #{Name='Action';Expression={
if ($_.EventID -eq '21'){"logon"}
if ($_.EventID -eq '22'){"Shell start"}
if ($_.EventID -eq '23'){"logoff"}
if ($_.EventID -eq '24'){"disconnected"}
if ($_.EventID -eq '25'){"reconnection"}
}
}
$Date = (Get-Date -Format s) -replace ":", "-"
$FilePath = "$env:USERPROFILE\Desktop\$Date`_RDP_Report.csv"
$FilteredOutput | Sort TimeCreated | Export-Csv $FilePath -NoTypeInformation
Write-host "Writing File: $FilePath" -ForegroundColor Cyan
Write-host "Done!" -ForegroundColor Cyan
#End
First time when i run the script, it runs fine and i get the csv output as it should be. When i run the script again than a new CSV is created (as it should be) but the same event log enteries are created twice and run it again than three enteries are created for the same event. This is very strange as a new csv is created each time and i dont not have -append switch for export-csv configured.
$FilteredOutput = #()
$Output = #()
I did try adding these two lines in above script as i read somewhere that it is needed if i am mixing multiple variables into a array (i do not understand this so applogies if i get this wrong).
Can someone please help me this, more importantly, I need to understand this as it is good to know for my future projects.
Thanks agian.
mEtho
It sounds like the$Output and $FilteredOutput variables aren't getting cleared when you run the script subsequent times (nothing in the current script looks to do that), so the results are just getting appended to these variables each time.
As you've already said, you could add these to the top of your script:
$FilteredOutput = #()
$Output = #()
This will initialise them as empty arrays at the beginning, which will ensure they start empty as well as make it possible for them to be appended to (which happens at the script via +=). Without doing this on the first run the script likely failed, so I assume you must have done this in your current session at some point for it to be working at all.

How to break Foreach loop in Powershell?

I'm looking for a way to break my Foreach loop.
This is my code
$MyArray = #("desktopstudio","controller","storefront","desktopdirector","licenseserver")
$component = "toto,blabla"
$component = $component.Split(",")
foreach ($value in $component)
{
if ($MyArray -notcontains $value)
{
Write-host "Your parameter doesn't match"
Write-host "Please use one of this parameter $MyArray"
Break
}
}
write-host "I'm here"
I don't understand why it's not breaking my code, because this is the result when I execute it :
Your parameter doesn't match
Please use one of this parameter desktopstudio controller storefront desktopdirector licenseserver
I'm here
You can see that my Write-Host "I'm here" is executed while it should not.
The break statement is used to exit from a loop or switch block which is what it is doing in your case. Instead, you probably want to use the exit command to stop execution of your script when an invalid parameter is found.
$MyArray = #("desktopstudio","controller","storefront","desktopdirector","licenseserver")
$component = "toto,blabla"
$component = $component.Split(",")
foreach ($value in $component)
{
if ($MyArray -notcontains $value)
{
Write-host "Your parameter doesn't match"
Write-host "Please use one of this parameter $MyArray"
exit # <--- change is here
}
}
write-host "I'm here"
See also Get-Help about_Break, Get-Help exit, Get-Help return for more information.

Resources