I am writing a script to quickly create a new distribution group and populate it with a CSV. I am having trouble testing to see if the group name already exists.
If I do a get-distributiongroup -id $NewGroupName and it does not exist I get an exception, which is what I expect to happen. If the group does exist then it lists the group, which is also what I expect. However, I can not find a good way to test if the group exists before I try to create it. I have tried using a try/catch, and also doing this:
Get-DistributionGroup -id $NewGroupName -ErrorAction "Stop"
which makes the try/catch work better (as I understand non-terminating errors).
Basically, I need to have the user enter a new group name to check if it is viable. If so, then the group gets created, if not it should prompt the user to enter another name.
You can use SilentlyContinue erroraction so that no exception/error shows:
$done = $false
while(-not $done)
{
$newGroupName = Read-Host "Enter group name"
$existingGroup = Get-DistributionGroup -Id $newGroupName -ErrorAction 'SilentlyContinue'
if(-not $existingGroup)
{
# create distribution group here
$done = $true
}
else
{
Write-Host "Group already exists"
}
}
This should do the trick:
((Get-DistributionGroup $NewGroupName -ErrorAction 'SilentlyContinue').IsValid) -eq $true
Related
In this script, I am trying to make a group (if not exist) and add users thats are not already in the group.
But the problem is he only takes the first if statement I think, because it don't seems like he is taking the next statements in the loop.
#Tweede test met if
$teams = #Here comes the csv file.
Foreach($team in $teams)
{
$Test = (Get-UnifiedGroup $team.DisplayName)
if (Get-UnifiedGroup $team.DisplayName)
{
Write-Host -ForegroundColor Green "$($team.Displayname) already exists!"
}
elseif ($Test -eq "false")
{
$Group = New-UnifiedGroup -DisplayName $team.DisplayName -Alias $team.Alias -AccessType $team.AccessType
}
foreach($Member in $Members)
{
elseif (get-UnifiedgroepLinks $team.Links)
{
write-host -ForegroundColor Green "$($team.Links) already exists!"
}
else
{
Add-UnifiedGroupLinks -Identity $team.Identity -LinkType $team.Linktype -Links $team.Links
}
}}
OK so this is my current output form #Theo last improvement
Output
OK I have something very interesting, because when I looked at the output of
$existingMembers = #((Get-UnifiedGroupLinks -Identity $Group.DistinguishedName -LinkType Members).PrimarySMTPAddress)
I will get certain blank spots. And when I ran the script for one user it was working but for another one it did not, so I looked at the user that did not worked, and he does not have a license. So I tested it further. And in my conclusion now it's working. So when an acc is unlicensed, it is not seen like he is added to that specific group. So he is also throwing the second if statement, but also the second else statement.
Does this make sense to you #Theo?
### script name: Users_Verwijderen ###
### Datum updated: 14-12-2022 ###
### Auteur: Wessel Rouw ###
### Purpose script is to add groups and users in to groups in Azure. ###
#######################################################################
$teams = import-csv #Here your CSV
foreach($team in $teams) {
$team | Format-Table
$Check = (Get-UnifiedgroupLinks -Identity $team.Identity -LinkType $team.Linktype)
$existingMembers = #((Get-UnifiedGroupLinks -Identity $Group.DistinguishedName -LinkType Members).PrimarySMTPAddress)
$Group = (Get-UnifiedGroup $team.DisplayName)
if ($Group)
{
Write-Host "$($team.Displayname) already exists!" -ForegroundColor Green
}
else
{
Write-Host "Creating group $($team.Displayname)"
$Group = New-UnifiedGroup -DisplayName $team.DisplayName -Alias $team.Alias -AccessType $team.AccessType
}
if ($existingMembers -contains $team.Links)
{
Write-Host "$($team.Links) already exists!" -ForegroundColor Green
}
else
{
Write-Host "Creating group Links $($team.Links)"
Add-UnifiedGroupLinks -Identity $team.Identity -LinkType $team.Linktype -Links $team.Links
}
}
This is now my current script working with help from #Theo (Only, users that are not licensed will get the message that they are added even if they are already in the group).
Here is my input now in my csv.
I have changed username (Links) and the domain name (After the Test101 and the users (Links).
DisplayName,Alias,AccessType,Identity,Linktype,Links
Test101,Test101,private,Test101#domain.nl,Member,Hek_Sme#Domain.nl
Test101,Test101,private,Test101#domain.nl,Member,Mek_Lei#Domain.nl
Test101,Test101,private,Test101#domain.nl,Member,Wek_Bog#Domain.nl
This is another very helpful output. again same story as above with the changed domain and usernames.
Name DisplayName GroupType PrimarySmtpA
ddress
---- ----------- --------- ------------
Test101_(**Here comes a private number)** Test101 Universal Test101#1...
PS C:\WINDOWS\system32> $existingMembers
**Here comes the domain admin**
Hek_Sme#Domain.nl
Gek_Wel#Domain.nl
Gek_Wel#Domain.nl
Dir_Bog#Domain.nl
Wek_Bog#Domain.nl
PS C:\WINDOWS\system32> $inputMembers
Mek_Lei#Domain.nl
PS C:\WINDOWS\system32>
And as you can see some fields are empty and that are exactly the two users who don't own a licence and when I then run the command to get everyone who is not presenting in the get commando of users for that group it is specified to that users again.
I only don't know why this and if my thought is right?
Oke, so thanks already for the help. Now it works better. But in the second part I want to verify that if a user already exists in azure it displays the message, but if don't it has to be added? But this is now the problem.
This is now the output of my running script
VERBOSE: Returning precomputed version info: 3.0.0
VERBOSE: POST with -1-byte payload
VERBOSE: received 2945-byte response of content type application/json;charset=utf-8
VERBOSE: Returning precomputed version info: 3.0.0
VERBOSE: POST with -1-byte payload
VERBOSE: received 2906-byte response of content type application/json;charset=utf-8
Test105 already exists!
Creating group Links #Here stand the email (Links)
VERBOSE: Returning precomputed version info: 3.0.0
VERBOSE: POST with -1-byte payload
VERBOSE: received 386-byte response of content type application/json;charset=utf-8
The problem is when a user already exist it does not goes to the line that says that it already exits but instead it skips this part i think and goed directy to the else statement.
I think I am pretty close now.
`$teams = import-csv #CSV here
{
#$team | Format-Table #This was voor debugging
$Check = (Get-UnifiedgroupLinks -Identity $team.Identity -LinkType $team.Linktype)
$Group = (Get-UnifiedGroup $team.DisplayName)
if ($Group)
{
Write-Host "$($team.Displayname) already exists!" -ForegroundColor Green
}
else
{
Write-Host "Creating group $($team.Displayname)"
$Group = New-UnifiedGroup -DisplayName $team.DisplayName -Alias $team.Alias -AccessType $team.AccessType
}
if ($Check -contains $team.Links)
{
Write-Host "$($team.Links) already exists!" -ForegroundColor Green
}
else
{
Write-Host "Creating group Links $($team.Links)"
Add-UnifiedGroupLinks -Identity $team.Identity -LinkType $team.Linktype -Links $team.Links
}
}`
These are the columns of my csv.
I am building a PowerShell script to create AD Groups (Global and DomainLocal) by Importing their names from a Csv file.
I am having a hard time handling exceptions that will be generated in case Groups already exist.
What I want to achieve is if the Groups do not exist by the name in Csv then PS should create them and show message "Groups have been created" and if they already exist then it should display "Groups already exist" line by line so that if one exists and the other one doesn't then it should display the corresponding message.
What is happening is that PS doesn't display a message when it has created groups and when exception does occur it displays message only for Global Group not Local.
Please advise
Here's the code -
Try {
New-ADGroup -Name TestGlobal -GroupCategory Security -GroupScope Global -ManagedBy TEMP01 -Description "Owner is TEMP01" -Path (Some OU)
} Catch [Microsoft.ActiveDirectory.Management.ADException] {
if ($_ -like "The specified group already exists") {
Write-Host “!!! GLOBAL GROUP ALREADY EXISTS !!!”
} elseif ($_ -eq $null) {
Write-Host " GLOBAL GROUP CREATED SUCCESSFULLY "
}
}
Try {
New-ADGroup -Name TestLocal -GroupCategory Security -GroupScope DomainLocal -ManagedBy TEMP02 -Description "Owner is TEMP02" -Path (Some OU)
} Catch [Microsoft.ActiveDirectory.Management.ADException] {
if ($_ -like "The specified group already exists") {
Write-Host “!!! LOCAL GROUP ALREADY EXISTS !!!”
} elseif ($_ -eq $null) {
Write-Host " LOCAL GROUP CREATED SUCCESSFULLY "
}
}
PowerShell is a bit strange in that, by default, errors are non-terminating. That means that errors will be output to the console, but it will just continue on to the next line of code as if nothing happened.
Unfortunately, Try blocks only respond to terminating errors.
You can change this behaviour. On both of your New-ADGroup lines, add this to the end:
-ErrorAction Stop
That will tell PowerShell that you want it to treat errors on that line as terminating.
If you want, you can do some more reading about it here:
https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/09/handling-errors-the-powershell-way/
https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/05/weekend-scripter-using-try-catch-finally-blocks-for-powershell-error-handling/
A bit of context, I am trying to get a list of users from a security group, then check if any of those users do not have an assigned XenDesktop.
Please forgive me, I only started using Powershell yesterday so my formatting is off. It first grabs the users from the AD group then checks if that user has an assigned desktop, which works but I what I can't seem to get working is that if the user is found in that list, I want it to move onto the next username, instead it continues to check against every machine and then onto the final bits of code.
$checkusernames = Get-ADGroupMember "***AD security Group***" | Select SamAccountName
$desktops = get-brokerdesktop -DesktopGroupName Personal_WIN8 | Select MachineName, #{Name='AssociatedUserNames';Expression={[string]::join(“;”, ($_.AssociatedUserNames))}}
foreach ($username in $checkusernames.SamAccountName) {
foreach ($desktop in $desktops) {
If ($desktop.AssociatedUserNames -like "*$username*") {
write-host $username "is assigned to" $desktop.machinename
}
write-host $username "is not assigned to a desktop"
}
Write-host $username "is not assigned to anything"
pause
}
If you want to exit from a ForEach loop early you can do so with the Break keyword. For example:
$checkusernames = Get-ADGroupMember "***AD security Group***" | Select SamAccountName
$desktops = get-brokerdesktop -DesktopGroupName Personal_WIN8 | Select MachineName, #{Name='AssociatedUserNames';Expression={[string]::join(“;”, ($_.AssociatedUserNames))}}
foreach ($username in $checkusernames.SamAccountName) {
$machine = ''
foreach ($desktop in $desktops) {
If ($desktop.AssociatedUserNames -like "*$username*") {
$machine = $desktop.machinename
break
}
}
If ($machine) {
write-host $username "is assigned to" $desktop.machinename
} Else {
write-host $username "is not assigned to a desktop"
pause
}
}
This will stop the current cycle of the inner ForEach loop (once it has completed in it's entirety) without interrupting the ongoing cycle of the outer one.
Per the dicussion in the comments, i've also reorganised the code so that you only get a single output dependent on whether a desktop is matched to a user or not and it only pauses if it does not find a match.
I have a powershell script that adds a computer to a domain. Sometimes, when I run the script I get the following error and when I run it for the second time it works.
How can I make the script to check if I get this error, and if so then to retry adding it to the domain?
I have read that it is hard to try and catch errors like that. Is that correct? Is there a better/different way to catch the error?
Thank you!
Code:
if ($localIpAddress -eq $newIP)
{ # Add the computer to the domain
write-host "Adding computer to my-domain.local.. "
Add-Computer -DomainName my-domain.local | out-null
} else {...}
Error:
This command cannot be executed on target computer('computer-name') due to following error: The specified domain either does not exist or could not be contacted.
You can use the built in $Error variable. Clear it before executing code, then test if the count is gt 0 for post error code.
$Error.Clear()
Add-Computer -DomainName my-domain.local | out-null
if($Error.count -gt 0){
Start-Sleep -seconds 5
Add-Computer -DomainName my-domain.local | out-null}
}
You could setup a function to call itself on the Catch. Something like:
function Add-ComputerToAD{
Param([String]$Domain="my-domain.local")
Try{
Add-Computer -DomainName $Domain | out-null
}
Catch{
Add-ComputerToAD
}
}
if ($localIpAddress -eq $newIP)
{ # Add the computer to the domain
write-host "Adding computer to my-domain.local.. "
Add-ComputerToAD
} else {...}
I haven't tried it to be honest, but I don't see why it wouldn't work. It is not specific to that error, so it'll infinitely loop on repeating errors (i.e. another computer with the same name exists in AD already, or you specify an invalid domain name).
Otherwise you could use a While loop. Something like
if ($localIpAddress -eq $newIP)
{ # Add the computer to the domain
write-host "Adding computer to my-domain.local.. "
While($Error[0].Exception -match "The specified domain either does not exist or could not be contacted"){
Add-Computer -DomainName my-domain.local | out-null
}
}
I am trying to create local user on all servers and I want to schedule this as a scheduled task so that it can run continually capturing all new servers that are created.
I want to be able to check for the existence of an account and if true, skip; if false, create account.
I have imported a module called getlocalAccount.psm1 which allows me to return all local accounts on the server and another function called Add-LocaluserAccount
which allows me to add local accounts these work with no problems
when I try and run the script I have created the script runs but does not add accounts
Import-Module "H:\powershell scripts\GetLocalAccount.psm1"
Function Add-LocalUserAccount{
[CmdletBinding()]
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName=$env:computername,
[parameter(Mandatory=$true)]
[string]$UserName,
[parameter(Mandatory=$true)]
[string]$Password,
[switch]$PasswordNeverExpires,
[string]$Description
)
foreach ($comp in $ComputerName){
[ADSI]$server="WinNT://$comp"
$user=$server.Create("User",$UserName)
$user.SetPassword($Password)
if ($Description){
$user.Put("Description",$Description)
}
if ($PasswordNeverExpires){
$flag=$User.UserFlags.value -bor 0x10000
$user.put("userflags",$flag)
}
$user.SetInfo()
}
}
$usr = "icec"
$rand = New-Object System.Random
$computers = "ServerA.","ServerB","Serverc","ServerD","ServerE"
Foreach ($Comp in $Computers){
if (Test-Connection -CN $comp -Count 1 -BufferSize 16 -Quiet){
$admin = $usr + [char]$rand.next(97,122) + [char]$rand.next(97,122) + [char]$rand.next(97,122) + [char]$rand.next(97,122)
Get-OSCLocalAccount -ComputerName $comp | select-Object {$_.name -like "icec*"}
if ($_.name -eq $false) {
Add-LocalUserAccount -ComputerName $comp -username $admin -Password "password" -PasswordNeverExpires
}
Write-Output "$comp online $admin"
} Else {
Write-Output "$comp Offline"
}
}
Why bother checking? You can't create an account that already exists; you will receive an error. And with the ubiquitous -ErrorAction parameter, you can determine how that ought to be dealt with, such as having the script Continue. Going beyond that, you can use a try-catch block to gracefully handle those exceptions and provide better output/logging options.
Regarding your specific script, please provide the actual error you receive. If it returns no error but performs no action check the following:
Event Logs on the target computer
Results of -Verbose or -Debug output from the cmdlets you employ in your script
ProcMon or so to see what system calls, if any, happen.
On a sidenote, please do not tag your post with v2 and v3. If you need a v2 compatible answer, then tag it with v2. Piling on all the tags with the word "powershell" in them will not get the question answered faster or more effectively.
You can do a quick check for a local account like so:
Get-WmiObject Win32_UserAccount -Filter "LocalAccount='true' and Name='Administrator'"
If they already exist, you can either output an error (Write-Error "User $UserName Already exists"), write a warning (Write-Warning "User $UserName Already exists"), or simply silently skip the option.
Please don't use -ErrorAction SilentlyContinue. Ever. It will hide future bugs and frustrate you when you go looking for them.
This can very easily be done in one line:
Get-LocalUser 'username'
Therefore, to do it as an if statement:
if((Get-LocalUser 'username').Enabled) { # do something }
If you're not sure what the local users are, you can list all of them:
Get-LocalUser *
If the user is not in that list, then the user is not a local user and you probably need to look somewhere else (e.g. Local Groups / AD Users / AD Groups
There are similar commands for looking those up, but I will not outline them here