Unable to close down called PowerShell window on completion - powershell

I have a VBScript that runs a PowerShell script. The PowerShell script completes, but it just shows a black window that does not close and go back to the VBScript. If I close the black window the script continues. The PowerShell script itself does run and exit if ran on its own. Here is the my VBScript that executes the PowerShell script:
Set objFSO = CreateObject("Scripting.FileSystemObject")
strUSer = InputBox("Enter the username you wish to test the object for. if there is more than one please put a space between each.")
UserArray = Split(strUser)
For Each x In UserArray
strMessage = strMessage & x & vbCrLf
Next
Set objTextFile = objFSO.CreateTextFile("C:\scripts\UserTest.txt", True)
objTextFile.Write (strMessage)
objTextFile.Close
Set objTextFile = Nothing
WScript.Sleep 2000
Set objShell = CreateObject("WScript.Shell")
strChatterCommand = "powershell.exe -ExecutionPolicy Bypass -NoLogo -File C:\scripts\User_Check.ps1"
Set RunChatter = objShell.Exec(strChatterCommand)
strText = ""
Do While Not RunChatter.StdOut.AtEndOfStream
strText = strText & RunChatter.StdOut.ReadLine() & vbCrLf
Loop
WScript.Echo strText
Set fso = Nothing
Set RunChatter = Nothing
WScript.Quit
Powershell script:
#Region Set Variables & Env
$SalesforceCsv = "\\some\path$\Platform_LiveExtract.csv"
$aOutput = #()
#EndRegion Set Variables & Env
#Region Functions
Function Install-ADcmdlets{
#Ensure Group Policy module is installed
if ((Get-Module | ? {$_.Name -eq "activedirectory"}) -eq $null){
$ErrorActionPreference = "stop"
Try{
import-module activedirectory
}Catch{
Write-Host "Please install the Active Directory powershell cmdlets. Exiting Script..."
exit
}
}
}
Function get-ChatterCsvDetails ($fCsv, $FedID){
$Return = ($fCsv | ? {$_.FEDERATIONIDENTIFIER -eq $FedID})
if (!($Return)){
Write-Host "No User Account found in Chatter..."
}else{
Write-Host "$FedID found in Chatter"
Write-Host (" - Chatter Account created: " + $Return.CREATEDDATE.subString(0,10))
Write-Host (" - Chatter Account last logon: " + $Return.LASTLOGINDATE.subString(0,10))
}
Return $Return
}
Function Pause-Script{
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit
}
Function Get-DomainFromDN ([string]$fDN){
[string]$fReturn = ""
[array]$fSplit = $fDN -split ",DC="
for([int]$i=1; $i -le ($fSplit.count -1); $i++){
$fReturn += ("." + $fSplit[$i])
}
return $fReturn.substring(1,($fReturn.length -1))
}
Function Check-ADObjectChatterReadiness ($fUser, $fCsv){
$fErrorsFound = $False
$fUserDomain = (Get-DomainFromDN $fUser.DistinguishedName)
Write-Host ("Checking object " + $fUserDomain + "\" + ($fUser.Samaccountname))
#Check Samid cases match FederationID
if ($fCsv){
If ($fUser.samaccountname -cne $fCsv.FEDERATIONIDENTIFIER){
Write-host ("ACTION: Users SamId is in the wrong case. Please change it to " + $fCsv.FEDERATIONIDENTIFIER)
$fErrorsFound = $True
}
}
#Check first Name not blank
if (!($fUser.GivenName)){
Write-host "ACTION: User's GivenName is blank"
$fErrorsFound = $True
}
#Check last name not blank
if (!($fUser.SN)){
Write-host "ACTION: User's Surname is blank"
$fErrorsFound = $True
}
#Check DisplayName is not blank
if (!($fUser.displayName)){
Write-host "ACTION: User's Display Name is blank"
$fErrorsFound = $True
}
#Check UPN is not blank
If (!($fUser.userprincipalName)){
Write-host "ACTION: User's UPN is blank"
$fErrorsFound = $True
}else{
#Check UPN for illegal characters
if ($fUser.userprincipalName.ToString().contains(" ")){
Write-host "ACTION: User's UPN contains a space"
$fErrorsFound = $True
}
}
#Check Email for space
if ($fUser.Mail){
if ($fUser.Mail.contains(" ")){
Write-host "ACTION: User's Email contains a space"
$fErrorsFound = $True
}
}
#Check User is in the correct OU
if ($fUserDomain -eq "bskyb.com"){
if ($fUser.DistinguishedName -notlike "*,OU=User Accounts,DC=bskyb,DC=com"){
write-host "ACTION: Bskyb User account is not in a supported OU"
$fErrorsFound = $True
}
}else{
if ($fUser.DistinguishedName -notlike "*,OU=User Accounts,DC=Ext,DC=bskyb,DC=com"){
write-host "ACTION: Ext User account is not in a supported OU"
$fErrorsFound = $True
}
}
#If chatter account doesn't exist, check user is a member of federation group
if (!($fCsv)){
if ($fUser.extensionattribute2)
{
write-host "ACTION: Clear the users ExtensionAttribute2 value.`nAttempting to clear attribute now..."
try{
Set-ADUser $fUser -clear Extensionattribute2 -Server $fUserDomain
Write-Host "ACTION: SUCCESS - Attribute value cleared... please get the user to retest."
}
catch{
Write-Host "ACTION: FAILED... please manually clear the attribute value."
}
$fErrorsFound = $True
}
}
else
{
if (!($fUser.extensionattribute2))
{
write-host "ACTION: Set the users ExtensionAttribute2 value.`nAttempting to set attribute now..."
try{
set-aduser $fUser -Add #{extensionAttribute2="ChatterUser"} -Server $fUserDomain
Write-Host "ACTION: SUCCESS - Attribute value set... please get the user to retest."
}
catch{
Write-Host "ACTION FAILED... please manually set the attribute value."
}
$fErrorsFound = $True
}
}
#Check account is enabled
If ($fUser.Enabled -eq $false){
write-host "ACTION: User account is disabled in Active Directory"
$fErrorsFound = $True
}
#Check account is not a member of Deactivated group
$fUser.MemberOf | % {
if ($_ -like "*APP-CHATTER-DEACTIVATED*"){
write-host "ACTION: User has been de-activated from Chatter. Please check with Chatter team."
$fErrorsFound = $True
}
}
#Check for errors
if ($fErrorsFound -eq $False){
Write-host "No issues found with Active Directory object"
}
}
Function Check-ChatterUser ($fCsv, $fSamid){
Write-Host `n"--------------------------------------------------"
Write-Host "------------ Checking account $fSamid ------------"
$fChatterIssues = ""
$fLdapFilter = ('(samaccountname=' + $fSamid + ')')
$fAdCmdletUser = (get-aduser -LDAPFilter $fLdapFilter -server bskyb.com:3268 -Properties givenName,sn,mail,displayName,memberof,ExtensionAttribute2)
if ($fAdCmdletUser){
# User/s found
$oChatterUser = get-ChatterCsvDetails $fCsv $_
if (($fAdCmdletUser.count) -and ($fAdCmdletUser.count -ge 2)){
# samid In both domains
$fAdCmdletUser | % {
Check-ADObjectChatterReadiness $_ $oChatterUser
}
}else{
# 1 User returned
Check-ADObjectChatterReadiness $fAdCmdletUser $oChatterUser
}
}else{
#No User found
Write-Host "No user with samaccoutname found in GC"
}
Write-Host "`n------ Complete ------"
}
#EndRegion Functions
#Region Main body
Install-ADcmdlets
$oCsv = Import-Csv $SalesforceCsv
If (!($Users)){
$users = get-content c:/scripts/ChatterUsers.txt
$array = $true
}
else
{
$Users = $User.trim()
}
$users | % {
Check-ChatterUser $oCsv $_
}
Do {
$Users = ""
If ($Users.trim() -eq ""){
exit #Script =$true
}else{
$users | % {
Check-ChatterUser $oCsv $_
}
}
}until(exit) #Script -eq $true)
#EndRegion Main body

have you looked at the command line parameters for powershell.exe?
Are you sure you don't have a '-noexit' parameter in your command line for powershell.exe?

So turns out this is a querk with the .Exec command. The solution is to run a wrapper script i created in order to resolve the issue.
VBScript
dim objFSO, objShell, StrChatterCommand,strText, objTextFile, strLine
set objFSO = CreateObject("Scripting.FileSystemObject")
Const fsoForWriting = 2
Dim strUser
dim UserArray
Dim strMessage
strUSer = InputBox("Enter the username you wish to test the chatter object for. if there is more than one please put a space between each.")
UserArray = Split(strUser)
for each x in UserArray
strMessage = strMessage & x & vbCrLf
next
Set objTextFile = objFSO.CreateTextFile("c:\scripts\ChatterUsers.txt", true)
objTextFile.Write (strMessage)
objTextFile.Close
Set objTextFile = Nothing
wscript.sleep 500
StrChatterCommand = "powershell.exe C:\Scripts\start_script.ps1"
Set objShell = CreateObject("WScript.Shell")
objShell.run strChatterCommand, 1, true
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile ("c:\scripts\OutputFile.txt", ForReading)
strText = ""
Do Until objTextFile.AtEndOfStream
strLine = objTextFile.Readline
strText = strText & strLine & VbCrLf
Loop
objTextFile.Close
wscript.echo strText
set objFSO = nothing
Set objShell = nothing
Set objTextFile = nothing
wscript.quit
1st powerhsell script:
powershell.exe c:\scripts\WSM_Check_Chatter.ps1 -ExecutionPolicy ByPass -NoLogo -File | Out-File c:\scripts\OutputFile.txt -Encoding ASCII -Width 50
2nd powershell script:
#Region Set Variables & Env
$SalesforceCsv = "\\some\path$\Platform_LiveExtract.csv"
$aOutput = #()
#EndRegion Set Variables & Env
#Region Functions
Function Install-ADcmdlets{
#Ensure Group Policy module is installed
if ((Get-Module | ? {$_.Name -eq "activedirectory"}) -eq $null){
$ErrorActionPreference = "stop"
Try{
import-module activedirectory
}Catch{
Write-Host "Please install the Active Directory powershell cmdlets. Exiting Script..."
exit
}
}
}
Function get-ChatterCsvDetails ($fCsv, $FedID){
$Return = ($fCsv | ? {$_.FEDERATIONIDENTIFIER -eq $FedID})
if (!($Return)){
Write-Host "No User Account found in Chatter..."
}else{
Write-Host "$FedID found in Chatter"
Write-Host (" - Chatter Account created: " + $Return.CREATEDDATE.subString(0,10))
Write-Host (" - Chatter Account last logon: " + $Return.LASTLOGINDATE.subString(0,10))
}
Return $Return
}
Function Pause-Script{
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit
}
Function Get-DomainFromDN ([string]$fDN){
[string]$fReturn = ""
[array]$fSplit = $fDN -split ",DC="
for([int]$i=1; $i -le ($fSplit.count -1); $i++){
$fReturn += ("." + $fSplit[$i])
}
return $fReturn.substring(1,($fReturn.length -1))
}
Function Check-ADObjectChatterReadiness ($fUser, $fCsv){
$fErrorsFound = $False
$fUserDomain = (Get-DomainFromDN $fUser.DistinguishedName)
Write-Host ("Checking object " + $fUserDomain + "\" + ($fUser.Samaccountname))
#Check Samid cases match FederationID
if ($fCsv){
If ($fUser.samaccountname -cne $fCsv.FEDERATIONIDENTIFIER){
Write-host ("ACTION: Users SamId is in the wrong case. Please change it to " + $fCsv.FEDERATIONIDENTIFIER)
$fErrorsFound = $True
}
}
#Check first Name not blank
if (!($fUser.GivenName)){
Write-host "ACTION: User's GivenName is blank"
$fErrorsFound = $True
}
#Check last name not blank
if (!($fUser.SN)){
Write-host "ACTION: User's Surname is blank"
$fErrorsFound = $True
}
#Check DisplayName is not blank
if (!($fUser.displayName)){
Write-host "ACTION: User's Display Name is blank"
$fErrorsFound = $True
}
#Check UPN is not blank
If (!($fUser.userprincipalName)){
Write-host "ACTION: User's UPN is blank"
$fErrorsFound = $True
}else{
#Check UPN for illegal characters
if ($fUser.userprincipalName.ToString().contains(" ")){
Write-host "ACTION: User's UPN contains a space"
$fErrorsFound = $True
}
}
#Check Email for space
if ($fUser.Mail){
if ($fUser.Mail.contains(" ")){
Write-host "ACTION: User's Email contains a space"
$fErrorsFound = $True
}
}
#Check User is in the correct OU
if ($fUserDomain -eq "bskyb.com"){
if ($fUser.DistinguishedName -notlike "*,OU=User Accounts,DC=bskyb,DC=com"){
write-host "ACTION: Bskyb User account is not in a supported OU"
$fErrorsFound = $True
}
}else{
if ($fUser.DistinguishedName -notlike "*,OU=User Accounts,DC=Ext,DC=bskyb,DC=com"){
write-host "ACTION: Ext User account is not in a supported OU"
$fErrorsFound = $True
}
}
#If chatter account doesn't exist, check user is a member of federation group
if (!($fCsv)){
if ($fUser.extensionattribute2)
{
write-host "ACTION: Clear the users ExtensionAttribute2 value.`nAttempting to clear attribute now..."
try{
Set-ADUser $fUser -clear Extensionattribute2 -Server $fUserDomain
Write-Host "ACTION: SUCCESS - Attribute value cleared... please get the user to retest."
}
catch{
Write-Host "ACTION: FAILED... please manually clear the attribute value."
}
$fErrorsFound = $True
}
}
else
{
if (!($fUser.extensionattribute2))
{
write-host "ACTION: Set the users ExtensionAttribute2 value.`nAttempting to set attribute now..."
try{
set-aduser $fUser -Add #{extensionAttribute2="ChatterUser"} -Server $fUserDomain
Write-Host "ACTION: SUCCESS - Attribute value set... please get the user to retest."
}
catch{
Write-Host "ACTION FAILED... please manually set the attribute value."
}
$fErrorsFound = $True
}
}
#Check account is enabled
If ($fUser.Enabled -eq $false){
write-host "ACTION: User account is disabled in Active Directory"
$fErrorsFound = $True
}
#Check account is not a member of Deactivated group
$fUser.MemberOf | % {
if ($_ -like "*APP-CHATTER-DEACTIVATED*"){
write-host "ACTION: User has been de-activated from Chatter. Please check with Chatter team."
$fErrorsFound = $True
}
}
#Check for errors
if ($fErrorsFound -eq $False){
Write-host "No issues found with Active Directory object"
}
}
Function Check-ChatterUser ($fCsv, $fSamid){
Write-Host `n"--------------------------------------------------"
Write-Host "------------ Checking account $fSamid ------------"
$fChatterIssues = ""
$fLdapFilter = ('(samaccountname=' + $fSamid + ')')
$fAdCmdletUser = (get-aduser -LDAPFilter $fLdapFilter -server bskyb.com:3268 -Properties givenName,sn,mail,displayName,memberof,ExtensionAttribute2)
if ($fAdCmdletUser){
# User/s found
$oChatterUser = get-ChatterCsvDetails $fCsv $_
if (($fAdCmdletUser.count) -and ($fAdCmdletUser.count -ge 2)){
# samid In both domains
$fAdCmdletUser | % {
Check-ADObjectChatterReadiness $_ $oChatterUser
}
}else{
# 1 User returned
Check-ADObjectChatterReadiness $fAdCmdletUser $oChatterUser
}
}else{
#No User found
Write-Host "No user with samaccoutname found in GC"
}
Write-Host "`n------ Complete ------"
}
#EndRegion Functions
#Region Main body
Install-ADcmdlets
$oCsv = Import-Csv $SalesforceCsv
If (!($Users)){
$users = get-content c:/scripts/ChatterUsers.txt
$array = $true
}
else
{
$Users = $User.trim()
}
$users | % {
Check-ChatterUser $oCsv $_
}
Do {
$Users = ""
If ($Users.trim() -eq ""){
exit #Script =$true
}else{
$users | % {
Check-ChatterUser $oCsv $_
}
}
}until(exit) #Script -eq $true)
#EndRegion Main body

You could always do a forced close using .NET in your powershell script.
Here's a couple of ways to cause that to happen:
[System.Environment]::Exit()
The above will cause the powershell.exe app to exit with a code of 0. There's a version of the Exit() method that accepts an integer parameter so you can exit with a specific exit code.
[System.Diagnostics.Process]::GetCurrentProcess().Kill()
This one is quite severe. It essentially calls TerminateProcess under the covers. No exit code, just immediate termination.

Related

How do I use a switch statement with while loop

I am trying to add a user to the Remote Desktop group using Powershell.
It seems it's not breaking the loop and doesn't execute further statements.
Can you please help me where the issue is:
$remote = ""
While($remote -ne "Y" ){
$remote = read-host "Do you need to add anyone to the Remote Desktop group (y/n)?"
Switch ($remote)
{
Y {
$remoteuser = ""
while ( ($remoteuser -eq "") -or ($UserExists -eq $false) )
{
$remoteuser = Read-Host "Enter the username that needs to be in the group"
Write-Host "User inputted $remoteuser"
sleep -Seconds 2
try {
Get-ADUser -Identity $remoteuser -Server <server-FQDN>
$UserExists = $true
Write-Host "$remoteuser found!"
sleep 5
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityResolutionException] {
Write-Host "User does not exist."
$UserExists = $false
}
catch {
Write-Host "Username is blank"
$UserExists = $false
}
}
}
N {Write-Host "No user accounts will be added to the Remote Desktop Users group. Restart your PC."}
default {Write-Host "Only Y/N are Valid responses"}
}
}
<further statements>

Setting variables based on value taken from CSV within a Foreach loop using an if else statement

I've created a script that takes new user data from a CSV file and connects to AzureAd and ExchangeOnline to create their AzureAD account, assigns them an Office license (not shown), and updates their Mailbox Office field.
CSV headers are Name, Department, OfficeLocation. The CSV used to contain a Domain and Company header. I removed those headers and added an if elseif statement to provide the logic to set those variables within the script. Prior to this addition, the script worked without any issues.
Now, the $company and $domain values are only updating for $main_offices and $corporate_offices Contoso and #contoso.com even when the OfficeLocation value is San Francisco or Austin and those values should be West/South Acme and west/south.acme.com.
Why are my $company and $domain values not being updated within the ForEach-Object loop as it iterates through the CSV? I confirmed that $company and $domain update properly when not reading in CSV data with ForEach-Object:
$new_users = Import-Csv -Path .\new-users.csv
...
$main_offices = 'New York','Los Angeles','Houston','Atlanta','Chicago'
$corporate_offices = 'Corporate Office (NY)','Corporate Office (LA)'
$west_office = 'San Francisco'
$south_office = 'Austin'
$new_users | ForEach-Object {
$first, $last = $_.Name.Split()
$mailnickname = $(($first.Substring(0,1) + $last).ToLower())
$password_profile = New-Object -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile
$password_profile.Password = 'XXXXXXXXXXXXXXXXXX'
$password_profile.ForceChangePasswordNextLogin = $false
$off_loc = $_.OfficeLocation
if ($off_loc -in $main_offices -or $corporate_offices) {
$company = 'Contoso'
$domain = '#contoso.com'
} elseif ($off_loc -eq $west_office) {
$company = 'West Acme'
$domain = '#west.acme.com'
} elseif ($off_loc -eq $south_office) {
$company = 'South Acme'
$domain = '#south.acme.com'
} else { $off_loc = Read-Host 'Type an office location' } #CSV OfficeLocation field either missing or has a spelling error
$attr_new_user = #{
AccountEnabled = $true
CompanyName = $company
Department = $_.Department
DisplayName = $_.Name
GivenName = $first
MailNickname = $mailnickname
PasswordProfile = $password_profile
Surname = $last
UsageLocation = 'US'
UserPrincipalName = $mailnickname + $domain
}
try {
Write-Host ('>> Creating account for ' + $attr_new_user.DisplayName) -ForegroundColor Yellow
New-AzureADUser #attr_new_user | Out-Null
$user_upn = Get-AzureADUser -ObjectId $attr_new_user.UserPrincipalName | Select-Object -ExpandProperty UserPrincipalName
Write-Host ('>> ' + $user_upn + ' has been created') -ForegroundColor Green
}
catch {
Write-Host ('>> Something went wrong') -ForegroundColor Red
Write-Warning $Error[0]
}
...
try {
Write-Host ('>> Adding email alias: ' + $alternate_email + ' and office: ' + $off_loc + ' to ' + $user_upn) -ForegroundColor Yellow
Set-Mailbox -Identity $user_upn -EmailAddresses #{ add = $alternate_email } -Office $off_loc
Write-Host ('>> Email Alias: ' + $alternate_email + ' and office: ' + $off_loc + ' added to ' + $user_upn) -ForegroundColor Green
}
catch {
Write-Host ('>> Something went wrong') -ForegroundColor Red
Write-Warning $Error[0]
}
I've run the script and the $off_loc value is being inputted correctly in the Office field of the Mailbox settings. Which is why I am having trouble understanding how to get this information to create the user with the correct the $company and $domain fields.
Any insight into a solution to this issue is appreciated, thank you for taking the time to answer my question.
Per Santiago Squarzon:
This condition $off_loc -in $main_offices -or $corporate_offices will
always be $true because $corporate_offices is not $null or empty
string. It should be $off_loc -in $main_offices -or $off_loc -in
$corporate_offices
Confirmed this resolved the issue.

Powershell - Azure licence based on ad group

I have been developing AzureAD licence script based on AD Group. So, Find users with a direct assigned, find them in AD, evaluate what group they should be a member of, add them to licensing group. I have hashtable with multiple values $SKUToGroupRev. I can not match hashtable with multiple values with if($ADGroup = $SKUToGroupRev[$SKU.SkuId]) .
From what I want to do :
if there are 18181a46-0d4e-45cd-891e-60aabd171b4e and 0c266dff-15dd-4b49-8397-2bb16070ed52 inside SKUs variable for below command then I will add AD group related to the inside hashtable such as O365_E1_Users
OR
if there are 6fd2c87f-b296-42f0-b197-1e91e994b900 and 0c266dff-15dd-4b49-8397-2bb16070ed52 inside SKUs variable for below command then I will add AD group related to the inside hashtable such as O365_E3_Users
e.g:
# Get licensed SKUs for the user
$aaduser = get-azureaduser -objectID $user.UserPrincipalName
$SKUs = $aaduser | Select UserPrincipalName,ImmutableID -ExpandProperty AssignedLicenses
e.g output:
UserPrincipalName ImmutableId DisabledPlans SKUId
----------------- ----------- ------------- -------------
User01#contoso.com x+MVG6EKEUWHi3r6zjgzCA== {041fe683-03e4-45b6-b1af-c0cdc516da4f... 6fd2c87f-b296-42f0-b197-1e91e994b900
User01#contoso.com x+MVG6EKEUWHi3r6zjgzCA== {} 0c266dff-15dd-4b49-8397-2bb16070ed52
Here is my script :
$CSVfile = "C:\temp\LicenseToGroupUsers.csv"
# Import the CSV file
try {
$users = import-csv $CSVfile
}
catch {
$errorZero = $Error[0]
write-host "Error: " $errorZero -ForegroundColor Red #Writes the latest error
Break
}
write-warning "About to add the following users to license groups for complete SKU:"
foreach ($user in $users){
write-host $user.UserPrincipalName
}
Read-Host -Prompt "Press Enter to continue or CTRL+C to quit"
$e3 = -split "0c266dff-15dd-4b49-8397-2bb16070ed52 6fd2c87f-b296-42f0-b197-1e91e994b900"
$e1 = -split "18181a46-0d4e-45cd-891e-60aabd171b4e 0c266dff-15dd-4b49-8397-2bb16070ed52"
$TEAMS_EXPLORATORY = -split "710779e8-3d4a-4c88-adb9-386c958d1fdf 0c266dff-15dd-4b49-8397-2bb16070ed52"
#$FLOW_FREE_E3 = -split "f30db892-07e9-47e9-837c-80727f46fd3d 6fd2c87f-b296-42f0-b197-1e91e994b900 0c266dff-15dd-4b49-8397-2bb16070ed52"
foreach ($user in $users){
$groupsToAdd = #()
$groupsToRemove = #()
write-host "Processing" $user.UserPrincipalName
# Get licensed SKUs for the user
$aaduser = get-azureaduser -objectID $user.UserPrincipalName
#$SKUs = $aaduser | Select UserPrincipalName,ImmutableID -ExpandProperty AssignedLicenses
#Get the AD ObjectGuid for the group add (cannot use UPN)
$ImmutableID = "" #Null these out otherwise gets reused from previous
#Have to match using the guid
$ImmutableID = $aaduser.ImmutableID
if ($ImmutableID) {$objectGUID = ([GUID][System.Convert]::FromBase64String($ImmutableID)).Guid}
else {
write-warning "Error getting ImmutableID for $UPN, user is likely cloud only, skipping"
Break
}
# test 1
$licenses = $aaduser.AssignedLicenses.SkuId
$is_e1 = !($e1 | ForEach-Object { $licenses.Contains($_) }).Contains($false)
if($is_e1 -eq "True"){
try {
write-host "Adding" $user.UserPrincipalName"to E1Group" -ForegroundColor Green
Write-Host "Test 1: $is_e1"
}
catch {
$errorZero = $Error[0]
write-host "Error: " $errorZero -ForegroundColor Red #Writes the latest error
}
}
$is_e3 = !($e3 | ForEach-Object { $licenses.Contains($_) }).Contains($false)
if($is_e3 -eq "True"){
try {
write-host "Adding" $user.UserPrincipalName"to E3Group" -ForegroundColor Green
Write-Host "Test 3: $is_e3"
}
catch {
$errorZero = $Error[0]
write-host "Error: " $errorZero -ForegroundColor Red #Writes the latest error
}
}
$is_TEAMS_EXPLORATORY = !($TEAMS_EXPLORATORY | ForEach-Object { $licenses.Contains($_) }).Contains($false)
if($is_TEAMS_EXPLORATORY -eq "True"){
try {
write-host "Adding" $user.UserPrincipalName"to (TEAMS_EXPLORATORY)E1Group" -ForegroundColor Green
Write-Host "Test 1: $is_TEAMS_EXPLORATORY"
}
catch {
$errorZero = $Error[0]
write-host "Error: " $errorZero -ForegroundColor Red #Writes the latest error
}
}
<# $is_FLOW_FREE_E3 = !($FLOW_FREE_E3 | ForEach-Object { $licenses.Contains($_) }).Contains($false)
if($is_FLOW_FREE_E3 -eq "True"){
try {
write-host "Adding" $user.UserPrincipalName"to (FLOWFREE)E3Group" -ForegroundColor Green
Write-Host "Test 1: $is_FLOW_FREE_E3"
}
catch {
$errorZero = $Error[0]
write-host "Error: " $errorZero -ForegroundColor Red #Writes the latest error
}
}#>
}
To test agains a combination of SkuID's, using a lookup hashtable as in your first approach is not the easiest way I think. Your current approach looks much better to me, only I would not put the ID's in array variables, but test them literally against the ID's as they are found in the users AssignedLicenses.
Something like this:
$CSVfile = "C:\temp\LicenseToGroupUsers.csv"
# Import the CSV file
$users = Import-Csv -Path $CSVfile
Write-Warning "About to add the following users to license groups for complete SKU:"
$users.UserPrincipalName -join [environment]::NewLine
Write-Host
$answer = Read-Host -Prompt "Press Enter to continue or Q to quit"
if ($answer[0] -eq 'Q') { Clear-Host; exit }
foreach ($user in $users) {
Write-Host "Processing" $user.UserPrincipalName
$ImmutableID = $null # Null these out
$ADGroup = $null
# Get licensed SKUs for the user
$aaduser = Get-AzureADUser -objectID $user.UserPrincipalName
# Get the AD ObjectGuid for the group add (cannot use UPN)
# Have to match using the guid
$ImmutableID = $aaduser.ImmutableID
if (![string]::IsNullOrWhiteSpace($ImmutableID)) {
$objectGUID = ([GUID][System.Convert]::FromBase64String($ImmutableID)).Guid}
else {
Write-Warning "Error getting ImmutableID for $($user.UserPrincipalName), user is likely cloud only, skipping"
continue # skip this one and proceed with the next user
}
$licenses = #($aaduser.AssignedLicenses.SkuId) # force it to be an array
##########################################################################################
# Apparently, SkuId '0c266dff-15dd-4b49-8397-2bb16070ed52' is needed for all combinations,
# so we could already rule out users that do not have that ID in their $licenses..
# if that is indeed the case, you can simplify al other tests by not having to check
# for this ID every time..
# for now, this is an assumption, so commented out.
# if (!($licenses -contains '0c266dff-15dd-4b49-8397-2bb16070ed52')) {
# Write-Warning "Could not determine a group for user $($user.UserPrincipalName)"
# continue # skip this one and proceed with the next user
# }
##########################################################################################
# test E1: 'Microsoft 365 Audio Conferencing' and 'OFFICE 365 E1'
if ($licenses -contains '0c266dff-15dd-4b49-8397-2bb16070ed52' -and
$licenses -contains '18181a46-0d4e-45cd-891e-60aabd171b4e') {
# Add this user to group 'O365_E1_Users'
$ADGroup = 'O365_E1_Users'
}
# test E3: 'Microsoft 365 Audio Conferencing' and 'OFFICE 365 E3'
elseif ($licenses -contains '0c266dff-15dd-4b49-8397-2bb16070ed52' -and
$licenses -contains '6fd2c87f-b296-42f0-b197-1e91e994b900') {
if ($licenses -contains 'f30db892-07e9-47e9-837c-80727f46fd3d') { # also 'MICROSOFT FLOW FREE' ?
# Add this user to group 'FLOW_FREE_E3'
$ADGroup = 'FLOW_FREE_E3'
}
else {
# Add this user to group 'O365_E3_Users'
$ADGroup = 'O365_E3_Users'
}
}
# test 'Microsoft 365 Audio Conferencing' and 'MICROSOFT TEAMS EXPLORATORY'
elseif ($licenses -contains '0c266dff-15dd-4b49-8397-2bb16070ed52' -and
$licenses -contains '710779e8-3d4a-4c88-adb9-386c958d1fdf') {
# Add this user to group 'TEAMS_EXPLORATORY'
$ADGroup = 'TEAMS_EXPLORATORY'
}
# finished the conditions, now see if we can add the user to one of the groups
if (![string]::IsNullOrWhiteSpace($ADGroup)) {
try {
Write-Host "Adding $($user.UserPrincipalName) to $ADGroup" -ForegroundColor Green
# Add-ADGroupMember -Identity $ADGroup -Members $objectGUID
}
catch {
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
else {
Write-Warning "Could not determine a group for user $($user.UserPrincipalName)"
}
}

Delete local administrator account with delete() method ADSI with Powershell

I am writing a powershell script to manage our local administrator accounts using a csv file.
#variable to store the data in data.csv
$userobjects = Import-CSV C:-data.csv
function main-list{
Write-Host "--------------------------------------"
Write-Host "Windows Powershell Account Manager"
Write-Host "--------------------------------------"
Write-Host "1 - Change Name"
Write-Host "2 - Disabled Account"
Write-Host "3 - Delete User"
Write-Host "4 - Exit"
[int]$action = Read-Host "Enter the menu number from above"
if ($action -eq 1){change-name}
if ($action -eq 2){disable-account}
if ($action -eq 3){delete-user}
if ($action -eq 4){cls; break}
}
function change-name
{
foreach ($user in $userobjects)
{
#Assign the content to variables
$FileHostname = $user.Host
$FileAccount = $user.Account
$FileNewname = $user.Rename
$FileDisable = $user.Disable
$FileDelete = $user.Delete
# Rename
if (($user.Account -ne $user.Rename) -and ($user.Rename -ne '' ))
{
#Write-Host "old name :"$FileHostname"/"$FileAccount "-> new name :"$FileHostname"/"$FileNewname
$connection = $FileHostname+"/"+$FileAccount
$accName = [ADSI]("WinNT://$connection")
if ($accName.path -eq "WinNT://"+$connection+"")
{
$accName.psbase.Rename($FileNewname)
Write-Host "Account(s) renamed"
$user.Account = $user.Rename
}
else
{
Write-Host "Account name :"$connection "can't be found on the host"
}
$user.Account = $user.Rename
$userobjects | export-csv C:-data.csv -notype
}
}
Write-Host "--------------------------------------"
main-list
}
function disable-account
{
foreach ($user in $userobjects)
{
#Assign the content to variables
$FileHostname = $user.Host
$FileAccount = $user.Account
$FileNewname = $user.Rename
$FileDisable = $user.Disable
$FileDelete = $user.Delete
if ($user.Disable -eq 'yes')
{
$connection = $FileHostname+"/"+$FileAccount
$accName = [ADSI]("WinNT://"+$connection+"")
if ($accName.UserFlags -eq '515')
{
Write-Host "Account :"$connection "is already disabled"
}
else
{
$accName.description = "Account disabled"
$accName.UserFlags = 2
$accName.setinfo()
Write-Host "Account(s) disabled"$connection
}
}
}
Write-Host "--------------------------------------"
main-list
}
function delete-user
{
foreach ($user in $userobjects)
{
#Assign the content to variables
$FileHostname = $user.Host
$FileAccount = $user.Account
$FileNewname = $user.Rename
$FileDisable = $user.Disable
$FileDelete = $user.Delete
#Delete
if ($user.Delete -eq 'yes')
{
$connection = $FileHostname+"/"+$FileAccount
$accName = [ADSI]("WinNT://"+$connection+"")
$accName.delete("user",$accName.name)
#Write-Host $connection deleted
}
else
{
Write-Host "Account name :"$connection "can't be found on the host"
}
}
}
}
$userobjects | export-csv C:-\data.csv -notype
main-list
I don't really know why I have this message when I am trying to use the delete function : "Unknown name", it is like it doesn't find the local account to delete it but I am not sure. However, It works perfectly when I want to rename or disable accounts.
My data file looks like that
http://www.noelshack.com/2016-05-1454622367-capture.png
I will post the real message when I will be back to work tomorow.
Thank you for your help.
Quick skim... wouldn't this need to be used instead? I think your $accName.name would be using the machine name.
$accName.delete("user",$user.account)
You delete() the user from the computer, so your [adsi] object should bind to the computer and call Delete() on that instead:
# Just the machine name, nothing more:
$Machine = [ADSI]"WinNT://$FileHostname"
# Now delete the user account from the machine
$Machine.Delete('user',$FileAccount)

Powershell - Generating username for Active Directory

I'm trying to create a script that creates a unique user I Active Directory.
Before the script can create a user it needs to make sure the username is available by asking two different domains if the generated username exists. The problem is I don't how generate a new username or rerun part of the script if necessary. Lets say that if the generated username exists in one of the domains I wan't to generate a new username and try again with the new one. This is what I have so far.
Import-Module ActiveDirectory
$firstname = "Test"
$lastname = "Tester"
$SecondaryDomain = "server1.domain1.net"
$PrimaryDomain = "server2.domain2.net"
$ErrorActionPreference = "SilentlyContinue"
$Generate = [Char[]]"$firstname$lastname"
$Generatedusername = ($Generate | Get-random -Count 3) -join ""
Write-host $Generatedusername
if (Get-ADUser -Filter {SamAccountName -eq $Generatedusername} -Server $PrimaryDomain)
{
#If the variable equals 1 the user exists
$PrimaryDomainOK = "1"
}
else
{
$PrimaryDomainOK = "0"
}
if (Get-ADUser -Filter {SamAccountName -eq $Generatedusername} -Server $SecondaryDomain)
{
#If the variable equals 1 the user exists
$SecondaryDomainOK = "1"
}
else
{
$SecondaryDomainOK = "0"
}
Write-host "Primary Domain $PrimaryDomainOK"
Write-host "Secondary Domain $SecondaryDomainOK"
If ($PrimaryDomainOK -and $SecondaryDomainOK -eq 0)
{
Write-host "Creating Account"
}
Else
{
Write-host "Can't create account"
}
Add a while statement embracing your generation/verification which checks for the status of $PrimaryDomainOK and $SecondaryDomainOK.
...
$Generate = [Char[]]"$firstname$lastname"
while(($PrimaryDomainOK -ne 0) -and ($SecondaryDomainOK -ne 0)) {
$Generatedusername = ($Generate | Get-random -Count 3) -join ""
Write-host $Generatedusername
...
...
...
If ($PrimaryDomainOK -and $SecondaryDomainOK -eq 0)
{
Write-host "Creating Account"
}
Else
{
Write-host "Can't create account"
}
}
Remember the closing brace.