powershell Import-csv pop up - powershell

so i am working with a bit of code that after setting a static location for the CSV i am using for import. When i run the code it seems to run until i get the Windows can't open this File pop. you know the one with what do you want to do options, like user the web services to find the correct program. i am copying the code so hopefully someone can point on where i made this fubar. just for note before i made the CSV static the Script asked you to type the location in every time so maybe i missed a setting there
if ($args[0] -eq $null)
{
$userNameFile = D:\lync_creation\userlog.csv
$userNameFile = $usernamefile -replace '"',""}
else
{$usernamefile = $args[0]}
if ($userNameFile -ne "")
{$csv=import-csv $userNameFile}
else
{"Could not find a valid .csv with the user information."
exit}
foreach($c in $csv)
# enable for lync
{
"Enabling " + $c.Identity + " for Lync 2010"
Enable-csuser -identity $c.Identity -registrarpool pool01.west.com –sipaddresstype EmailAddress
}
write-host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,AllowCtrlC")

You are seriously over complicating things if you're just going to use a static location for your CSV file.
$csv = Import-CSV D:\lync_creation\userlog.csv
foreach($c in $csv){
"Enabling $($c.Identity) for Lync 2010"
Enable-csuser -identity $c.Identity -registrarpool pool01.west.com –sipaddresstype EmailAddress
}
write-host "Press any key to continue..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,AllowCtrlC")
The first line imports the CSV file into a variable.
The next 4 loops through all entries in that variable, write the host who it's enabling and then enables the person.
The last 2 lines give a Press any key to continue message and then waits for a key press before continuing.

Related

Using powershell to list AD users and making an interactive menu to remove specific user

so what i want to do is use powershell to list all ADusers into a basic interactive menu so that a specific user can be chosen and removed.
This is what I got so far, and this all users and allows me to select a specific one. But the Remove-ADUser -identity $ouEntry (on line: 18) runs right after I start the script and selects all the users for removal before I can select a specific one. I need it to run after i select an option, and with the correct user. I have been looking into a switch menu, but with poor results since I cant embed the ForEach properly.
Appreciate all help. I'm also open to alternate solutions
Clear-Host
$ouCounter = 1
$MenuArray = #()
$DomainName = ($env:USERDNSDOMAIN).split('.')[0]
$Tld = ($env:USERDNSDOMAIN).split('.')[1]
Write-Host "`nChoose the user you want to delete"
foreach ($ouEntry in ((Get-ADUser -SearchBase "DC=$DomainName,DC=$Tld" -Filter *).name))
{
$(" "+$ouCounter+".`t"+$ouEntry)
$ouCounter++
$MenuArray += $ouEntry + " was removed"
$MenuArray += Remove-ADUser -identity $ouEntry
}
do
{ [int]$menuSelection = Read-Host "`n Enter Option Number"}
until ([int]$menuSelection -le $ouCounter -1)
$MenuArray[ $menuSelection-1]
Output
Choose the user you want to delete
1. Administrator
2. Guest
3. user1
4. user2
5. user3
6. user4
7. user5
8. user6
9. Jon Snow
Enter Option Number:
Previous reference: Making a dynamic menu in Powershell
You might consider doing this in a Windows Forms GUI, so the list to choose from can have a scrollbar.
Having said that, the code you have now writes the entry on screen as menu item and immediately removes that user.
Below code first gets the users in an array once and creates a List object from that.
The reason for using a List object is because with that it is easy to remove an item (unlike with using an array).
$DomainName = ($env:USERDNSDOMAIN).Split('.')[0]
$Tld = ($env:USERDNSDOMAIN).Split('.')[1]
# get an array of users in the given OU, sorted on the Name property
$users = Get-ADUser -SearchBase "DC=$DomainName,DC=$Tld" -Filter * | Sort-Object Name
# store them in a List object for easy removal
$list = [System.Collections.Generic.List[object]]::new()
$list.AddRange($users)
# now start an endless loop for the menu handling
while ($true) {
Clear-Host
# loop through the users list and build the menu
Write-Host "`r`nChoose the user you want to delete. Press Q to quit." -ForegroundColor Yellow
$index = 1
$list | ForEach-Object { " {0}.`t{1}" -f $index++, $_.Name }
$menuSelection = Read-Host "`r`nEnter Option Number."
# if the user presses 'Q', exit the loop
if ($menuSelection -eq 'Q') { break }
# here remove the chosen user if a valid input was given
if ([int]::TryParse($menuSelection, [ref]$index)) {
if ($index -gt 0 -and $index -le $list.Count) {
$userToDelete = $list[$index - 1]
Write-Host "Removing user $($userToDelete.Name)" -ForegroundColor Cyan
Remove-ADUser -Identity $userToDelete.DistinguishedName
# remove the user from the list
$list.RemoveAt($index - 1)
}
}
# add a little pause and start over again
Start-Sleep -Seconds 1
}
Hope that helps

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.

How to configure a timeout for Read-Host in PowerShell

Like I said, this code works in PowerShell version 2, but not in PowerShell version 5.
function wait
{
$compte = 0
Write-Host "To continue installation and ignore configuration warnings type [y], type any key to abort"
While(-not $Host.UI.RawUI.KeyAvailable -and ($compte -le 20))
{
$compte++
Start-Sleep -s 1
}
if ($compte -ge 20)
{
Write-Host "Installation aborted..."
break
}
else
{
$key = $host.ui.rawui.readkey("NoEcho,IncludeKeyup")
}
if ($key.character -eq "y")
{Write-Host "Ignoring configuration warnings..."}
else
{Write-Host "Installation aborted..."
}}
The official documentation or Read-Host -? will tell that it's not possible to use Read-Host in that manner. There is no possible parameter to tell it to run with some kind of timeout.
But there are various other questions detailing how to do this in PowerShell (usually utilizing C#).
The idea seems to be to check whenever the user pressed a key using $Host.UI.RawUI.KeyAvailable and check that for the duration of your timeout.
A simple working example could be the following:
$secondsRunning = 0;
Write-Output "Press any key to abort the following wait time."
while( (-not $Host.UI.RawUI.KeyAvailable) -and ($secondsRunning -lt 5) ){
Write-Host ("Waiting for: " + (5-$secondsRunning))
Start-Sleep -Seconds 1
$secondsRunning++
}
You could use $host.UI.RawUI.ReadKey to get the key that was pressed. This solution probably would not be acceptable if you need more complex input than a simple button press. See also:
Windows PowerShell Tip of the Week - Pausing a Script Until the User Presses a Key
PowerTip: Use PowerShell to Wait for a Key Press (Hey, Scripting Guy!)
Seth, thank you for your solution. I expanded on the example you provided and wanted to give that back to the community.
The use case is a bit different here - I have a loop checking if an array of VMs can be migrated and if there are any failures to that check the operator can either remediate those until the checks clear or they can opt to "GO" and have those failing VMs excluded from the operation. If something other than GO is typed state remains within the loop.
One downside to this is if the operator inadvertently presses a key the script will be blocked by Read-Host and may not be immediately noticed. If that's a problem for anyone I'm sure they can hack around that ;-)
Write-Host "Verifying all VMs have RelocateVM_Task enabled..."
Do {
$vms_pivoting = $ph_vms | Where-Object{'RelocateVM_Task' -in $_.ExtensionData.DisabledMethod}
if ($vms_pivoting){
Write-Host -ForegroundColor:Red ("Some VMs in phase have method RelocateVM_Task disabled.")
$vms_pivoting | Select-Object Name, PowerState | Format-Table -AutoSize
Write-Host -ForegroundColor:Yellow "Waiting until this is resolved -or- type GO to continue without these VMs:" -NoNewline
$secs = 0
While ((-not $Host.UI.RawUI.KeyAvailable) -and ($secs -lt 15)){
Start-Sleep -Seconds 1
$secs++
}
if ($Host.UI.RawUI.KeyAvailable){
$input = Read-Host
Write-Host ""
if ($input -eq 'GO'){
Write-Host -ForegroundColor:Yellow "NOTICE: User prompted to continue migration without the blocked VM(s)"
Write-Host -ForegroundColor:Yellow "Removing the following VMs from the migration list"
$ph_vms = $ph_vms | ?{$_ -notin $vms_pivoting} | Sort-Object -Property Name
}
}
} else {
Write-Host -ForegroundColor:Green "Verified all VMs have RelocateVM_Task method enabled."
}
} Until(($vms_pivoting).Count -eq 0)
Also note that all this $Host.UI stuff doesn't work from the Powershell ISE.
To find out from within a script you could test for $Host.Name -eq "ConsoleHost". When true you can use the code from this topic. Otherwise you could use $Host.UI.PromptForChoice or any other way of showing a dialog box. With System.Windows.Forms.Timer you can then set a timer, and code to close the dialog box or form can be run when it expires.

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

Powershell - Loop script until user chooses to exit

How can I start a script over again? I have 3 switches and I want them to revert back to the beginning of the script.
Import-Module ActiveDirectory
Write-Host "--Please Login using a.account--"
#login
$credential = Get-Credential
#Main
Write-Host "--Remote Computer Rename v2.0--"
Write-Host "1. Query AD (Outputs to a text file)"
Write-Host "2. Quick computer rename"
Write-host "3. Quit"
$choice=Read-Host "Chose a number to continue"
#AD Query for computer
switch ($choice)
{
1 {
Write-Host "--Enter first five characters of computer name or full computer name i.e. USCLT--"
$cn=Read-Host 'Computer name'
$out="$cn*"
Get-ADComputer -Filter 'SamAccountName -like $out' >> c:\myscripts\dsquery.txt
Write-Host "Query complete. See dsquery.txt saved to Desktop."
}
...rest of my code.
So after See dsquery.txt saved to Desktop." I want it to go back to write-host portion.
Simple, short, stupid:
& cmd /c pause
exit
This will even contribute the "Press any key" message the TO requested. If you prefer to stay in PowerShell:
Read-Host "Press any key to exit..."
exit
But we may also get the input back:
$reply = Read-Host "Please type EXIT to exit"
if ($reply -eq "EXIT") { exit; }
I like that Read-Host exits the script when typing Ctrl-C, like cmd's pause does.
My personal favorite for checking user input is the do { } until () loop. Here is your code with the added loop, this will accomplish what your looking for:
Import-Module ActiveDirectory
Write-Host "--Please Login using a.account--"
#login
$credential = Get-Credential
#Main
do {
Write-Host "--Remote Computer Rename v2.0--"
Write-Host "1. Query AD (Outputs to a text file)"
Write-Host "2. Quick computer rename"
Write-host "3. Quit"
$choice=Read-Host "Chose a number to continue"
#AD Query for computer
switch ($choice)
{
1 {
Write-Host "--Enter first five characters of computer name or full computer name i.e. USCLT--"
$cn=Read-Host 'Computer name'
$out="$cn*"
Get-ADComputer -Filter 'SamAccountName -like $out' >> c:\myscripts\dsquery.txt
Write-Host "Query complete. See dsquery.txt saved to Desktop."
}
...rest of my code.
} until ($choice -eq 3)
This is a pretty unique strategy in my opinion. I took this from Jerry Lee Ford’s book : Microsoft Windows PowerShell Programming for the absolute beginner
you can read more about these and every other loop in powershell here : http://www.powershellpro.com/powershell-tutorial-introduction/logic-using-loops/
From a blog post I found:
echo "Press any key to exit..."
$Host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown") | OUT-NULL
$Host.UI.RawUI.FlushInputbuffer()
Enclose the whole thing in a while (1) {} block. That creates an infinite loop that will only terminate if it encounters a break (end the loop) or exit (end the script). Presumably, option 3 will lead to one of those statements.