Power Shell Script for loop? - powershell

I am trying to create a script in PowerShell to run a utility with some default parameters. There will be multiple IP addresses into a CSV file that we will need to import. Then do a loop to run the utility for each IP address imported.
Set-Location 'C:\Program Files\Utility
$printerlist = Get-Content ".\Printer.csv"
$pass = Read-Host "Enter your Password"
.\Utility.exe -USERNAME="ADMIN" -PASSWORD="$pass"-ADDRESS="$printerlist" -PP-INSTALL="192.168.33.21" -JA-INSTALL="192.168.33.21" -IPA-INSTALL="192.168.33.21" -QUOTA-DELETE
Foreach($printer in $printerlist){
echo $line
}

As the comment points out, you need to loop over those IP addresses. You can use a feature called splatting to apply a set of default arguments:
Set-Location -Path $Env:ProgramFiles\Utility
$pass = Read-Host -Prompt 'Enter your Password'
$utilArgs = #(
'-USERNAME="ADMIN"'
"-PASSWORD=""$pass"""
'-PP-INSTALL="192.168.33.21"'
'-JA-INSTALL="192.168.33.21"'
'-IPA-INSTALL="192.168.33.21"'
'-QUOTA-DELETE'
)
foreach ($printer in Get-Content -Path Printer.csv) {
.\Utility.exe "-ADDRESS=""$printer""" #utilArgs
}
Docs
about_Splatting

Related

Add smtp Proxy Addresses from users listed in a text file using PowerShell

I am trying to create a simple script to add Proxy Addresses to the AD field using PowerShell.
I was able to get it working using this, but now I am at a roadblock on how I can do this importing the usernames from a text file.
$Username = Read-Host -Prompt "Enter the username'
Set-AdUser $Username -add #{ProxyAddresses = "smtp:$Username#example.com,smtp:$Username#marketing.example.com" -split ","}
What I want to do now is instead of prompting for a username to be entered I just want to have a text file with username like this.
Text File Of Usernames: These will all be on a separate line. I am not sure how to format that way on here.
jallen
sdiggs
gdavis
mhyde
twhite
I am confused how to go forward with this. To my understanding I want to use Get-Content to create the username array and then for each line in the text file add the proxy addresses.
$Username = Read-Host -Prompt "Enter the username'
Set-AdUser $Username -add #{ProxyAddresses = "smtp:$Username#example.com,smtp:$Username#marketing.example.com" -split ","}
I want to remove the need for user input and import the username variables from a text file.
Assuming you have the txt file with each user in a new line as shown in your question, you're right, you can use Get-Content to read your file then you need to loop over each line:
(Get-Content path\to\yourfile.txt).Trim() | ForEach-Object {
try {
Set-AdUser $_ -Add #{ ProxyAddresses = "smtp:$_#example.com,smtp:$_#marketing.example.com".Split(",") }
}
catch {
# can do error handling here
Write-Error $_
}
}
The use of Trim() in this example is so it removes any excess of white space from the beginning and end of all lines.

Change currently running script

Is there any way to add text to specific part of script to the currently running script?
If i have a menu with options:
Install All
Add item
Quit
Could the Add item be possible?
Learning to use powershell (heavy user of batches).
When entering Add item, then a read-host would pop up, adding a row between the long row of ### addwifi -wnm $USERINPUT afterwards 'restarting' the script.
Current script:
#cmd: title Add****
$host.ui.RawUI.WindowTitle = "Add Wi-Fi networks"
#When Show-Menu –Title 'SetupWi-Fi' is called
function Show-Menu
{
# NOTE if changing warible from somewhere else (Show-Menu -WARIBLE VALUE) then param part must be included
param (
[string]$Title = 'SetupWi-Fi'
)
Clear-Host
#cls and echo on #echo off
Write-Host "================ $Title ================"
Write-Host "a: Add Wi-Fi networks."
Write-Host "q: Quit."
}
#Do this until x
#For future shortening purposes
function addwifi
{
param (
[string]$wnm
#wnm= wifi name
)
netsh wlan add profile filename="$wnm.xml"
#for some reason (nice for this script) . stops the warible name
}
do
{
# call Show-Menu and optionally change varible: –Title 'Warible' changes the $title varible
Show-Menu
# makin varible chaase equal user input, placing Selection before it
$chaase = Read-Host "Selection:"
#switch according to the varible chaase
switch ($chaase)
{
'a' {
#'single quote' acts as echo, now executing commands of 'a' varible
'Adding Wi-Fi networks.'
$host.ui.RawUI.WindowTitle = "Adding Wi-Fi networks"
#note the upper function is called with warible
#add below here! #####################################################################
addwifi -wnm laptopidee
#add above here! #####################################################################
}
#close a execution
#close switch
}
#close do
}
#until x: selection == input q
until ($chaase -eq 'q')
One possibility is to use placeholders that you replace at runtime, though I'm not sure how well it will hold up for more complex scripts.
For example, if you have the following script:
$scriptPath = "$PsScriptRoot\$($MyInvocation.MyCommand.Name)"
$scriptContent = Get-Content "$PsScriptRoot\$($MyInvocation.MyCommand.Name)" -Raw
$newItem = Read-Host "Please enter new command"
##Placeholder
$scriptContent -replace "$([char]0x0023)$([char]0x0023)Placeholder", "$([char]0x0023)$([char]0x0023)Placeholder$([char]0x000D)$([char]0x000A)$newItem" |
Set-Content -Path $scriptPath
Each time you run it, you will be prompted for a new command, which will be added below the ##Placeholder. So, if you enter Get-Process when prompted, the script would end up on-disk like this:
$scriptPath = "$PsScriptRoot\$($MyInvocation.MyCommand.Name)"
$scriptContent = Get-Content "$PsScriptRoot\$($MyInvocation.MyCommand.Name)" -Raw
$newItem = Read-Host "Please enter new command"
##Placeholder
Get-Process
$scriptContent -replace "$([char]0x0023)$([char]0x0023)Placeholder", "$([char]0x0023)$([char]0x0023)Placeholder$([char]0x000D)$([char]0x000A)$newItem" |
Set-Content -Path $scriptPath
Next time you run the script you will be prompted for a new command, which is added to the list, and all commands already on the list will be executed.
Yes. Use external files as sources to be pulled in. The Add Item menu option creates another file to be read in at next execution.
Many people did this with batch files using .ini files to hold parameters. Similar construct.

Sending each line from text file to remote computer?

This is my script to whitelist IP in a remote system. I want my script to read data from a text file on my local system and then foreach line I want to execute the scriptblock on the remote server.
Text file looks like this:
url1
url2
url3
Here is my code:
Invoke-Command -ComputerName $($server.text) -Credential ciqdev\riteshthakur {
param($a, $b, $c, $url)
Set-Location "C:\Windows\System32\inetsrv"
$url | foreach {
.\appcmd.exe set config "$_" -section:system.webServer/security/ipSecurity /+"[ipAddress='$($a)',allowed='$($c)',subnetMask='$($b)']" /commit:apphost
}
} -ArgumentList $ip.text, $mask.text, $allowed, (get-content "File location")
This adds provided ip to all the pages in all the websites in IIS. Please help.
EDIT: Improved efficiency by generating the command dynamically, and invoking it once.
I'd suggest using a technique similar to the following, where you read in the text file as an array of lines, and then iterate over each line, generating the commands that you want to run on the remote system.
Once you've generated the command as a string, you simply call the static [ScriptBlock]::Create() method to create a ScriptBlock object, based on the command string, and pass that into Invoke-Command.
I'd suggest you get familiar with the concept of PowerShell Splatting, which I talk about in this YouTube video: https://www.youtube.com/watch?v=CkbSFXjTLOA. It's a really powerful concept, and helps make your code easier to read. The example code below uses PowerShell Splatting (available in PowerShell 3.0 and later).
### Read the text file on the local system
$Whitelist = Get-Content -Path IPwhitelist.txt;
### Generate the stub for the remote command
$RemoteCommand = #'
param($a, $b, $c)
Set-Location -Path C:\Windows\System32\inetsrv
'#
### Add more commands to the remote command
foreach ($Line in $Whitelist) {
$RemoteCommand += '{1}.\appcmd.exe set config "{0}" -section:system.webServer/security/ipSecurity /+"[ipAddress=''$($a)'',allowed=''$($c)'',subnetMask=''$($b)'']" /commit:apphost' -f $Line, "`n";
}
### Invoke the entire remote command (once)
$Command = #{
ComputerName = $Server.Text
Credential = Get-Credential -Credential ciqdev\riteshthakur
ScriptBlock = [ScriptBlock]::Create($RemoteCommand);
ArgumentList = #($ip.text, $mask.text, $allowed)
}
Invoke-Command #Command;
Just read the file using the Get-Content cmdlet and iterate over each item using the Foreach-Object cmdlet:
Invoke-Command -ComputerName $($server.text) -Credential ciqdev\riteshthakur {
param($a, $b, $c, $urls)
Set-Location "C:\Windows\System32\inetsrv"
$urls | Foreach {
.\appcmd.exe set config $_ -section:system.webServer/security/ipSecurity /+"[ipAddress='$($a)',allowed='$($c)',subnetMask='$($b)']" /commit:apphost
}
} -ArgumentList $ip.text, $mask.text, $allowed, (Get-Content 'Path_to_your_file')

Powershell answer file similar to Linux bash

What I want: Execute my powershell script (.ps1) and answer all the read-host questions using an answer file.
On Linux bash this is straightforward see:Answer file Linux bash
You can use a subexpression ($()) to call Read-Host in case a parameter argument is not present:
param(
$Name = $(Read-Host -Prompt "Input Name"),
$Company = $(Read-Host -Prompt "Input Company Name"),
$Country = $(Read-Host -Prompt "Country")
)
if(-not $Country){
$Country = "US"
}
Write-Host $(#'
Hello, {0} from {1}!
How is the weather in {2}?
'# -f $Name,$Company,$Country)
# do more stuff
Save as myscript.ps1.
Now, when you run it without any parameters, it prompts you for all the values:
PS C:\> .\prompt.ps1
Input Name: Arni
Input Company Name: MegaCorp Inc.
Country:
Hello, Arni from MegaCorp Inc.!
How is the weather in US?
PS C:\>
But if you want to run it without being prompted, just supply all required parameters:
PS C:\> .\prompt.ps1 -Name Xavier -Company "SuperCorp SA" -Country Brazil
Hello, Xavier from SuperCorp SA!
How is the weather in Brazil?
PS C:\>
What you are asking for does not exist in PowerShell, the methods of passing arguments to a function (e.g. splatting, the pipeline) cannot be used with Read-Host.
What is possible is creating your script as a function and making use of the aforementioned methods to pass the arguments when the function is to be run in an automated fashion.

perform nslookup from PowerShell

I'm writing a powershell to exact the ip from a server name, which need me to embed the nslookup code into my powershell
how can I do the intergrating work?
Can any body help me?
Add-PSSnapin Microsoft.SharePoint.PowerShell
$web = Get-SPWeb -Identity “http://nycs00058260/sites/usitp“
$server_status = "PROD"
$list=$web.Lists[”DNS_Status”]
$items = $list.items
Foreach($item in $items){
$item_name = $item["Server_name"] #need to get the ip by this name
/*nslook up*/
$item_name.update()
}
If you install the PSCX module, it comes with a cmdlet Resolve-Host which handles name lookups.
Absent that, this one-liner will do the job
[System.Net.Dns]::GetHostAddresses("www.msn.com")
You can also pass in an IP address - but the results will be different.
See also http://blogs.msdn.com/b/powershell/archive/2006/06/26/647318.aspx & http://powershell.com/cs/media/p/210.aspx
PowerShell 3.0 on Windows 8 and higher comes with a Resolve-DnsName cmdlet that will get this information:
(Resolve-DnsName $server_name)[0].IpAddress
Simply use :
Resolve-DnsName monServer | ? { # make selection here } | % { $_.IPAdress } | select-object -first 1
#Here is a far better method for nslookup
# HOWTO ensure an nslookup results no errors but still gives the original names and column separations
$day = Get-Date -Format yyyyMMdd #<-- HOWTO set the day variable for today
$ErrorActionPreference = ‘SilentlyContinue’ #<-- HOWTO turn off error messages
$WarningActionPreference = 'SilentlyContinue' #<-- HOWTO turn off warning messages
$servers = Get-Content .\input\servers.txt
Foreach ($server in $servers){
$result = Resolve-DnsName $server -Server $env:LOGONSERVER.Remove(0,2) -Type ALL #<-- NSLOOKUP using your logon server
write-host ($server+","+$result.Name+","+$result.IPAddress) #<-- HOWTO Write two variables separated by a comma
}
$ErrorActionPreference = ‘SilentlyContinue’ #HOWTO turn on error messages
$WarningActionPreference = 'SilentlyContinue' #HOWTO turn on warning messages