If error, skip to next in Powershell (Microsoft Teams) - powershell

Good evening,
I have written a piece of code in Powershell that takes a .csv file as input, and create a new
Microsoft Team with the channels and users in the .csv
The script is working, but i dont really like the part where i add the owners to the team. I recieve a list of ID's in the .csv file, but i can only add the owners with a mailadres. This would be a easy loop, but there are 3 possible domains that the user is connected to.
My goal is to have a piece of code that adds #domain1.nl to the ID that i get in the .csv, and try to add the user. if i receive a error because that address does not exist, it will try to add the owner with #domain2.nl and #domain3.nl added to it. If nothing works, it should give a Write-Host that says "This domain has to be added"
Below is the piece of code that works, but i think its not the best way to it and it could be improved.
#Adding the owners to the Team
if ($d.ID) {
$Error.Clear()
try {
$ID = $d.ID + "#domain1.nl"
Add-TeamUser -GroupId $GroupID -User $ID -Role Owner
} catch { "Error occured" }
if ($Error) {
$Error.Clear()
try {
$ID = $d.ID + "#domain2.nl"
Add-TeamUser -GroupId $GroupID -User $ID -Role Owner
} catch { "Error occured" }
if ($Error) {
$Error.Clear()
try {
$ID = $d.ID + "#domain3.nl"
Add-TeamUser -GroupId $GroupID -User $ID -Role Owner
} catch { "Error occured" }
if ($Error) {
Write-Host "This domain has to be added to the code"
}
}
}
}
Many thanks in advance!

Use try / catch inside a foreach loop:
$ok = $false
foreach ($domain in '#domain1.nl', '#domain2.nl', '#domain3.nl') {
try {
Add-TeamUser -GroupId $GroupID -User ($d.ID + $domain) -Role Owner
$ok = $true
} catch {
Write-Warning "Error occurred with domain $domain."
}
if ($ok) { break }
}
if (-not $ok) {
Write-Error 'This domain has to be added to the code'
}

Related

How i get this powershell dynamic script working?

Hello everyone i need this script to work and i'm stuck with a error.
I need to have a dynamic script with user choice and linking the mailbox we enter in first step to the HR choice.
In the csv part we have a group distribution list
Error says that i can not do the add-distributiongroupmember and i don't know why
can someone help me on this one ?
(I just do the 0 part choice because i need this one to work before doing the other choice)
code below
Connect-ExchangeOnline
$User = Read-Host "Enter Name of the mailbox to add"
Try {
$Mbx = Get-Mailbox -Identity $User -ErrorAction Stop | Select -ExpandProperty PrimarySmtpAddress}
Catch {
Write-Host "No mailbox can be found called" $User; break }
$Services = [System.Management.Automation.Host.ChoiceDescription]::new('&Services')
$Services.HelpMessage = 'Get running services'
$HR = New-Object System.Management.Automation.Host.ChoiceDescription '&HR', 'Get running HRDL'
$Legal = New-Object System.Management.Automation.Host.ChoiceDescription '&Legal', 'Get running LegalDL'
$Quit = New-Object System.Management.Automation.Host.ChoiceDescription '&Quit', 'Quit menu'
$options = [System.Management.Automation.Host.ChoiceDescription[]]($HR, $Legal, $Quit)
$Result = $host.UI.PromptForChoice('Task menu', 'Select a Department', $options , 0 )
$DLs = Import-Csv -Path "C:\Users\GregorySemedo\Desktop\Script\DL\DL-HR.csv"
switch($Result)
{
0 { ForEach ($DL in $DLs) {
Try {
Add-DistributionGroupMember -Identity $DL."HR" -Member $Mbx -ErrorAction Continue }
Catch {
Write-Host "Couldn't add" $Mbx "to DL" (Get-DistributionGroup -Identity $DL."HR").DisplayName }
If($?)
{
Write-Host $User Succesfully added -ForegroundColor Green
}
Else
{
Write-Host $User - Error occurred -ForegroundColor Red
}}
}
}

Using Powershell to get AllowLogon from AD doesn't always display the correct information

I have a script that uses an input file with users SamAccountName. It goes thought the script and updates the users profile to check mark the
"Deny this user permissions to log on to Remote Desktop Session Host Server".
Once the value is set I also want to read it to make sure it got changed properly.
For most users it works but for some it will say it changed but it actually is not.
$ADUsers = Get-Content "C:\PSTOOLS\Passwordneverexpire\disable-enbale deny logon.txt"
ForEach ($User in $ADUsers) {
$UserDN = (Get-ADUser -identity $User).distinguishedName
if ($UserDN) {
$Command = [ADSI] "LDAP://$UserDN"
$Command.psbase.invokeSet("AllowLogon",0) # it will NOT allow remote logon
$Command.setinfo()
Write-Host $User + "Allow logon " + $Command.psbase.InvokeGet("AllowLogon") -as [Boolean]
}
else {
Write-Host "$UserDN Does Not Exist"
}
}
AllowLogon has 3 state possible :
Enabled = $true
Disabled = $False
Never Defined = ERROR on read !
you can use this code
$AdsiItem = [adsi]"LDAP://$($item.DistinguishedName)"
try {
$AllowLogon = $AdsiItem.InvokeGet("AllowLogon")
} catch {
# unreadable, because it is never defined
$AllowLogon = $Null
}
if($AllowLogon -eq $true) {
'TSE authorized!'
} elseif ($null -eq $AllowLogon ) {
'TSE not forbidden!'
} else {
'Forbidden!'
}

Enable Users Script

I am attempting to make a script that will check a variety of settings and ask permission before changing them. I'm writing this for non-IT users, so each of the user checks is a pop out message box. I thought that this part of the code was working, but now not so much. I'm getting an error indicating the user wasn't found, but that's what I'm trying to use as an if-else trigger. Error Message
As always, thanks to all the saints out there saving my behind from this.
PS: I know its not overly secure to have the password hard coded into the script, and if it were up to me, we wouldn't do it this way. But this is how the boss wants it for now.
#User Group
If (Get-LocalGroup -Name "Koko Svc"){
Write-Host "User Group Koko Svc already exists"
}
Else{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the Local Group `"Koko Svc`"?","`"Koko Svc`" Group Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm){
"Yes" {
write-host "User agreed to create `"Koko Svc`""
New-LocalGroup -Name 'Koko Svc' -Description 'KoKo Svc'
}
"No" {
write-host "User declined to create `"Koko Svc`""
break
}
"Cancel" {
write-host "User stopped Settings Check"
exit
}
}
}
#Users
If (Get-LocalUser -Name "KoKo Svc"){
Write-Host "User Koko Svc already exists"
}
Else{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the User `"Koko Svc`"?","`"Koko Svc`" User Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm){
"Yes" {
write-host "User agreed to create `"Koko Svc`""
$Password1 = ConvertTo-SecureString "FooBar" -AsPlainText -Force
New-LocalUser "KoKo Svc" -Password $Password1 -FullName "KoKo Svc"
Add-LocalGroupMember -Group 'Administrators' -Member ('KoKo Svc','Administrators')
Add-LocalGroupMember -Group 'Koko Svc' -Member ('KoKo Svc','KoKo Svc')
}
"No" {
write-host "User declined to create `"Koko Svc`""
break
}
"Cancel" {
write-host "User stopped Settings Check"
exit
}
}
}
If (Get-LocalUser -Name "Valued Customer"){
Write-Host "User Valued Customer already exists"
}
Else{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the User `"Valued Customer`"?","`"Valued Customer`" User Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm){
"Yes" {
write-host "User agreed to create `"Valued Customer`""
$Password2 = ConvertTo-SecureString "BarFoo" -AsPlainText -Force
New-LocalUser "Valued Customer" -Password $Password2 -FullName "Valued Customer"
Add-LocalGroupMember -Group 'Administrators' -Member ('Valued Customer','Administrators')
Add-LocalGroupMember -Group 'Koko Svc' -Member ('Valued Customer','KoKo Svc')
}
"No" {
write-host "User declined to create `"Valued Customer`""
break
}
"Cancel" {
write-host "User stopped Settings Check"
exit
}
}
}
You could change it to
If (Get-LocalUser -Name "Valued Customer" -ErrorAction SilentlyContinue){
Write-Host User Valued Customer already exists
}
Else{
write-host available
}
That way only if it produces an output it will run the if portion.
A few things.
You can't use the same name for both a group and a user, which is why you get the error
The name KoKo Svc is already in use
On commands that you expect to fail, and want to take action if it does, use try/catch blocks. You can go the -ErrorAction SilentlyContinue route, but in my opinion, that's sloppy and inelegant. You'll just be ignoring the error, instead of taking action on it. I would do something like this
try
{
Get-LocalUser -Name $Name -ErrorAction Stop
$exists = $true
Write-Host "User $Name already exists"
}
catch [Microsoft.PowerShell.Commands.UserNotFoundException]
{
$exists = $false
}
then DRY the code up by tossing it in a simple function or two, so I'm not copy pasting a big chunk every time
function Test-LocalUser([string]$Name)
{
try
{
Get-LocalUser -Name $Name -ErrorAction Stop
$exists = $true
Write-Host "User $Name already exists"
}
catch [Microsoft.PowerShell.Commands.UserNotFoundException]
{
$exists = $false
}
return $exists
}
function Test-LocalGroup([string]$Name)
{
try
{
Get-LocalGroup -Name $Name -ErrorAction Stop
$exists = $true
Write-Host "Group $Name already exists"
}
catch [Microsoft.PowerShell.Commands.GroupNotFoundException]
{
$exists = $false
}
return $exists
}
Then for your code, you can do something like this
$group = "Koko Svc group"
if(!(Test-LocalGroup -Name $group))
{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the Local Group `"$group`"?","`"$group`" Group Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm)
{
"Yes"
{
write-host "User agreed to create `"$group`""
New-LocalGroup -Name $group -Description $group
}
"No"
{
write-host "User declined to create `"$group`""
break
}
"Cancel"
{
write-host "User stopped Settings Check"
exit
}
}
}
#Users
$user = "Koko Svc user"
if(!(Test-LocalUser -Name "Koko Svc"))
{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the User `"$user`"?","`"$user`" User Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm)
{
"Yes"
{
write-host "User agreed to create `"$user`""
$Password1 = ConvertTo-SecureString "FooBarasdasdasdasdadad2334342342!!!" -AsPlainText -Force
New-LocalUser "$user" -Password $Password1 -FullName "$user"
Add-LocalGroupMember -Group 'Administrators' -Member ($user,'Administrators')
Add-LocalGroupMember -Group $group -Member ($user,$group)
}
"No"
{
write-host "User declined to create `"$user`""
break
}
"Cancel"
{
write-host "User stopped Settings Check"
exit
}
}
}
I would also recommend tossing the user creation portion into a function as well, to reduce all the copy-paste code. If this is something designed for other people, making it easy to maintain is a priority. By making functions out of your repeated code, you only have to make a change in one place, rather than every copy/pasted section. If you want to see an example of the user creation portion in a function, lemme know and I'll toss it in an edit.

Powershell: How to request user authentication to continue

My Powershell script has some features/functions implemented, but there are some features that I want to restrict to some users.
In order to allow the current user or a different user to select such restricted features from the menu, I am looking for a way to require user authentication from Windows to continue. How could I do that? How the UserAuthentication function below should be like?
Code:
$feature = Read-Host 'Select the feature by typing the number [1 - 2]'
switch ($feature)
{
1
{
write-output "This feature any user can reach"
}
2
{
$user = Read-Host "This feature only some user can reach and requires authentication. Entry your username to proceed"
$allowedUsers = "user1", "user2"
if($allowedUsers.contains($user))
{
write-output "This feature the user $user can reach. Please authenticate to continue"
if((UserAuthentication $user) -eq $true)
{
write-output "$user successfully authenticated"
}
else
{
write-output "$user unsuccessful authenticated"
}
}
else
{
write-output "This feature the user $user cannot reach"
}
}
}
function UserAuthentication($user)
{
return $true #May return 'True' if successfully authenticated or 'False' if not.
}
This answer is for when your users are member of an AD domain
I have changed the function name UserAuthentication to Get-Authentication to comply with the Verb-Noun function naming convention in PowerShell.
# helper function test if a username/password combination is valid.
# if valid, the username entered in the box is returned.
function Get-Authentication {
$Credentials = Get-Credential "$env:USERDOMAIN\$env:USERNAME" -Message "Please authenticate to continue" -ErrorAction SilentlyContinue
if ($Credentials) {
$UserName = $Credentials.UserName
$Password = $Credentials.GetNetworkCredential().Password # --> plain-text password
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ds = New-Object System.DirectoryServices.AccountManagement.PrincipalContext Domain
if ($ds.ValidateCredentials($UserName, $Password)) {
# return the username entered
$UserName
}
}
}
# your code here
# fill in the SamAccountNames of allowed users for this feature
$allowedUsers = 'samaccountname','of', 'users', 'that', 'are', 'allowed', 'to', 'use', 'feature 2'
$feature = Read-Host 'Select the feature by typing the number [1 - 2]'
switch ($feature) {
'1' { Write-Output "This feature any user can reach" }
'2' {
$user = Get-Authentication
if ($null -ne $user -and $allowedUsers -contains $user) {
Write-Output "User $user is allowed for this feature"
}
else {
Write-Output "This feature the user cannot reach"
}
}
}

Continue execution on Exception

Below is the script I want to execute. The issue here is once an exception occurs it stops executing, I used continue in the catch block but that did not work. How do I get it working even after an exception occurs it should loop in foreach.
I also used a while($true) loop but that went into infinite loop. How to go about it?
$ErrorActionPreference = "Stop";
try
{
# Loop through each of the users in the site
foreach($user in $users)
{
# Create an array that will be used to split the user name from the domain/membership provider
$a=#()
$displayname = $user.DisplayName
$userlogin = $user.UserLogin
# Separate the user name from the domain/membership provider
if($userlogin.Contains('\'))
{
$a = $userlogin.split("\")
$username = $a[1]
}
elseif($userlogin.Contains(':'))
{
$a = $userlogin.split(":")
$username = $a[1]
}
# Create the new username based on the given input
$newalias = $newprovider + "\" + $username
if (-not $convert)
{
$answer = Read-Host "Your first user will be changed from $userlogin to $newalias. Would you like to continue processing all users? [Y]es, [N]o"
switch ($answer)
{
"Y" {$convert = $true}
"y" {$convert = $true}
default {exit}
}
}
if(($userlogin -like "$oldprovider*") -and $convert)
{
LogWrite ("Migrating User old : " + $user + " New user : " + $newalias + " ")
move-spuser -identity $user -newalias $newalias -ignoresid -Confirm:$false
LogWrite ("Done")
}
}
}
catch {
LogWrite ("Caught the exception")
LogWrite ($Error[0].Exception)
}
You use try {...} catch {...} when you want to handle errors. If you want to ignore them, you should set $ErrorActionPreference = "Continue" (or "SilentlyContinue") as #C.B. suggested, or use -ErrorAction "SilentlyContinue" for the particular operation raising the error. If you want to handle errors from a certain instruction, you'd put that instruction in the try {...} catch {...} block, not the entire loop, e.g.:
foreach($user in $users) {
...
try {
if(($userlogin -like "$oldprovider*") -and $convert) {
LogWrite ("Migrating User old : " + $user + " New user : " + $newalias + " ")
move-spuser -identity $user -newalias $newalias -ignoresid -Confirm:$false
LogWrite ("Done")
}
} catch {
LogWrite ("Caught the exception")
LogWrite ($Error[0].Exception)
}
}
You seem to have placed the "catch" outside the loop body, so that aborts the loop. Put the catch inside the loop
Modified the code as below. Used the following piece of code after move-spuser -identity $user -newalias $newalias -ignoresid -Confirm:$false
if($?)
{
LogWrite ("Done!")
LogWrite (" ")
}
else
{
LogWrite ($Error[0].ToString())
LogWrite (" ")
}
Something that worked for me is to set the $ErrorActionPreference variable to stop, and then reset it back to continue in the catch block:
$e = $ErrorActionPreference
$ErrorActionPreference="stop"
try
{
#Do Something that throws the exception
}
catch
{
$ErrorActionPreference=$e
}
$ErrorActionPreference=$e;