Get only the required parameters when using Get-Help

February 24, 2013

If you type down A cmdlet and forget to include A required parameter (within A parameter set – each parameter set has its own required parameters) than PowerShell will produce an error with the relevant parameter that’s missing.
This trial and error scenario, and carefully reading all of the cmdlet’s help file, is the effective way to get comfortable with A cmdlet.
but sometimes you’ll just want A quick refresher of the required parameters, that’s when I’ll pipe Get-Help -Parameters * to Where-Object:

PS C:\> Get-Help Get-ADUser -Parameter * | where {$_.required -eq “true”}

The output will be the required parameters help content that lives inside the cmdlet’s help XML file.
Again, that’s a little “trick” I use from time to time when I want A quick refresher about the required parameters.
Don’t forget, not all the parameters you see in the output can work together – some cmdlets have more than 1 property sets. In the case of Get-ADUser, you can’t use “-Filter” alongside “-Identity”.

Do you also need to remind yourself from time to time what are the required parameters?

Tell me what you think!


Find Active Directory computer objects by their Operating System

January 15, 2013

Find out if you still have any Windows 2000 objects left in your domain

I was recently asked by a friend how to find Windows 2000 computers with PowerShell.

While its very easy to accomplish with ADUC, he needed a script.

Every computer object in Active Directory has an Operating System attribute (simply called “OperatingSystem”).

All you need to do is to use Get-ADComputer cmdlet and provide an expression for its filter parameter.

PS C:\> Get-ADComputer -Filter ‘OperatingSystem -like “Windows 2000*”‘

Checking \ Setting Remote Desktop Services Profile Settings

December 24, 2012

Check or Set Remote Desktop Services Profile Settings With PowerShell

Many Administrators and Helpdesk teams are assigned with the task of configuring their clients RDP Settings. from the GUI, It is done through the “Remote Desktop Services Profile” tab in the ADUC user settings (that’s in Windows Server 2008 R2. in earlier versions, its called “Terminal Services Profile”)

Like most IT tasks (when it comes to Microsoft’s products), this task can be automated with PowerShell.
Personally, I like to use Microsoft’s ActiveDirectory PowerShell module for all PowerShell AD tasks.

In order to retrieve Remote Desktop settings, the Classic “Get-ADUser -Identity SomeUser -Properties *” wont help us find properties with relevant info, because Get-ADUser can’t get them all.

Another built-in solution is to use the old-fashioned ADSI adapter type. the .NET frameworks wraps the adapter like a PowerShell object. its accessible through the .psbase member set which let us access the objects public members.
Not as friendly as a Cmdlet, but it will give us properties and methods to work with.

The ADSI adapter is operated using LDAP queries (it can also query other LDAP instances than Active Directory), which means I have to use a Distinguished Name (DN) in order to get the user object:

PS C:\> $ADUser = [ADSI]”LDAP://CN=UserName,OU=Users,DC=TestDomain,DC=com”

But I got many OU’s… and typing down DN’s is so V1…

PS C:\> $ADUser = Get-ADUser UserName | select -ExpandProperty disting*
PS C:\> $ADUser = [ADSI]”LDAP://$ADUser”

(Notice that LDAP is all upper-case!)

Next, I query the object received with its InvokeGet() method.
First, I see if the Profile Path attribute is populated:

PS C:\> $ADUser.psbase.InvokeGet(“terminalservicesprofilepath”)
\\TSServer\Profiles\UserName

And make sure that the “Deny this user permissions to log on to Remote Desktop Sessions host server”
is UN-checked (“1” stands for allow, “0” for denied):

$ADUser.psbase.InvokeGet(‘allowlogon’)
1

So I can also check bulks of users:

PS C:\> Get-ADGroupMember Sales_Team | ForEach-Object {
>> Write-Host $_.samaccountname + ” RDP Configuration:”
>> $x = [ADSI]”LDAP://$($_.DistinguishedName)”
>> $x.psbase.invokeget(“terminalservicesprofilepath”)
>> $x.psbase.invokeget(“allowLogon”)
>> }

Thats pretty useful, but how do I configure those attributes? similar to the last example, I use the InvokeSet() method.

PS C:\> $x.psbase.invokeset(“terminalservicesprofilepath”,”\\TSServer\Profiles\UserName”)
PS C:\> $x.psbase.invokeSet(“allowLogon”,1)
PS C:\> $x.setinfo()

Do you find it helpful?
Let me know what you think!
Happy scripting ūüôā


Set User’s Home Folder That Is Managed With FSRM – PowerShell

October 24, 2012

Managing Home Folders with FSRM

Important! The following article only applies to FSRM Roles that are installed on Windows Server 2003/2008/R2, as 2012 FSRM has it’s own PowerShell module!

In our organization, we got users asking us to¬†increase their¬†Home Folder’s capacity¬†on a daily basis. We manage these home folders on our file servers using the File Server Resource Manager (FSRM) server role.

Everytime you want to set a quota limit that is managed wtih FSRM, you have to do it with the FSRM MMC, and its biggest downside, is that even when you only need to set just one quota limit, you need to wait for all the other data to load, and that can take well more than 8 or so seconds on most occasions Рenough time to set quotas for multiple users through a script.

Where I work, we got at least 1000 quotas on each file server, scattered around 8 file server across the country. loading all that data over WAN can sometimes be annoying.

Now when it comes to setting those quotas with powershell, one possibility is to load the Fsrm.FsrmQuotaManager COM Object into the shell¬†and use it to set Quotas. But this COM object doesn’t exists in Windows 7,¬†only on¬†the server itself (Server 2003 / 2008 ) and I don’t want to access¬†the relevant file server¬†with Remote Desktop every time I need set a quota limit… and my security team doesn’t allow me to start PS Sessions to most of our servers..

Using dirquota.exe With PowerShell to Set Home Folders That are Managed with FSRM

Throughout my search for a solution, I¬†found out that Microsoft’s Storage Team supply the dirquota.exe utility, that comes along when you install the FSRM RSAT Tool (in “turn windows features on or off”, select Remote Server Administration Tools > File Services Tools > File Server resource Manager Tools)

I’ve played with it, and like most .exe¬†utilities, it’s not as syntax-friendly and¬†easy to use as a PowerShell¬†Cmdlet. one of the reasons is that you have to type the original path¬†of that folder (D:\Users\James), and that can be a problem, because that path can be different from one file server to another.¬†therefore, it’s easier for me to use a UNC.

So I decided I’ll just¬†write a Cmdlet that will pass its data to the relevent parameters of dirquota.exe.

instead of finding out the true location of the UNC (D:\Users\James. or is it E:\Users\James? errh!) and then use dir quota:

PS C\:> dirquota.exe q m /remote:FileServer /path:D:\Users\James /Limit:1400MB

I will run a PowerShell Cmdlet:

PS C:\> Set-FSRMQuota -User James -Limit 1700

Lets get to Work!

Writing the Script Cmdlet

By understanding how dirquota.exe accpets input, I know 3 things:

  • I need to know the¬†name of the file¬†server that is hosting the home folder.
  • I need to know the home folder’s original path on that server.
  • I’ll need to take this data, and populate dirquota’s appropriate parameters.

Sounds like a classic PowerShell mission…

For the first task, we will use Get-ADUser to store the user information in a variable.

Next, we’ll export the UNC out of the user’s HomeDirectory attribute:

Now I’ll¬†need to extract the Share name and the Server name out of the UNC. I’ll try to minimize the use of string editing. first,

I’ll use Get-Item to extract the shared folder’s name:

PS C:\> $FolderUNC = (Get-Item $UNC).parent | select -ExpandProperty name

and then I’ll just trim the original UNC in two phases:

PS C:\> $ServerUNC ($UNC -Replace “$FolderUNC.*”).Trim(‘\’)

Note that im using “Select -ExpandProperty” (Select is an alias for Select-Object).¬†I¬†do it because¬†I need that object¬†as a type of string, because the original¬†object is the type of ActiveDirectory.Management.ADUser, and it’s value is something that i cant edit, or attach to Get-Item.

Now, We need to find the UNC’s original path on the file server. For this task, I’ll use WMI’s Win32_Share class. I’ll use it¬†on $ServerUNC, because that is the file server that hosts the home folder. I’ll filter the results¬†with Where-Object to try to find a folder that its name¬†matches $FolderUNC:

We’ll extract that path and save it in a variable:


Only thing left,¬†is to populate dirquota’s¬†“/limit:” parameter, which accepts data as a number, followed by a “MB” suffix (for example – “1700MB”).¬†because the final¬†script¬†is¬†accessible¬†like a Cmdlet,¬†it has¬†a variable¬†that accept’s¬†parameter input, with a “param ()” block at the start of the script. We will use this for illustration:

Now we can run direquota.exe and populate its parameters with all the data we collected. this command will live inside the final script:

dirquota.exe q m /remote:$serverUNC /path:$path\$($ad.SamAccountName) /limit:$limit
Quotas modified successfully

Informing us that the “Quotas modified successfully” is very helpful. but i¬†want a final report on the operation I just did! I’ll store all the data that I collected into a custom object that I’ll create using New-Object:

finally, We will put everything we wrote in an Advanced Function construct, so we can use it like we wanted to in the first place – without typing the File Server and the original path, because the file servers and the path’s can be configured and named differently from one server or user to another.

PS C:\> Set-FSRMQuota -User James -Limit 500

This is how the final script looks like.

A link to download from MS TechNet gallery:

Set-FSRMQuota