Data Structure issues powershell - powershell

My end goal is to be able to enter several strings, then reference them in other commands, in this case, mapping a network drive.
I'm having issues with the 'several' part of that. I can work with one at a time, but when I try to do more it fails.
$Servers = #{"Server1" = "10.10.10.10";"Server2" = "10.10.10.11"}
$Sites = Read-Host "enter site codes"
$Sites.Split('.')
ForEach ($Site In Sites){
write-host $Servers[$Sites]
}
This in theory should output 10.10.10.10 and 10.10.10.11 on two lines, but it doesn't. It just outputs the value of $Sites, Server1,Server2
I don't know what I'm doing wrong.

I believe your mistake(s) is using $Sites (instead of $Site) as the key in your foreach loop, and not getting your split array into the foreach collection:
$Servers = #{"Server1" = "10.10.10.10";"Server2" = "10.10.10.11"}
$Sites = Read-Host "enter site codes"
ForEach ($Site In $Sites.Split(',')){
write-host $Servers[$Site]
}

Related

How to print data from hashTable with variable?

i'd like to print data from table. When i use Read-Host this code not working.
How I can make this?
(Sorry for my english).
my Code is here:
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
$cureentData = Get-Date -format "yyyy-M-d"
$table = $DataSet.Tables[0]
$i=0;
$hash = #{};
foreach ($row in $table)
{
$hash.Add(($i),(#{
'app_id' = ($row.app_id)
'app_guid' = ($row.app_guid)
'app_nazwa_pliku' = ($row.app_nazwa_pliku)
}))
Write-Host [$i] "Nr sprawy:" $row.sp_numer "Zakończono:" $row.ak_zakonczono"-" $row.app_guid ;
$i++;
}
if($table.Rows.Count -gt 1)
{
$selected = Read-Host -Prompt 'Który z plików chcesz zmienić?';
($hash.$selected).app_guid; #working only if $selected is $selected=5 without Read-Host
($hash[$selected]).app_guid; #working only if $selected is $selected=5 without Read-Host
($hash.5).app_guid; #working, but i need use variable
}
Someone can help me?
$selected is not an integer
Read-Host will always return strings. You built your hashtable with numerical keys. So, in its simplest form, you need to coerce integers from your input.
[int]$selected = Read-Host -Prompt 'Który z plików chcesz zmienić?';
or
$selected = (Read-Host -Prompt 'Który z plików chcesz zmienić?') -as [int];
Beware that since you can type anything you want into Read-Host you should do some data validation before attempting to use the data as an integer.
Change the hash table
You could also reduce this complexity by using strings in your hash table generation as well
$hash.Add(("$i"),(#{
Using this approach you don't have to make changes to the Read-Host prompt output
Improve your choice method
You might be able to improve your choice system depending on the required complexity of your task.
your problem appears to be the type of the item used as a key. Read-Host returns a [string] ... so the number you get from it is a numeric string, not an [int]. coerce it to an [int] and the lookup works. [grin] here's an example ...
$HashTable = #{}
foreach ($Index in 0..10)
{
$HashTable.Add($Index,
#{
Pow2 = [math]::Pow($Index, 2)
Pow3 = [math]::Pow($Index, 3)
})
}
$HTKey = [int](Read-Host 'Enter a number from 0 to 10 to see the cube of it ')
$HashTable[$HTKey].Pow3
number entered = 3
result = 27

Powershell and jenkins foreach loops

I have a function in Powershell and want to run this on many servers.
It's running from Jenkins via a Powershell step, the input param $env:servers is configured as a "Muli-line String".
Simple example:
function test {
param(
[string]$servername
)
#do somthing
}
$servers = $env:servers
foreach ($s in $servers) {
test -servername $s
}
But when I build it with parametrs, the foreach does not work - it treats $servers like a single string. What's wrong?
As your input param ($env:servers) is a multi-line string, $servers will also be a single multi-line string.
To use this with foreach it needs to be an array of strings, you will need to split $env:servers so $servers becomes an array of strings with each line an item. This is very simple to do using Split() (blog on this subject):
$servers = ($env:servers).Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries)
This will split on NewLine and deal with any blank lines by removing an empty entries from the final output.
Example code to show this behaviour for future reference to others:
$input_servers = #"
server1
server2
server3
"#
$servers = $input_servers.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries)
foreach ($server in $servers) {
Write-Output "Server Name: $server"
}

Foreach loop not running through list of entries

I've tried searching this multiple times but havent resolved the issue. I have a list of servers in $mediaagentlist, the foreach loop is supposed to run through each one and get the state of certain services:
$mediaagentlist = "cs0400ma01
cs0400ma02"
[string]$Commcell_Input = $args[0]
$MAChoice = $args[1]
if ($MAChoice -eq $null)
{
Write-Output "No media agent was specified, running against all MAs in the Commcell..."
#Run this loop for each MA which is stored in Mediaagentlist
foreach ($Mediaagent in $Mediaagentlist)
{
Write-Output $Mediaagent
$GxCLMgrS_State = Invoke-Command -ComputerName $Mediaagent {Get-Service -name "GxClMgrS(Instance001)"}
$GXMMM_State = Invoke-Command -ComputerName $Mediaagent {Get-Service -name "GXMMM(Instance001)"}
$GxCVD_State = Invoke-Command -ComputerName $Mediaagent {Get-Service -name "GxCVD(Instance001)"}
Write-Output "Client manager service state: " $GxCLMgrS_State.Status
Write-Output "Media manager mount service state: " $GXMMM_State.Status
Write-Output "Communications service state: " $GxCVD_State.Status
}
}
How do I correct this so the for each loop runs through the list of entries in $mediaagentlist and runs the code for each server?
Thanks in advance!
It looks like your issue is here
$mediaagentlist = "cs0400ma01
cs0400ma02"
It looks like your missing a closing qoute per word and a comma
try
$mediaagentlist = "cs0400ma01", "cs0400ma02"
or
$mediaagentlist = #("cs0400ma01", "cs0400ma02")
Or you can define a multi-line string, then split on new lines, if there's a reason you needed the input to be a single multi-line string:
$mediaagentlist = "cs0400ma01
cs0400ma02" -split '[\r\n]+'

Output ALL results at the end of foreach instead of during each run

I inherited a script which loops through a set of servers in a server list and then outputs some stuff for each one. It uses StringBuilder to append stuff to a variable and then spits out the results...how do I get the script to store the contents so I can display it at the VERY end with the results of the entire foreach instead of having it print (and then overwrite) on each iteration?
Currently my results look like this:
ServerName1
Text1
Next run:
ServerName2
Text 2
How do I get it to store the data and then output the following at the end so I can email it?
ServerName1
Text1
ServerName2
Text2
My code:
foreach($Machine in $Machines)
{
Invoke-Command -ComputerName $Machine -ScriptBlock{param($XML1,$XML2,$XML3,$URL)
[System.Text.StringBuilder]$SB = New-Object System.Text.StringBuilder
$X = $SB.AppendLine($env:COMPUTERNAME)
if (Test-Path <path>)
{
$PolResponse = <somestuff>
$PolResponse2 = <somestuff>
Write-Host "[1st] $PolResponse" -ForegroundColor Magenta
Write-Host "[2nd] $PolResponse2" -ForegroundColor Magenta
$X = $SB.AppendLine($PolResponse)
$X = $SB.AppendLine($PolResponse2)
}
else
{
$PolResponse = "[1st] No Response"
$PolResponse2 = "[2nd] No Response"
Write-Host $PolResponse -ForegroundColor Red
Write-Host $PolResponse2 -ForegroundColor Red
$X = $SB.AppendLine($PolResponse)
$X = $SB.AppendLine($PolResponse2)
}
} -ArgumentList $XML1, $XML2, $XML3, $URL
}
# Sending result email
<<I want to send the TOTALITY of $SB here>>
You can start by moving the StringBuilder variable declaration outside of the for loop (prior to it)
[System.Text.StringBuilder]$SB = New-Object System.Text.StringBuilder
then FOR LOOP
I don't know if this will be a good solution for what you're asking for or not, but what you could do is create a txt file and every loop in the foreach loop add the information to a txt file. This is one way to store all of the information and then have all of it together at the end.
New-Item -Path "\\Path\to\file.txt" -Itemtype File
Foreach(){
$Stuff = # Do your stuff here
Add-Content -Value $stuff -Path "\\Path\to\file.txt"
}
# Email .txt file ?
# You could use Send-MailMessage to do this possibly
Hopefully this can be helpful for your goal.

Printing ZPL (Zebra Programming language) file via Powershell

I wrote a Powershell script that asks questions, takes the user's input, plugs those variables in a label created in ZPL, then print it out via Out-Printer. Everything seems to work fine except the label that prints has incorrect spacing or missing data.
Originally I had the script create a .txt file that held the label in ZPL format. Checking the label all the data was correct. When I would print the .txt file from Notepad using the same printer (Driver was set to Generic/ Plain text). The label would be perfect.
I also tried switching the printing method to the WMI variant. It would do the same formatting issues and missing data, but now in different spots.
It almost seems Powershell is formatting the data before it prints.
Here is the current code I have with some data censored for privacy concerns.
$i = 0
$global:counter = $i + 1
$AllPrinters = gwmi win32_printer -computername $env:computername
$DefaultPrinterString = $AllPrinters | where {$_.Default -eq $true}
$DefaultPrinter = [regex]::match($DefaultPrinterString, '\"([^\"]+)\"').Groups[1].Value
Write-Host "========== Print Company Labels =========="
Write-Host "Question will be on the left, type in answer and hit ENTER"
$location = Read-Host "Which location? (LOC1 or LOC2)"
$pro = Read-Host "What is the Pro#?"
$quote = Read-Host "What is the quote number?"
$pallet = Read-Host "How many pallets are there?"
$printer = Read-Host "What printer do you want?"
While ($global:counter -le $pallet)
{
$printcode = "^XA^MCY^XZ^XA^SZ2^MMT^MTT~JSN^LT0^MD0^MNY^PR5^PON^PMN^CI0^LRN
^FT300,1300^A0B,350,160^FDPRO: $pro^FS
^FT480,1300^A0B,175,150^FD$location^FS
^FT480,1300^A0B,175,150^FD$location^FS
^FT480,900^A0B,175,100^FDQuote: $quote^FS
^FT800,1300^A0B,350,225^FDPallet $global:counter of $pallet^FS
^PQ01~*QUANT,04~,0,~*COPIES,04~,N^MCY^XZ"
(New-Object -ComObject WScript.Network).SetDefaultPrinter($printer)
$printcode | Out-Printer
Start-Sleep 1
(New-Object -ComObject WScript.Network).SetDefaultPrinter($DefaultPrinter)
$global:counter++
}
Any help would be greatly appreciated.
Thanks in advance