Monthly Archives: February 2012

Finding the logon scripts

What logon scripts are in your environment

"`nMicrosoft"            
Get-ADUser -LDAPFilter "(&(objectclass=user)(objectcategory=user)(scriptpath=*))" -Properties *|            
Format-Table Name, DistinguishedName, ScriptPath -AutoSize            
            
"`nAD provider"            
Get-ChildItem -Filter "(&(objectclass=user)(objectcategory=user)(scriptpath=*))" `
 -Path Ad:\"DC=Manticore,DC=org" -Recurse |             
foreach {             
 $user = [adsi]"LDAP://$($_.DistinguishedName)"            
 $user | select @{N="Name"; E={$_.name}},             
 @{N="DistinguishedName"; E={$_.distinguishedname}},            
 @{N="LogonScript"; E={$_.scriptpath}}            
} | Format-Table -AutoSize            
             
"`nQuest"            
Get-QADUser -LDAPFilter "(&(objectclass=user)(objectcategory=user)(scriptpath=*))" -IncludeAllProperties |            
Format-Table Name, DN, ScriptPath -AutoSize            
            
"`nScript"            
$root = [ADSI]""            
$search = [adsisearcher]$root            
$search.Filter = "(&(objectclass=user)(objectcategory=user)(scriptpath=*))"             
$search.SizeLimit = 3000            
$search.FindAll() | foreach {            
             
$user = $_.GetDirectoryEntry()            
$user | select @{N="Name"; E={$_.name}},             
 @{N="DistinguishedName"; E={$_.distinguishedname}},            
 @{N="LogonScript"; E={$_.scriptpath}}            
} | Format-Table -AutoSize


Standard search for any user that has the scriptpath attribute set and then display name, distinguished name and scriptpath (logon script name).



To search for a given logon script – change the search filter



"(&(objectclass=user)(objectcategory=user)(scriptpath=<logon_script_name>))"



To just get a list of active logon scripts change the Format-Table as shown below



Get-ADUser -LDAPFilter "(&(objectclass=user)(objectcategory=user)(scriptpath=*))" -Properties *|
sort scriptpath | select ScriptPath -Unique

Set user’s logon script

Staying on the profile tab we can also set a logon script

$ou = "OU=BlogTests,DC=Manticore,DC=org"            
            
"`nMicrosoft"            
$name = "UserA"            
Get-ADUser -Identity $name |            
Set-ADUser -ScriptPath "ls1.cmd"            
            
"`nAD provider"            
$name = "UserB"            
$dn = "cn=$name,$ou"            
Set-ItemProperty -Path AD:\$dn  -Name scriptpath -Value "ls1.cmd" -Force            
             
"`nQuest"            
$name = "UserC"            
Get-QADUser -Identity $name |            
Set-QADUser -LogonScript "ls1.cmd"            
            
"`nScript"            
$name = "UserD"            
$dn = "cn=$name,$ou"            
$user = [adsi]"LDAP://$dn"            
$user.scriptpath = "ls1.cmd"            
$user.SetInfo()


Simply set the name of the logon script file in the scriptpath attribute. Notice that the Quest cmdlet uses –LogonScript for the parameter



The full path isn’t required because logon scripts are in the netlogon share on domain controllers – you don’t want to set a specific domain controller usually

Finding the users home drives

To display the home drive information for your users

"`nMicrosoft"            
Get-ADUser -LDAPFilter "(&(objectclass=user)(objectcategory=user)(homeDirectory=*))" -Properties *|            
Format-Table Name, DistinguishedName, HomeDirectory, HomeDrive -AutoSize            
            
"`nAD provider"            
Get-ChildItem -Filter "(&(objectclass=user)(objectcategory=user)(homeDirectory=*))" `
 -Path Ad:\"DC=Manticore,DC=org" -Recurse |             
foreach {             
 $user = [adsi]"LDAP://$($_.DistinguishedName)"            
 $user | select @{N="Name"; E={$_.name}},             
 @{N="DistinguishedName"; E={$_.distinguishedname}},            
 @{N="HomeDirectory"; E={$_.homeDirectory}},            
 @{N="HomeDrive"; E={$_.homeDrive}}             
} | Format-Table -AutoSize            
             
"`nQuest"            
Get-QADUser -LDAPFilter "(&(objectclass=user)(objectcategory=user)(homeDirectory=*))" -IncludeAllProperties |            
Format-Table Name, DN, HomeDirectory, HomeDrive -AutoSize            
            
"`nScript"            
$root = [ADSI]""            
$search = [adsisearcher]$root            
$search.Filter = "(&(objectclass=user)(objectcategory=user)(homeDirectory=*))"             
$search.SizeLimit = 3000            
$search.FindAll() | foreach {            
             
$user = $_.GetDirectoryEntry()            
$user | select @{N="Name"; E={$_.name}},             
 @{N="DistinguishedName"; E={$_.distinguishedname}},            
 @{N="HomeDirectory"; E={$_.homeDirectory}},            
 @{N="HomeDrive"; E={$_.homeDrive}}             
} | Format-Table -AutoSize


In all cases perform an LDAP search with the filter set for any occurrence of the the home directory being set.



The cmdlets can immediately display the required attributes but for the provider and script we have to get a directory entry so we can select the required attributes.

Setting a users home directory

One task when creating a new user is to set their home directory. This information is on the Profile tab in the lower box.

In the GUI we would use the Connect radio button, select a drive letter and supply the UNC path to a share.  In PowerShell we do this

$ou = "OU=BlogTests,DC=Manticore,DC=org"            
            
"`nMicrosoft"            
$name = "UserA"            
Get-ADUser -Identity $name |            
Set-ADUser -HomeDirectory "\\fileserver\$name" -HomeDrive "H:"            
            
"`nAD provider"            
$name = "UserB"            
$dn = "cn=$name,$ou"            
Set-ItemProperty -Path AD:\$dn  -Name homeDirectory -Value "\\fileserver\$name"  -Force            
Set-ItemProperty -Path AD:\$dn  -Name homeDrive     -Value "H:"       -Force            
             
"`nQuest"            
$name = "UserC"            
Get-QADUser -Identity $name |            
Set-QADUser -HomeDirectory "\\fileserver\$name" -HomeDrive "H:"            
            
"`nScript"            
$name = "UserD"            
$dn = "cn=$name,$ou"            
$user = [adsi]"LDAP://$dn"            
$user.homeDirectory = "\\fileserver\$name"            
$user.homeDrive = "H:"            
$user.SetInfo()


 



The cmdlets supply parameters for HomeDirectory and HomeDrive – both fairly obvious



In the provider we have a couple of calls to Set-Itemproperty. The attribute names are self explanatory. The script is similar in that we get a directory entry for the user and set the appropriate attributes.

UK PowerShell group–February 2012 recording

The recording, slides and demo scripts from tonight’s PowerShell and SQL Server session are available as a single zip file for download from

https://skydrive.live.com/#cid=43CFA46A74CF3E96&id=43CFA46A74CF3E96%212943

The file is created with jzip but any zip handling program should be able to unzip it

Thank you to the attendees and especially for the questions – I’ve posted the answer to the question regarding accessing named instances using a port number here

http://msmvps.com/blogs/richardsiddaway/archive/2012/02/28/connecting-via-smo-to-a-named-instance.aspx

Next meeting will be 28 March 2012

Topic will probably be CIM in PowerShell v3

Group’s displayname

A question on the forum asked about setting the value for a group’s displayname attribute. 

When you first create a group using any of the techniques we have seen earlier the displayname property is not set.  You can set it like this

Get-QADGroup -Identity GroupDmlSecA
$group = "GroupDmlSecA"
Get-QADGroup -Identity $group
Get-QADGroup -Identity $group | Set-QADGroup -ObjectAttributes @{displayName = $group}

 

Not sure why you would want to do this as as far as I can tell the displayname is never used for a group – the name showing in AD Users and Computers is the object name (cn attribute) not the display name

Connecting via SMO to a named instance

A question came up in tonight’s User group session regarding connecting to SQL server instances using SMO


If you have just a default instance – just give the server name


$server = New-Object -TypeName "Microsoft.SqlServer.Management.Smo.Server" -ArgumentList "W08R2SQl12"


 


If you have a named instance the give the instance name as well


$serverI = New-Object -TypeName "Microsoft.SqlServer.Management.Smo.Server" -ArgumentList "W08R2SQl12\instance_name"


 


These work as long as the SQL Server browser service is running. 


If it isn’t this is what I think you have to do.


This is untested and a best guess. I will try and test.


$cons = "server=W08R2SQL12\instance_name,port_number;Trusted_Connection=true;multipleactiveresultsets=false"


$cn = New-Object -TypeName "System.Data.SqlClient.SqlConnection" -ArgumentList $cons
$serverZ = New-Object -TypeName "Microsoft.SqlServer.Management.Smo.Server" -ArgumentList $cn
If anyone manages to test this please let me know – I’ll test as soon as I can

Remove all members from a group

Do you need to remove all members from a group

$ou = "OU=BlogTests,DC=Manticore,DC=org"            
            
"`nMicrosoft"            
$group = "GroupUnvlSecA"            
Get-ADGroupMember -Identity $group |            
Remove-ADPrincipalGroupMembership -MemberOf $group -Confirm:$false            
            
            
"`nAD provider"            
$group = "GroupUnvlSecB"            
$ou = "OU=TestGroups,DC=Manticore,DC=org"            
            
$members = @()            
Set-ItemProperty -Path ad:\"cn=$group,$ou" -Name member -Value $members -Force            
            
"`nQuest"            
$group = "GroupUnvlSecC"            
Get-QADGroupMember -Identity $group |             
Remove-QADGroupMember -Identity $group            
            
            
"`nScript"            
$group = "GroupUnvlSecD"            
$ge = [adsi]"LDAP://cn=$group,$ou"            
            
$ge.member |            
foreach {            
  $ge.Remove("LDAP://$($_)")             
}


The Microsoft cmdlet and provider will moan about insufficient privileges if you get the syntax wrong



For the Microsoft cmdlet we can pipe the group membership into Remove-ADPrincipalGroupMembership. Notice the use of –Confirm.  if you don’t use that you will be asked to confirm every deletion.



The Quest cmdlet is a simple get | remove operation



The provider treats the members as an array so we can use an empty array to overwrite the memebrship



The script iterates through the members and uses the Remove() method to delete members

February UG meeting–Final reminder

 


The UK PowerShell group presents a Live Meeting tomorrow on using PowerShell with SQL Server


Details from


http://msmvps.com/blogs/richardsiddaway/archive/2012/02/09/february-powershell-group-meeting-sql-server-and-powershell.aspx

Copy group membership

We may need to copy the members of one group into a second

In these examples I’m copying the membership of a Universal group into a Domain Local group.  That’s just because I have those groups available. You can copy between any two groups but remember that global groups can only contain members from within the domain – in my test environment I only have a single domain so the restriction doesn’t apply.

$ou = "OU=BlogTests,DC=Manticore,DC=org"            
            
"`nMicrosoft"            
$gsource = "GroupUnvlSecA"            
$gtarget = "GroupDmlSecA"            
Get-ADGroupMember -Identity $gsource |            
foreach {            
 Add-ADGroupMember -Identity $gtarget -Members $($_.DistinguishedName)            
}            
            
"`nAD provider"            
$gsource = "GroupUnvlSecB"            
$gtarget = "GroupDmlSecB"            
$ou = "OU=TestGroups,DC=Manticore,DC=org"            
            
$m = Get-ItemProperty -Path ad:\"cn=$gsource,$ou" -Name member            
$members = @($m.member)            
Set-ItemProperty -Path ad:\"cn=$gtarget,$ou" -Name member -Value $members            
            
"`nQuest"            
$gsource = "GroupUnvlSecC"            
$gtarget = "GroupDmlSecC"            
Get-QADGroupMember -Identity $gsource |             
Add-QADGroupMember -Identity $gtarget            
            
            
"`nScript"            
$gsource = "GroupUnvlSecD"            
$gtarget = "GroupDmlSecD"            
            
$source = [adsi]"LDAP://cn=$gsource,$ou"            
$target = [adsi]"LDAP://cn=$gtarget,$ou"            
            
$source.member |            
foreach {            
  $target.Add("LDAP://$($_)")             
}


The two cmdlet based solutions involve getting the membership of the source group and piping it into a cmdlet that can add those members to a new group.



The provider simply gets the member property of the source group, converts it to an array and uses that to set the target group membership



The script iterates through the members of the source group and uses the Add() method to add them to the new group