PowerShell Script: Modify Users (HomeDirectory) - windows

I'm doing a virtual machine test, I have the following dilemma.
I want to modify a field to users who have HomeDirectory configured, for a new DFS path.
I have this script I does not work:
$user = Get-ADUser -Filter {HomeDirectory -like '*'} -Properties HomeDirectory | Select-Object samaccountname
Set-ADUser -Identity $user -Replace #{homeDirectory="\\\mboulaayoun.com\comu\personals\$user"}

Hi guys finnaly i get the correct way o do this, i hope can help someone with the same o similar problem.
$user = Get-ADUser -Filter {HomeDirectory -like '*'} -Properties HomeDirectory, HomeDrive
foreach($e in $user)
{
$name= $e.SamAccountName
$drive = $e.HomeDrive
Set-ADUser -Identity $name -HomeDirectory \\mboulaayoun.com\comu\personals\$nom -HomeDrive $drive
}

Related

I'm trying to see the result of this script, when it runs it closes right away and doesn't show the groups the user was added too

This is my script,
I'm trying to add a user to these groups and show the result at the end to which group the user are in.
$user = Read-host "Please enter user"
$groups = 'M365-E3-Laptop-Office-Desktop','M365-E3-Laptop-EXO'
$groupsremove = 'M365-F3-WebOnly-Apps'
foreach($group in $groups){
Add-ADGroupMember -Identity $group -Members $user}
foreach($groupsremove in $groupsremove){
Remove-ADGroupMember -Identity $groupsremove -Members $user}
foreach($user in $groups){
Get-ADPrincipalGroupMembership $user | select name}
Start-Sleep -seconds 30
try this, maybe its case sensitive
$user = Read-host "Please enter user"
$groups = 'M365-E3-Laptop-Office-Desktop','M365-E3-Laptop-EXO' $groupsremove = 'M365-F3-WebOnly-Apps'
foreach($group in $groups){ Add-ADGroupMember -Identity $group -Members $user}
foreach($groupsremove in $groupsremove){ Remove-ADGroupMember -Identity $groupsremove -Members $user}
foreach($user in $groups){Get-ADPrincipalGroupMembership $user | select name}
Start-Sleep -Seconds 30`
First, there is no need to use ForEach instruction if your variable $groupsremove only contains one group.
Second, there is also no need to use ForEach instruction since you only have one user.
$user = Read-host "Please enter user"
$groups = 'M365-E3-Laptop-Office-Desktop','M365-E3-Laptop-EXO'
$groupsremove = 'M365-F3-WebOnly-Apps'
ForEach($group in $groups)
{
Add-ADGroupMember -Identity $group -Members $user
}
Remove-ADGroupMember -Identity $groupsremove -Members $user
Get-ADPrincipalGroupMembership $user | Select-Object Name
It should returns you something like this:
Name
----
M365-E3-Laptop-Office-Desktop
M365-E3-Laptop-EXO
Then, regarding the powershell prompt closing after the script is finished, you could simply call the script through a PowerShell prompt first instead of executing the script directly from the file, so the window doesn't close at the end.

PowerShell using user attributes to assign to another user attribute

I was creating what I thought was a super-simple PowerShell script to update the location field with "Mobile: " + Mobile Phone number. Using the limited fields on GAL to show mobile number for all users.
Somehow, I only get the "Mobile: " without the number. I have tried many variations of this same script but ultimately $User.mobile is incorrect.
Import-Module ActiveDirectory
$Userlist = Get-ADUser -Server XXXXX -filter * -SearchBase "OU=Users,OU=Corporate,OU=XXXXXXXX,DC=XXXXXX,DC=com"
foreach ($User in $Userlist) {
$newlocation = "Mobile: "
$newlocation = $newlocation + $User.mobile
Set-ADUser -Instance $User
}
# Update properties.
Two things you need to change here:
Include the mobile and location attributes in the original Get-ADUser query, it won't retrieve these by default:
$Userlist = Get-ADUser -Server XXXXX -filter * -Properties mobile,physicalDeliveryOfficeName -SearchBase "OU=Users,OU=Corporate,OU=XXXXXXXX,DC=XXXXXX,DC=com"
and then make sure you actually modify the $User object before calling Set-ADUser:
foreach ($User in $Userlist) {
$newlocation = "Mobile: " + $User.mobile
$User.physicalDeliveryOfficeName = $newlocation
Set-ADUser -Instance $User
}
The Get-AdUser adding -properties was the answer. It worked like a charm.
$Userlist = Get-ADUser -Server XXXXX -filter * -Properties mobile,physicalDeliveryOfficeName -SearchBase "OU=Users,OU=Corporate,OU=XXXXXXXX,DC=XXXXXX,DC=com"
foreach($User in $userlist)
{
$newlocation = "Mobile: " + $User.mobile
$User.physicalDeliveryOfficeName = $newlocation
Set-ADUser -Instance $User
}

Lazy loading in powershell?

Can we defer a variable initialization untill it is needed ?
What I would like to do is predefine some variables in my profile that will contain a list of AD computer:
let's say I want:
$OU1_workstation to be fill with computers found in OU=workstations,OU=OU1,dc=domain,dc=com
$OU2_workstation fill with computers found in
OU=workstations,OU=OU2,dc=domain,dc=com and so on...
I use the following script to do it but it takes 30sec to compute, so currently I can't put that in my profile...
Get-ADOrganizationalUnit -SearchScope onelevel -Filter "*" -Properties "name","distinguishedname" |%{
set-Variable -Name "$($_.name)_workstation" -value (Get-ADComputer -Searchbase "OU=workstations,$($_.Distinguishedname)" -Filter * )
}
What options are available in powershell ?
Finally, based on #Richard's reply of a previous question of mine, I've chosen the following path to achieve some sort of lazy loading : using a scriptproperty of a PSCustomObject.
So I can put this in my profile
#requires -module activedirectory
$server=New-Object PSCustomObject
Get-ADOrganizationalUnit -SearchScope onelevel -Filter "*" -Properties "name","distinguishedname" |
?{
$_.name -notmatch 'Administrateurs|Administration|Comptes de deploiement|Contacts|Domain Controllers|Groupes|Serveurs|Services'
} |
%{
$OU=$_.name
$s=[scriptblock]::Create("Get-ADComputer -SearchBase ""OU=servers,OU=$OU,DC=domain,DC=com"" -Filter 'name -notlike "" *old""' |select -expand name")
$server| Add-Member -MemberType ScriptProperty -name $OU -value $s -Force
}
then when needed I can call $server.OU1 to get all server under this OU, $server.OU2 etc...

Check Win32_group membership with powershell

I want to know if a user whom username is delivered is member of a group whom groupname is delivered.
$u = Get-WmiObject -Class Win32_UserAccount -Filter "Name='$username'"
$g = Get-WmiObject -Class Win32_Group -Filter "Name='$groupname'"
So I get two object with the property SID.
How can I check that user $u is member of group $g?
You can do this with an Associators query (example). Which are notoriously slow but do work.
$u = Get-WmiObject -Class Win32_UserAccount -Filter "Name='user'"
$group = Get-WmiObject -Class Win32_Group -Filter "Name='group'" | Select-Object -ExpandProperty Caption
$u | foreach {
$query = “Associators Of {Win32_UserAccount.Domain='” `
+ $_.Domain + “',Name='” + $_.Name `
+ “'} WHERE AssocClass=Win32_GroupUser”
$memberOf = Get-WmiObject -Query $query |
select -ExpandProperty Caption
If($memberOf -contains $group){
Write-Host "$($_.Name) is a member of $group"
} Else {
Write-Host "$($_.Name) is not a member of $group"
}
}
Get the use you are looking for and group your are checking to see if the user is a member of. While u$ should be only one user it is still a collection with one member. Pipe it into a ForEach-Object and build the Associators query. Execute the query and return all the group captions ( domain\groupname). Since $memberof is an array we can use -contains to see if the group you are looking for is there.
Alternatively
You could use the AD cmdlets if you have access to them and run the following
(Get-ADUser $user -Properties memberof | Select-Object -ExpandProperty memberof) -contains (Get-ADGroup -Identity $group)
The above will return True or False. You can install Ad cmdlets by using import-module activedirectory
Continued Testing
OpenLDAP should support this from what I gather and it's much faster then the previous WMI.
$search = [adsisearcher]"(&(objectcategory=user)(Name=userFullName))"
$userLDAP = $search.FindOne().Path
$userMembers = ([ADSI]$userLDAP).memberof
$search = [adsisearcher]"(&(objectcategory=group)(Name=groupname))"
$group = ($search.FindOne().Path) -replace "LDAP://"
$userMembers -contains $group
Sorry as I do not have access to OpenLDAP for testing. Do a search for a user and get the MemberOf as $userMembers. Then get the group into $group. Needed to remove the LDAP prefix from the string. Then just do another -Contains again.

Filter Get-ADComputer where "Name -notlike" in Powershell

My goal is to get a list of AD computer objects not following naming conventions with the whenCreated property. I am trying to export out a HTML file using the following PowerShell function:
function get_bad_names
{
$result = Get-ADComputer -searchbase $OU
-Filter {Name -notlike 'name1' -and
Name -notlike 'name2' -and
Name -notlike 'name3'}
-Properties whenCreated | sort whenCreated
$result | ConvertTo-Html | Out-File $dir\badnames.html
}
get_bad_names
Is there a more elegant way of structuring the Name filter lines? We have over 40 lines of different "names." In other words, over 40 lines in my script say Name -notlike 'name#' -and
Ideally I'd like for the code to read from a text file and export out the same results.
FYI: this function works but it is not ideally written. Any suggestions would be appreciated.
If you'd like to filter the query, construct an LDAP filter:
# Define the names to exclude
$NamesToExclude = "Name1","Name2","Name3"
# Turn them into LDAP clauses in the form of "(!(Name=Name1))"
$LDAPClauses = $NamesToExclude |ForEach-Object {
'(!(Name={0}))' -f $_
}
# Create a single query filter string with all the clauses from above
$LDAPFilter = "(&$LDAPClauses)"
$result = Get-ADComputer -LDAPFilter $LDAPFilter -SearchBase $OU -Properties whenCreated |Sort-Object whenCreated
You could filter with a regular expression using Select-Object but then you should get all computers in the OU with the -filter *, and that might strain your network. I would do the filtering and if more properties are needed, run Get-Computer again only for the matches:
Get-ADComputer -searchbase $OU -Filter * |
? { $_.name -match "name\d{1,2}" } | # Match if string "name" is followed one or two digits
Get-ADComputer -property * # Get all properties for the computers if needed
Is there a more elegant way of structuring the Name filter lines?
Not exactly. You have a fairly limited set of operators when you use the -Filter parameter of commands in the ActiveDirectory module because it has to translate them all to LDAP filters.
However, you can do something like this:
$ExcludedPatterns = 'Name1', 'Name2', 'Name3'
$ComputerFilter = foreach ($Pattern in $ExcludedPatterns) { "(Name -notlike '$Pattern')" }
$ComputerFilter = $ComputerFilter -join ' -and '
Get-ADComputer -Filter $ComputerFilter
Now you can maintain a list of name patterns.
Keep in mind that the -Filter property is not a ScriptBlock on the ActiveDirectory commands. They're all Strings and in spite of the documentation for these commands they should be written that way. Writing them as ScriptBlocks will eventually cause you problems with variable expansion.
Compare:
$ComputerName = hostname
Get-ADComputer -Filter "Name -eq '$ComputerName'"
Get-ADComputer -Filter { Name -eq '$ComputerName' }
Thank you to everyone for their feedback. I was impressed how fast the responses were.
I was able to achieve my goal using regular expressions reading from a text file.
My code now looks like this:
[regex]$Expression = Get-Content $dir\regex.txt
function get_bad_names
{
$result = Get-ADComputer -searchbase $OU
-Filter {Enabled -eq $true}
-Properties whenCreated | Where-Object {$_.Name -notmatch $Expression}| sort whenCreated
$result | ConvertTo-Html | Out-File $dir\badnames.html
}
get_bad_names

Resources