<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PowerShell.nu &#187; Projects</title>
	<atom:link href="http://www.powershell.nu/category/projects/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.powershell.nu</link>
	<description></description>
	<lastBuildDate>Wed, 14 Jul 2010 22:17:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Joining a Windows 7 Client to a Domain through PowerShell</title>
		<link>http://www.powershell.nu/2009/06/05/joining-a-windows-7-client-to-a-domain-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/06/05/joining-a-windows-7-client-to-a-domain-through-powershell/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 17:02:49 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=754</guid>
		<description><![CDATA[Time to join a Windows 7 client to a domain. Now that the Test Domain is up and running ( Check Previous Posts ), we can start joining clients to the domain. Since it&#8217;s a freshly installed Windows 7 client, we dont have to bother about userprofiles and so on.. we&#8217;ll save that for later [...]]]></description>
			<content:encoded><![CDATA[<p>Time to join a Windows 7 client to a domain. Now that the Test Domain is up and running ( <a href="http://www.powershell.nu/2009/04/11/part-00-migrate-from-windows-server-2003-to-windows-server-2008-r2-and-windows-7-using-powershell/">Check Previous Posts</a> ), we can start joining clients to the domain.</p>
<p />
Since it&#8217;s a freshly installed Windows 7 client, we dont have to bother about userprofiles and so on.. we&#8217;ll save that for later <img src='http://www.powershell.nu/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p />
Joining the domain is done through WMI. Just create a new Object containing the Win32_ComputerSystem WMI object and call the JoinDOmainOrWorkGroup() method.</p>
<p />
<pre>
<strong>
function JoinDomain ([string]$Domain, [string]$User, [string]$Password ) {

	$DomainUser = $Domain + "\" + $User
	$OU = $null

	$ComputerSystem = gwmi Win32_ComputerSystem

	$ComputerSystem.JoinDomainOrWorkGroup(
		$Domain,
		$Password,
		$DomainUser,
		$OU,
		3
	)
}
</strong>
</pre>
<p />
Here&#8217;s an example on running the function.</p>
<p />
<pre>
<strong>
PS > JoinDomain PowerShell.nu migaccount Password1
</strong>
</pre>
<p />
And voila! the client shuts down and on Startup, It&#8217;ll have joined the new domain.</p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/06/05/joining-a-windows-7-client-to-a-domain-through-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adding HomeFolder Through PowerShell</title>
		<link>http://www.powershell.nu/2009/04/27/part-116-adding-homefolder-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/27/part-116-adding-homefolder-through-powershell/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 21:26:28 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=718</guid>
		<description><![CDATA[It&#8217;s been some time since my last post now, had alot of things to do at work, but now I&#8217;m back OnTrack with my blogging. Last time we checked out how to add group membership through PowerShell, so now we should have a nice test environment in place, based on Star Trek. In this post, [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been some time since my last post now, had alot of things to do at work, but now I&#8217;m back OnTrack with my blogging.</p>
<p />
Last time we checked out how to add group membership through PowerShell, so now we should have a nice test environment in place, based on Star Trek.</p>
<p />
In this post, we are going to script up Users homefolders and add each user to the correct folder. We&#8217;ll accomplish this through the following four steps:</p>
<ul>
<li>Add a Share on the Server</li>
<li>Add unique folders for all Users</li>
<li>Add unique Permissions to the FOlders</li>
<li>Edit the User Objects in Active-Direcroty</li>
</ul>
<p>I&#8217;m also going to re-use a script I wrote a couple of months ago, but we&#8217;ll get back to that.</p>
<p />
Let&#8217;s start off by creating a Share. This can be done through the Create() method in the WMI class Win32_Share. The Win32_Share is well described in <a href="http://msdn.microsoft.com/en-us/library/aa394435(VS.85).aspx">MSDN</a>.</p>
<p />
Since we want to make the script re-usable, we should check if the Share already exists. This is a simple procedure through PowerShell.</p>
<p />
<pre>
<strong>
PS > $Share = "C:\Share"
PS > $ShareName = "Share"
PS > if ((gwmi Win32_Share | Where { $_.Path -eq $Share}).Path -eq $Share ) {
>>  Write-Host "Share: $ShareName already exists." -ForeGroundColor Red
>>  }
</strong>
</pre>
<p>If the Share Already exists &#8220;Share: Share already exists&#8221; will be prompted, if not we can continue with the script.</p>
<p />
Now that we know that the share doesn&#8217;t exist, we have to check that the folder exists, and if not, create the folder.</p>
<p />
<pre>
<strong>
PS > if (!(Test-Path $Share)) {
>>  New-Item -Path $Share -type directory | Out-Null
>>  }
</strong>
</pre>
<p />
and finally, we can create our Share through WMI. Setting type to 0 creates a Disk Drive Share.</p>
<p />
<pre>
<strong>
PS > $CreateShare = [wmiclass]"Win32_Share"
PS > $CreateShare.Create($Share,$ShareName,$Type) | Out-Null
</strong>
</pre>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stshare02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stshare02.jpg" alt="add-stshare02" title="add-stshare02" width="367" height="473" class="alignnone size-full wp-image-720" /></a></p>
<p />
Now that the share is up and running, we can create our HomeFolders. First we set up our HomeDrive and HomeFolder variables, we&#8217;ll also set up a User for the example.</p>
<p />
<pre>
<strong>
PS > $Share = "Share"
PS > $User = "jeapic"
PS > $HomeDrive = "H"
PS > $HomeDirectory = "\\" + $env:COMPUTERNAME + "\" + $Share + "\" + $User
</strong>
</pre>
<p />
Since the script runs on the server where the Share is created, we can use the environment variable to retrieve the computername.</p>
<p />
Next, we want to check if the user already has the homedrive and homedirectory set. We can use the <a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">Get-AD.ps1</a> script for this. I&#8217;m also adding the -ToObject switch since i want to use the object later on.</p>
<p />
<pre>
<strong>
PS > $GetUser = ./Get-AD.ps1 -Domain $Domain -User $User -Filter sAMAccountName -ToObject
PS > if ($GetUser.homeDirectory -match $HomeDirecory -AND $GetUser.homeDrive -match $HomeDrive) {
>> Write-Host "User: $User HomeDrive Already Set" -ForeGroundColor Yellow
>> }
</strong>
</pre>
<p />
If the User already has the HomeDrive set, we won&#8217;t continue, if not, we can go ahead and add it. But before connecting the User to the folder, want to create and give the user FullControl of his HomeFolder. Here we can use the <a href="http://www.powershell.nu/wp-content/uploads/2009/02/setfolderpermission.ps1">Set-FolderPermission.ps1</a> script</p>
<p />
<pre>
<strong>
PS > $Domain = "powershell.nu"
PS > $DomainUser = $Domain + "\" + $User
PS > ./Set-FolderPermission.ps1 -Path $HomeDirectory -Access $DomainUser -Permission FullControl
</strong>
</pre>
<p />
The <a href="http://www.powershell.nu/wp-content/uploads/2009/02/setfolderpermission.ps1">Set-FolderPermission.ps1</a> both created the folder and set up the permissions for us, now all we have to do is set HomeDrive and HomeDirectory to the User Object.</p>
<pre>
<strong>
PS > $GetUser.Put("homeDirectory",$HomeDirectory)
PS > $GetUser.Put("homeDrive",$HomeDrive)
PS > $GetUser.SetInfo()
</strong>
</pre>
<p />
And that&#8217;s it.</p>
<p />
Running the script Doesn&#8217;t require the Star Trek Csv file used in the other examples, it does however require you to loop through each Users that you want to add Homefolders to. In order to get a list of all Users within an OU you can use the <a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">Get-AD.ps1</a> script, as shown below.</p>
<p />
<pre>
<strong>
PS > ./Get-AD.ps1 -domain "LDAP://OU=Star Trek: The Next Generation,DC=powershell,DC=nu" -User AllUsers -Property sAMAccountName | ForEach {
>> ./Add-STHomeFolder.ps1 -Domain powershell.nu -User $_.sAMAccountName -Share Share -HomeDrive H
>> }
</strong>
</pre>
<p />
All I have to do now is change the LDAP path above and repeat the ForEach on each OU that contains Users that I want to add a HomeFolder to.</p>
<p />
Here are a couple of screenshots on running the scripts:</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-sthomefolder.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-sthomefolder-500x319.jpg" alt="add-sthomefolder" title="add-sthomefolder" width="500" height="319" class="alignnone size-large wp-image-721" /></a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-sthomefolder02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-sthomefolder02-500x375.jpg" alt="add-sthomefolder02" title="add-sthomefolder02" width="500" height="375" class="alignnone size-large wp-image-722" /></a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stshare.ps1">Click Here to Download the Add-STShare.ps1 Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-sthomefolder.ps1">Click Here to Download the Add-STHomeFolder.ps1 Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script is also required.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/setfolderpermission.ps1">Here&#8217;s the Set-Foldepermission.ps1 Script that&#8217;s also required.</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/27/part-116-adding-homefolder-through-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding Group Membership Through PowerShell</title>
		<link>http://www.powershell.nu/2009/04/16/part-115-adding-group-membership-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/16/part-115-adding-group-membership-through-powershell/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 18:37:49 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=706</guid>
		<description><![CDATA[Time to add some members to our groups. Following the steps in the previous posts, we should now have a couple of Users, groups and computers in our test environment. Group Names are based on the Character position in the Star Trek Csv file so now, all we have to do is match up the [...]]]></description>
			<content:encoded><![CDATA[<p>Time to add some members to our groups. Following the steps in the previous posts, we should now have a couple of Users, groups and computers in our test environment. Group Names are based on the Character position in the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Star Trek Csv file</a> so now, all we have to do is match up the Characters with their Positions.</p>
<p />
Starting of, Let&#8217;s collect the information we need from the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Csv File.</a></p>
<p />
There are 68 Characters in the file so I&#8217;m only going to select the first one in the eample below.</p>
<p />
<pre>
<strong>
PS > $CsvFile = Import-Csv StarTrek.csv
PS > ($CsvFile | Select Character, Position, Series)[0] | fl
</strong>

Character : Jean-Luc Picard
Position  : Commanding Officer
Series    : Star Trek: The Next Generation
</pre>
<p />
What we want to do now is add each member to the correct group. Let&#8217;s take the first User, Captain Picard, as an example and see how this is done.</p>
<p />
Since there are 4 different Commanding Officer groups, we want to make sure that we connect to the correct one. We know which Starship (OU) the Captain is in since and we have that information in the Csv file so we can use this in combination with the <a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">Get-AD.ps1 script.</a></p>
<p />
First we have get the OU:s distinguishedName.</p>
<p />
<pre>
<strong>
PS > $Domain = "powershell.nu"
PS > $Series = "Star Trek: The Next Generation"
PS > $OU = ./Get-AD.ps1 -Domain $Domain -OU $Series -property distinguishedName
PS > $OU
</strong>

distinguishedName
-----------------
OU=Star Trek: The Next Generation,DC=powershell,DC=nu

<strong>
PS > $DomainConnection = "LDAP://" + [string]$OU.distinguishedName
PS > $DomainConnection
</strong>
LDAP://OU=Star Trek: The Next Generation,DC=powershell,DC=nu
</pre>
<p />
Now that we have the connectionstring, we can use this to narrow down the search in the Get-AD.ps1 script. By typing -Domain followed by an OU:s distinguishedName forces the script to only search within the OU structure.</p>
<p />
<pre>
<strong>
PS > $Character = "Jean-Luc Picard"
PS > $User = ./Get-AD.ps1 -Domain $DomainConnection -User $Character -property distinguishedName, Name
PS > $UserConnection = "LDAP://" + [string]$User.distinguishedName
PS > $UserConnection
</strong>
LDAP://CN=Jean-Luc Picard,OU=Users,OU=Star Trek: The Next Generation,DC=powershell,DC=nu
<strong>
PS > $UserdistinguishedName = [string]$User.distinguishedName
PS > $UserdistinguishedName
</strong>
CN=Jean-Luc Picard,OU=Users,OU=Star Trek: The Next Generation,DC=powershell,DC=nu
</pre>
<p />
So why bother to create one variable holding the distinguishedName and one holding the LDAP connection string ?? well, we&#8217;ll get to that in a while but first we need a connection to the group as well.</p>
<p />
<pre>
<strong>
PS > $Position = "Commanding Officer"
PS > $Group = ./Get-AD.ps1 -Domain $DomainConnection -Group $Position -ToObject
PS > $Group | Format-List *
</strong>

objectClass          : {top, group}
cn                   : {Commanding Officer}
description          : {Commanding Officer}
distinguishedName    : {CN=Commanding Officer,OU=Groups,OU...
instanceType         : {4}
whenCreated          : {4/15/2009 5:09:08 PM}
whenChanged          : {4/15/2009 5:09:08 PM}
uSNCreated           : {System.__ComObject}
uSNChanged           : {System.__ComObject}
name                 : {Commanding Officer}
objectGUID           : {74 231 168 162 107 193 157 74 161
objectSid            : {1 5 0 0 0 0 0 5 21 0 0 0 50 71 101...
sAMAccountName       : {COMMANDIN}
sAMAccountType       : {268435456}
groupType            : {-2147483646}
objectCategory       : {CN=Group,CN=Schema,CN=Configuratio...
nTSecurityDescriptor : {System.__ComObject}
</pre>
<p />
Now that we got the correct group, all we have to do is make a simple check so that the Captain isn&#8217;t already member of the group and if not, add him to it. Here&#8217;s where the distinguishedName and LDAP string come in handy.</p>
<p />
<strong><br />
PS > if ($Group.member -Contains $UserdistinguishedName) {<br />
  Write-Host &#8220;The Captain is already member&#8221;<br />
} else {<br />
  $Group.Add($UserConnection)<br />
}<br />
</strong>
</pre>
<p />
Now let's how the complete script would handle this.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember01.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember01-500x319.jpg" alt="add-stmember01" title="add-stmember01" width="500" height="319" class="alignnone size-large wp-image-710" /></a></p>
<p />
Repeating the script tells us that the Characters are already members of the groups.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember02-500x319.jpg" alt="add-stmember02" title="add-stmember02" width="500" height="319" class="alignnone size-large wp-image-711" /></a></p>
<p />
And here's a quick check in the Active-Directory snapin.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember03.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember03.jpg" alt="add-stmember03" title="add-stmember03" width="402" height="449" class="alignnone size-full wp-image-712" /></a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stmember.ps1">Click Here to Download the Complete Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script is also required.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Click here to download the Csv File</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/16/part-115-adding-group-membership-through-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding Groups Through PowerShell</title>
		<link>http://www.powershell.nu/2009/04/15/part-114-adding-groups-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/15/part-114-adding-groups-through-powershell/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 19:08:18 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=678</guid>
		<description><![CDATA[With our Users and Computers in place, we can start adding groups. The groups will be based on the Postition ocf the characters in the StarTrek Csv file. I&#8217;ve chosen position since many characters can have the same position. First, let&#8217;s look at all the unique Positions in the Csv file. I&#8217;m also using the [...]]]></description>
			<content:encoded><![CDATA[<p>With our Users and Computers in place, we can start adding groups. The groups will be based on the Postition ocf the characters in the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">StarTrek Csv file</a>. I&#8217;ve chosen position since many characters can have the same position.</p>
<p />
First, let&#8217;s look at all the unique Positions in the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Csv file</a>. I&#8217;m also using the Series as a Descrption and it&#8217;s also used to place the group in the correct OU.</p>
<p />
<pre>
<strong>
PS > $CsvFile | Select Position, Series -Unique
</strong>

Position                     Series
--------                     ------
Commanding Officer           Star Trek: The Next Generation
First Officer                Star Trek: The Next Generation
Chief Engineer               Star Trek: The Next Generation
Chief of Security            Star Trek: The Next Generation
Chief Medical Officer        Star Trek: The Next Generation
Ship's Counselor             Star Trek: The Next Generation
Chief Operations             Star Trek: The Next Generation
Conn Officer                 Star Trek: The Next Generation
Transporter Officer          Star Trek: The Next Generation
Botanist                     Star Trek: The Next Generation
Nurse                        Star Trek: The Next Generation
Bartender                    Star Trek: The Next Generation
Engineering Officer          Star Trek: The Next Generation
Federation Ambassador        Star Trek: The Next Generation
Security Officer             Star Trek: The Next Generation
Medical Officer              Star Trek: The Next Generation
Operations Officer           Star Trek: The Next Generation
Commanding Officer           Star Trek: Deep Space Nine
First Officer                Star Trek: Deep Space Nine
Chief of Security            Star Trek: Deep Space Nine
Chief Medical Officer        Star Trek: Deep Space Nine
Chief Science Officer        Star Trek: Deep Space Nine
Counselor                    Star Trek: Deep Space Nine
Strategic Operations Officer Star Trek: Deep Space Nine
Chief Operations             Star Trek: Deep Space Nine
Civilian                     Star Trek: Deep Space Nine
Bartender                    Star Trek: Deep Space Nine
Commanding Officer           Star Trek: Voyager
First Officer                Star Trek: Voyager
Second Officer               Star Trek: Voyager
Chief Engineer               Star Trek: Voyager
Medical Officer              Star Trek: Voyager
Chief Operations Officer     Star Trek: Voyager
Chief Medical Officer        Star Trek: Voyager
Chef                         Star Trek: Voyager
Aeroponics caretaker         Star Trek: Voyager
Miscellaneous                Star Trek: Voyager
Conn Officer                 Star Trek: Voyager
Science                      Star Trek: Voyager
Engineering Officer          Star Trek: Voyager
Civilian                     Star Trek: Voyager
Commanding Officer           Star Trek: Enterprise
First Officer                Star Trek: Enterprise
Armory Officer               Star Trek: Enterprise
Engineering Officer          Star Trek: Enterprise
Medical Officer              Star Trek: Enterprise
Communications Officer       Star Trek: Enterprise
Chief Engineer               Star Trek: Enterprise
</pre>
<p />
I&#8217;m going to use the first entry &#8220;Commanding Officer&#8221; to explain how the script works. At first, we have to check if the group already exists. we&#8217;ll reuse the checker function that I&#8217;ve mentioned in previous blog posts.</p>
<p />
<pre>
<strong>
function Check-distinguishedName ([string]$Domain, [string]$Group) {

   trap {  $Script:distinguishedNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -Group $Group -filter distinguishedName | Out-Null
}
</strong>
</pre>
<p />
Next we have to build up the groups distinguishedName in order to check it.</p>
<p />
<pre>
<strong>
PS > $Domain = "powershell.nu"
PS > $Position = "Commanding Officer"
PS > $Series = "Star Trek: The Next Generation"
PS > $distinguishedName = "CN=" + $Position + ",OU=Groups,OU=" + $Series +
>> $Series + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
PS > $distinguishedName
</strong>
CN=Commanding Officer,OU=Groups,OU=Star Trek: The Next Generation,DC=powershell,DC=nu
</pre>
<p />
Now that we&#8217;ve built up a distinguishedName we can check it through the Check-distinguishedName function. If the group doens&#8217;t exist, the variable $distinguishedNameDoesntExist is set to $True, which means that we can go ahead and create the group.</p>
<p />
<pre>
<strong>
PS > Check-distinguishedName $Domain $distinguishedName
PS > $distinguishedNameDoesntExist
</strong>
True
</pre>
<p />
Now that we&#8217;re sure that the group does&#8217;t exist we can create a connection to Active-Directory and create the group. First we&#8217;ll set up the connectionstring to the correct OU and create a [adsi] connection.</p>
<p />
<pre>
<strong>
PS > $Connection = "LDAP://OU=Groups" + $Series.Insert(0,",OU=") +
>> ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
PS > $AD = [adsi] $Connection
</strong>
</pre>
<p />
Adding the group is quite simple using the Create() method.</p>
<p />
<pre>
<strong>
PS > $Group = $AD.Create("Group", "CN=$Position")
PS > $Group.SetInfo()
</strong>
</pre>
<p />
The part that&#8217;s not so simple is adding a unique sAMAccountName. Since there&#8217;s One Commanding officer for each ship, we will have a total of four different groups with the same name, the distinguishedName doesnt have to be unique as long as its not in the same OU but the sAMAccountName has to be.</p>
<p />
First we have to create a sAMAccountName for the group. Since the Group names tend to be quite long, we&#8217;ll shorten the groups sAMAccountName through the subString() method if it&#8217;s longer than 10 characters. We&#8217;ll also remove spaces in the string.</p>
<p />
<pre>
<strong>
PS > $sAMAccountName = ($Position.replace(" ","")).ToUpper()

PS > if ($sAMAccountName.Length -gt 10) {
  $sAMAccountName = $sAMAccountName.SubString(0,9)
}
PS > $sAMAccountName
</strong>
COMMANDIN
</pre>
<p />
Now that we have a sAMAccountName, we have to check so that it doesn&#8217;t exist. again through a checker function.</p>
<p />
<pre>
<strong>
function Check-sAMAccountName ([string]$Domain, [string]$Group) {

  trap {  $Script:sAMAccountNameDoesntExist = $True ; continue }
  .Get-AD.ps1 -Domain $Domain -Group $Group -filter sAMAccountName | Out-Null
}
</strong>
</pre>
<p />
If the sAMAccountName exists, we will handle this through a while loop and append an integer at the end.</p>
<p />
<pre>
<strong>
While ($Script:sAMAccountNameDoesntExist -eq $False) {

   $LastChar = $sAMAccountName.SubString($sAMAccountName.Length -1)

   if(1..9 -Contains $LastChar) {

    $sAMAccountName = ($sAMAccountName.TrimEnd([string]$LastChar)) +
    ([int]$LastChar + 1)
   } else {

    $sAMAccountName = $sAMAccountName + 1
   }

   Check-sAMAccountName -Domain $Domain -Group $sAMAccountName
}
</strong>
</pre>
<p />
Finally, we can add the additional group information, in this case: sAMAccountName and Description.</p>
<p />
<pre>
<strong>
$Group.put("Description", $Position)
$Group.put("sAMAccountName", $sAMAccountName)
$Group.setinfo()
</strong>
</pre>
<p />
Here&#8217;s how it looks if we run it in our test environment.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup01.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup01-500x318.jpg" alt="add-stgroup01" title="add-stgroup01" width="500" height="318" class="alignnone size-large wp-image-679" /></a></p>
<p />
Repeating the script shows that the groups already exist.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup02-500x318.jpg" alt="add-stgroup02" title="add-stgroup02" width="500" height="318" class="alignnone size-large wp-image-680" /></a></p>
<p />
and here&#8217;s a quick look in dsa.msc</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup03.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup03-500x304.jpg" alt="add-stgroup03" title="add-stgroup03" width="500" height="304" class="alignnone size-large wp-image-681" /></a></p>
<p />
Additionally, let&#8217;s look at our Commanding Officer groups. We can do this through the <a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">Get-AD.ps1 script</a></p>
<p />
<pre>
<strong>
PS > .Get-AD.ps1 -Domain powershell.nu -Group AllGroups -Property sAMAccountName, cn |
>> Where { $_.cn -match "Commanding Officer" }
</strong>

sAMAccountName cn
-------------- --
COMMANDIN      Commanding Officer
COMMANDIN1     Commanding Officer
COMMANDIN2     Commanding Officer
COMMANDIN3     Commanding Officer
</pre>
<p />
Isn&#8217;t it cool how you can take the result of a script and pipe it to the Where-Object CmdLet.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stgroup.ps1">Click Here to Download the Complete Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script is also required.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Click here to download the Csv File</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/15/part-114-adding-groups-through-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding Computers through PowerShell</title>
		<link>http://www.powershell.nu/2009/04/13/part-113-adding-computers-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/13/part-113-adding-computers-through-powershell/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 19:35:26 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=664</guid>
		<description><![CDATA[Now let&#8217;s add a couple of computers to our test environment. The Computer Names are based on the Starships from the Csv file. Since there are alot of characters but not that many different ships we need to get a unique list of ships. We also wnat the Series, Location and Registry values. PS > [...]]]></description>
			<content:encoded><![CDATA[<p>Now let&#8217;s add a couple of computers to our test environment. The Computer Names are based on the Starships from the Csv file. Since there are alot of characters but not that many different ships we need to get a unique list of ships. We also wnat the Series, Location and Registry values.</p>
<p />
<pre>
<strong>
PS > $CsvFile = Import-Csv StarTrek.csv
PS > $CsvFile | Select Series, Starship, Location, Registry -unique | fl
</strong>

Series   : Star Trek: The Next Generation
Starship : USS Enterprise (NCC-1701-D)
Location : Alpha Quadrant
Registry : NCC-1701-D

Series   : Star Trek: Deep Space Nine
Starship : Deep Space Nine
Location : Alpha Quadrant
Registry : DS9

Series   : Star Trek: Voyager
Starship : USS Voyager (NCC-74656)
Location : Delta Quadrant
Registry : NCC-74656

Series   : Star Trek: Enterprise
Starship : Enterprise (NX-01)
Location : Alpha Quadrant
Registry : NX-01
</pre>
<p />
Let&#8217;s walk through how the script handles the first Starship. At first we have to check if the Computer exists, We&#8217;ll use a checker function that checks if the Computer doesn&#8217;t exist.</p>
<p />
<pre>
<strong>
function Check-distinguishedName ([string]$Domain, [string]$Computer) {

   trap {  $Script:distinguishedNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -Computer $Computer -filter distinguishedName | Out-Null
}
</strong>
</pre>
<p />
Next we have to check create a variable holding a distinguishedName and check if it exists or not.</p>
<p />
<pre>
<strong>
PS > $Starship = "USS Enterprise (NCC-1701-D)"
PS > $Domain = "powershell.nu"
PS > $distinguishedName = "CN=" + $Starship + ",OU=Computers,OU=" + $Series + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
</strong>
</pre>
<p />
Now we can run the function.</p>
<p />
<pre>
<strong>
PS > Check-distinguishedName -Domain $Domain -Computer $distinguishedName
</strong>
</pre>
<p />
Now that we&#8217;ve checked the distinguisehdName we can connect to AD and start adding our Computer.</p>
<p />
<pre>
<strong>
PS > $Connection = "LDAP://OU=Computers" + $Series.Insert(0,",OU=") + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")

PS > $AD = [adsi] $Connection

PS > $Computer = $AD.Create("Computer", "CN=$Starship")
PS > $Computer.SetInfo()
</strong>
</pre>
<p />
Now for the additional information. We might want to change the sAMAccountName from the default name generated by AD. We also want to check that the name we choose doesn&#8217;t exist so we&#8217;ll use yet another check function.</p>
<p />
<pre>
<strong>
function Check-sAMAccountName ([string]$Domain, [string]$Computer) {

   trap {  $Script:sAMAccountNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -Computer $Computer -filter sAMAccountName | Out-Null
}
</strong>
</pre>
<p />
We&#8217;ll base the sAMAccountName on the Ships Registry information. In this case, the registry is NCC-1701-D</p>
<p />
<pre>
<strong>
PS > $sAMAccountName = ($Registry).ToUpper()

PS > Check-sAMAccountName -Domain $Domain -Computer $sAMAccountName
</strong>
</pre>
<p />
If the sAMAccountName doesn&#8217;t exist the script will use it on the Computer object. If it does exist, theres a while loop that loops through and appends a digit in order to get a unique sAMAccountName. Here&#8217;s an example on the where loop.</p>
<p />
<pre>
<strong>
While ($Script:sAMAccountNameDoesntExist -eq $False) {

   # Create New sAMAccountName

   $LastChar = $sAMAccountName.SubString($sAMAccountName.Length -1)

    if(1..9 -Contains $LastChar) {

    $sAMAccountName = $sAMAccountName.SubString(0,$sAMAccountName.Length -1) + ([int]$LastChar + 1)

   } else {

    $sAMAccountName = $sAMAccountName.SubString(0,$sAMAccountName.Length -1) + 1
   }

   Check-sAMAccountName -Domain $Domain -Computer $sAMAccountName
}
</strong>
</pre>
<p />
The final Steps of the script add the additional information and enables the computer.</p>
<p />
<pre>
<strong>
PS > $Computer.put("sAMAccountName", $sAMAccountName)
PS > $Computer.put("Location", $Location)
PS > $Computer.put("Description", $Starship)
PS > $Computer.setinfo()

PS > $Computer.PsBase.InvokeSet("AccountDisabled", $False)
PS > $Computer.SetInfo()
</strong>
</pre>
<p />
Now let&#8217;s run the script in our test environment.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stcomputer011.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stcomputer011-500x319.jpg" alt="add-stcomputer011" title="add-stcomputer011" width="500" height="319" class="alignnone size-large wp-image-669" /></a></p>
<p />
If we repeat the script it&#8217;ll tell us that the computers already exist.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stcomputer02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stcomputer02-500x318.jpg" alt="add-stcomputer02" title="add-stcomputer02" width="500" height="318" class="alignnone size-large wp-image-670" /></a></p>
<p />
If we check in dsa.msc snap-in we can see that the computer objects have been created.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stcomputer03.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stcomputer03-500x304.jpg" alt="add-stcomputer03" title="add-stcomputer03" width="500" height="304" class="alignnone size-large wp-image-671" /></a></p>
<p />
and finally, if we want to retrieve the information through PowerShell, we can use the Get-AD.ps1 script.</p>
<p />
<pre>
<strong>
PS > .Get-AD.ps1 -Domain powershell.nu -Computer "Uss Enterprise (NCC-1701-D)"
</strong>

objectClass          : top person organizationalPerson user computer
cn                   : USS Enterprise (NCC-1701-D)
description          : USS Enterprise (NCC-1701-D)
distinguishedName    : CN=USS Enterprise (NCC-1701-D),OU=Computers,OU=Star Trek
                       u
instanceType         : 4
whenCreated          : 4/13/2009 7:19:11 PM
whenChanged          : 4/13/2009 7:19:11 PM
uSNCreated           : System.__ComObject
uSNChanged           : System.__ComObject
name                 : USS Enterprise (NCC-1701-D)
objectGUID           : 31 54 123 251 207 232 62 72 153 101 238 77 71 88 19 27
userAccountControl   : 544
badPwdCount          : 0
codePage             : 0
countryCode          : 0
badPasswordTime      : System.__ComObject
lastLogoff           : System.__ComObject
lastLogon            : System.__ComObject
pwdLastSet           : System.__ComObject
primaryGroupID       : 513
objectSid            : 1 5 0 0 0 0 0 5 21 0 0 0 50 71 101 4 93 25 58 165 36 24
accountExpires       : System.__ComObject
logonCount           : 0
sAMAccountName       : NCC-1701-D
location             : Alpha Quadrant
sAMAccountType       : 805306368
objectCategory       : CN=Computer,CN=Schema,CN=Configuration,DC=powershell,DC=
nTSecurityDescriptor : System.__ComObject
</pre>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/Add-STComputer.ps1">Click Here to Download the Complete Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script is also required.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Click here to download the Csv File</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/13/part-113-adding-computers-through-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adding Users through PowerShell</title>
		<link>http://www.powershell.nu/2009/04/13/part-112-adding-users-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/13/part-112-adding-users-through-powershell/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 13:23:11 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=647</guid>
		<description><![CDATA[Now that we have our OU structure in place, we can start adding users. Since the Users contain alot of information we&#8217;ll go ahead and use the whole csv file. Let&#8217;s take a quick look at the first entry in the Csv file: PS > (Import-Csv StarTrek.csv)[0] Character : Jean-Luc Picard Position : Commanding Officer [...]]]></description>
			<content:encoded><![CDATA[<p>Now that we have our <a href="http://www.powershell.nu/2009/04/13/part-11-adding-ou-structure-using-powershell/">OU structure</a> in place, we can start adding users.</p>
<p />
Since the Users contain alot of information we&#8217;ll go ahead and use the whole <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">csv file.</a></p>
<p />
Let&#8217;s take a quick look at the first entry in the Csv file:</p>
<p />
<pre>
<strong>
PS > (Import-Csv StarTrek.csv)[0]
</strong>

Character  : Jean-Luc Picard
Position   : Commanding Officer
Rank       : Captain
Department : Main Bridge
Species    : Human
Starship   : USS Enterprise (NCC-1701-D)
Class      : Galaxy
Registry   : NCC-1701-D
Series     : Star Trek: The Next Generation
Location   : Alpha Quadrant
</pre>
<p />
Let&#8217;s start adding the Users to the Domain. First off, we need to build up a connectionstring. In the script, I build it based on </p>
<pre>
<strong>
PS > $Series = "Star Trek: The Next Generation"
PS > $Domain = "powershell.nu"
PS > $Connection = $Series.Insert(0,"LDAP://OU=Users,OU=") + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
PS > $Connection
</strong>
LDAP://OU=Users,OU=Star Trek: The Next Generation,DC=powershell,DC=nu
</pre>
<p />
Now for the Fun part. In the Csv file, some Characters don&#8217;t have any surNames and some have middle names, so this is something I have to consider in the script. Thanks to the Power of PowerShell it doesn&#8217;t have to get to complex.</p>
<p />
Step one is Checking the characters name. I use the Split() method to determine if the user has a SurName or any Middle Names.</p>
<p />
<pre>
<strong>
PS > $Character = "Jean-Luc Picard"
PS > $CharacterName = $Character.Split(" ")
PS > $CharacterName
</strong>
Jean-Luc
Picard
</pre>
<p />
In this example, Jean-Luc would be the givenName and Picard the surName. I control this in the script through a if else statement that checks if the $CharacterName contains 1 row or more.</p>
<p />
<pre>
<strong>
if (($CharacterName.Count) -le 1) {

} else {

}
</strong>
</pre>
<p />
In the case of Jean-Luc Picard, the Name contains more than 1 row, so let&#8217;s move on to the else statement.</p>
<p />
The else statement starts of by setting up giveName and SurName. the $giveName variable contain all names except the last one. So if we would use Charles Trip Tucker instead of Picard, the givenName would be &#8220;Charles Trip&#8221; and surName would be set to &#8220;Tucker&#8221;.</p>
<p />
<pre>
<strong>
PS > $givenName = $CharacterName[0..($CharacterName.Count -2)]
PS > $sn = $CharacterName[($CharacterName.Count -1)]
PS > $givenName
</strong>
Jean-Luc
<strong>
PS > $sn
</strong>
Picard
</pre>
<p />
Now that we&#8217;ve sliced and diced the characters name, we do an additional check to see if the character name will fit the sAMAccountName structure decided in <a href="http://www.powershell.nu/2009/04/11/part-10-scripting-up-an-active-directory-test-environment-through-powershell/">Part 1.0.0</a> (First 3 from giveName and first 3 from surName).</p>
<p />
<pre>
<strong>
if ($givenName.Length -lt 3 -AND $sn.Length -lt 3) {

   $Tempcn = $givenName + $sn
   $AddNum = 3 - $Tempcn.Length

   # Build Last Part Of cn

   for ($i = 0; $i -lt ($AddNum -1); $i ++) { $AddTocn += "0" }
   $AddTocn += "1"

   [string]$sAMAccountName = ($Tempcn).ToLower() + $Addtocn
   $cn = $givenName

   # Set Checker to Null

   $AddTocn = $Null

} elseif ($givenName.Length -lt 3 -OR $sn.Length -lt 3) {

   $Tempcn = $givenName + $sn

   [string]$sAMAccountName = ($Tempcn.SubString(0,6)).ToLower()
   $cn = $givenName + " " + $sn

} else {

   [string]$sAMAccountName = ($givenName.SubString(0,3)).ToLower() + ($sn.SubString(0,3)).ToLower()
   $cn = $givenName + " " + $sn
}
</strong>
</pre>
<p />
The if elseif else statement goes through the characters name and checks if it falls within parameters. If it does not, a number will be added at the end of the Name to compensate. The elseif statement takes care of users where givenName or surName has less than 3 characters and compensates this.</p>
<p />
Here&#8217;s how Jean-Luc Picard is set up now:</p>
<p />
<pre>
<strong>
PS > $givenName
</strong>
Jean-Luc
<strong>
PS > $sn
</strong>
Picard
<strong>
PS > $sAMAccountName
</strong>
jeapic
<strong>
PS > $cn
</strong>
Jean-Luc Picard
</pre>
<p />
Now that we have the sAMAccountName in place we have to check if the sAMAccountName is taken by some other User. We can do this by creating a function that looks up the users sAMAccountName from the Get-AD.ps1 script.</p>
<p />
<pre>
<strong>
function Check-sAMAccountName ([string]$Domain, [string]$User) {

   trap {  $Script:sAMAccountNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -User $User -Filter sAMAccountName | Out-Null
}
</strong>
</pre>
<p />
If the UserName already exists the script uses a While loop to determine how many sAMAccountNames are taken and when an empty sAMAccountName is found it will be used.</p>
<p />
<pre>
<strong>
if ($sAMAccountNameDoesntExist -eq $True) {

} else {

   While ($Script:sAMAccountNameDoesntExist -eq $False) {

    $LastChar = $sAMAccountName.SubString($sAMAccountName.Length -1)

    if(1..9 -Contains $LastChar) {

       $sAMAccountName = ($sAMAccountName.TrimEnd([string]$LastChar)) + ([int]$LastChar + 1)
    } else {

       $sAMAccountName = $sAMAccountName + 1
    }

    Check-sAMAccountName -Domain $Domain -User $sAMAccountName
   }
}
</pre>
<p></strong></p>
<p />
If jeapic already exists the number 1 will be appended to his sAMAccountName, and if jeapic1 already exists 1+1 ( 2) would be appended instead. Note that doing this sets the sAMAccountName to 7 characters instead of 6. If you always want to use 6 chars you could substring() out characters 1 to 5 ( 0,4 ) and build up a sAMAccountName containing only 6 characters.</p>
<p />
Now that we have a unique sAMAccountName, we want to check the Users distinguishedName. If the distinguishedName already exists then we will not Add the User, since he already exists. If not, we will go ahead and add our user. The distinguishedName check function is basically the same as the sAMAccountName checker, only differens is that it filters on distinguishedName instead.</p>
<p />
<pre>
<strong>
function Check-distinguishedName ([string]$Domain, [string]$User) {
   trap {  $Script:distinguishedNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -User $User -filter distinguishedName | Out-Null
}
</strong>
</pre>
<p>The function takes distinguishedName as an argument, so we have to build up this string. The OU structure was set up in <a href="http://www.powershell.nu/2009/04/13/part-11-adding-ou-structure-using-powershell/">Part 1.1.1</a> so the User should be in the following OU: &#8220;OU=Users,OU=Star Trek: The Next Generation,DC=powershell,DC=nu&#8221;.</p>
<p />
<pre>
<strong>
$distinguishedName = "CN=" + $cn + ",OU=Users,OU=" + $Series + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
</strong>
</pre>
<p />
If the disyinguishedName doesnt exist, we can go ahead and create the User. For safety reasons, we generate a secure password for each user that we create and store the passwords in a password file. We could obviously set all Passwords to &#8220;Password1&#8243; but that wouldn&#8217;t be fun.</p>
<p />
Here&#8217;s a simple password generator that I&#8217;ve created. Using the System.Random Class to generate random numbers.</p>
<p />
<pre>
<strong>
function Generate-Password {

  $Random = New-Object System.Random

  # Two Upper Case Characters

  [string]$Password += [char]$Random.Next(49,57)
  [string]$Password += [char]$Random.Next(65,72)

  # Two LowerCase Characters

  [string]$Password += [char]$Random.Next(97,107)
  [string]$Password += [char]$Random.Next(109,122)

  # One Special Char

  [string]$Password += [char]$Random.Next(36,43)

  # Two UpperCase Characters

  [string]$Password += [char]$Random.Next(65,72)
  [string]$Password += [char]$Random.Next(80,91)

  # One LowerCase

  [string]$Password += [char]$Random.Next(97,107)

  $Password
  $Password = $Null
}
</strong>
</pre>
<p />
Why not make it a a shorter script and randomize [char]49 to [char]122? Well, if I randomize any character from [char]49 to [char]122 i might get an &#8220;O&#8221; and numeric &#8220;0&#8243;, or &#8220;l&#8221;,&#8221;I&#8221; or numeric &#8220;1&#8243;. Users might find it hard to differentiate an O from an 0 so I&#8217;ve excluded Characters that look alike in the function. Also, if I use a for statement and loop through [char]$Random.Next(49,122) eight times, it&#8217;s not certain that i get an acceptable Password, i might all uppercase characters and AD wouldn&#8217;t accept that.</p>
<p />
Now that we have a Password generator we can create our User.</p>
<p />
<pre>
<strong>
PS > $Description = $Position + " (" + $Species + ")"
PS > $Title = $Rank
PS > $physicalDeliveryOfficeName = $Starship
PS > $userPrincipalName = $sAMAccountName + "@" + $Domain
PS > $mail = ([string]$Character).Replace(" ",".") + "@" + $Domain

PS > [string]$Password = Generate-Password

PS > $OU = [adsi] $Connection
PS > $User = $OU.Create("user", "cn=$cn")
PS > $User.Put("sAMAccountName", $sAMAccountName)
PS > $User.Put("userPrincipalName", $userPrincipalName)
PS > $User.Put("DisplayName", $cn)
PS > $User.Put("givenName", $givenName)
PS > $User.Put("sn", $sn)
PS > $User.Put("Description", $Description)
PS > $User.Put("l", $Starship)
PS > $User.Put("streetAddress",$Location)
PS > $User.Put("physicalDeliveryOfficeName", $physicalDeliveryOfficeName)
PS > $User.Put("Title", $Title)
PS > $User.Put("Department", $Department)
PS > $User.Put("Company", $Starship)
PS > $User.Put("mail", $mail)
PS > $User.SetInfo()

PS > $User.PsBase.Invoke("SetPassword", $Password)
PS > $User.PsBase.InvokeSet("AccountDisabled", $false)
PS > $User.SetInfo()
</strong>
</pre>
<p />
Now all i have to do is Collect the Generated Password in a file.</p>
<p />
<pre>
<strong>
PS > $FileName = "PasswordList " + (get-date -uformat "%Y-%m-%d") + ".txt"
PS > "$sAMAccountName,$cn,$Password" | Add-Content $FileName
</strong>
</pre>
<p />
Running the script in our test environment would look something like this:</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser01.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser01-500x318.jpg" alt="add-stuser01" title="add-stuser01" width="500" height="318" class="alignnone size-large wp-image-651" /></a></p>
<p />
If we repeat the script, the checker function fould tell us that the Users already exist:</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser02-500x318.jpg" alt="add-stuser02" title="add-stuser02" width="500" height="318" class="alignnone size-large wp-image-652" /></a></p>
<p />
Now for a peek in Active-Directory snap-in dsa.msc</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser03.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser03-500x304.jpg" alt="add-stuser03" title="add-stuser03" width="500" height="304" class="alignnone size-large wp-image-653" /></a></p>
<p />
And Finally, let&#8217;s look closer on Captain Jean-Luc Picard and see if the Values specified in the script are set.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser04.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser04.jpg" alt="add-stuser04" title="add-stuser04" width="406" height="485" class="alignnone size-full wp-image-654" /></a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/passwordlist.txt">And here&#8217;s an example on the Autogenerated Password List.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stuser.ps1">Click Here to Download the Complete Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script is also required.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Click here to download the Csv File</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/13/part-112-adding-users-through-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adding Ou Structure using Powershell</title>
		<link>http://www.powershell.nu/2009/04/13/part-11-adding-ou-structure-using-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/13/part-11-adding-ou-structure-using-powershell/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 10:03:34 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=626</guid>
		<description><![CDATA[Starting of, we need to set up a couple of OrganizationalUnits in our test environment. Following the structure set up in Part 1.1.0: Organizational Unit Structure ou = Series l = Location Description = Starship Child OU: Computers Child OU: Groups Child OU: Users The first step in scripting up a OU structure from based [...]]]></description>
			<content:encoded><![CDATA[<p>Starting of, we need to set up a couple of OrganizationalUnits in our test environment. Following the structure set up in <a href="http://www.powershell.nu/2009/04/11/part-10-scripting-up-an-active-directory-test-environment-through-powershell/">Part 1.1.0</a>:</p>
<p />
<h3>Organizational Unit Structure</h3>
<ul>
<li>ou = Series</li>
<li>l = Location</li>
<li>Description = Starship</li>
<li>Child OU: Computers</li>
<li>Child OU: Groups</li>
<li>Child OU: Users</li>
</ul>
<p />
The first step in scripting up a OU structure from based on the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">StarTrek Csv file</a> is to collect the information through PowerShell. Since the Csv file contains 68 rows of information and 10 different columns, we want to retrieve only information that we need to create a Csv Structure. The columns of interest are: Series, Starship and Location. Using Import-Csv in combination With Select-Object gets all entries matching this.</p>
<p />
<pre>
<strong>
PS > Import-Csv StarTrek.csv | Select-Object Series, Starship, Location
</strong>

Series                         Starship                    Location
------                         --------                    --------
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
</pre>
<p />
Now we,ve managed to retrieve the specified columns and rows. Next we need to narrrow the list down to only unique entries. We can achieve this through the -Unique SwitchParameter.</p>
<p />
<pre>
<strong>
PS > Import-Csv .StarTrek.csv | Select-Object Series, Starship, Location -Unique
</strong>

Series                         Starship                    Location
------                         --------                    --------
Star Trek: The Next Generation USS Enterprise (NCC-1701-D) Alpha Quadrant
Star Trek: Deep Space Nine     Deep Space Nine             Alpha Quadrant
Star Trek: Voyager             USS Voyager (NCC-74656)     Delta Quadrant
Star Trek: Enterprise          Enterprise (NX-01)          Alpha Quadrant
</pre>
<p />
Now that we&#8217;ve narrowed down our list, we can start creating the OU structure.</p>
<p />
The OU:s Name should be &#8220;Series&#8221;, so the structure that we&#8217;re looking for is:</p>
<p />
<ul>
<li>Star Trek: The Next Generation</li>
<li>Star Trek: Deep Space Nine</li>
<li>Star Trek: Voyager</li>
<li>Star Trek: Enterprise</li>
</ul>
<p />
But how do we know that these OU:s dont already exist in our Environment ? We have to check this in some way so we need a checker that makes sure that the OU doesn&#8217;t exist. This is an excellent oppurtunity to use the Get-AD.ps1 script that I wrote. The checker is rather simple, it consists of a function that sets a variable to $True if the OU does not exist.</p>
<p />
<pre>
<strong>
function Check-distinguishedName ([string]$Domain, [string]$OU) {

	trap {  $Script:distinguishedNameDoesntExist = $True ; continue }
	.\Get-AD.ps1 -Domain $Domain -OU $OU -Filter distinguishedName | Out-Null
}
</strong>
</pre>
<p />
The Variable $Script:distinguishedNameDoesntExist is set to $True if we test the function on a non existing OU. Here&#8217;s an example on how it works:</p>
<p />
<pre>
<strong>
PS > Check-distinguishedName -Domain powershell.nu -OU "OU=Domain Controllers,DC=powershell,DC=nu"
PS > $distinguishedNameDoesntExist
</strong>
</pre>
<p />
Since Domain Controllers Exist, the variable $distinguishedNameDoesntExist is not set to anything. Running the same function on a OU that does not exist:</p>
<p />
<pre>
<strong>
PS > Check-distinguishedName -Domain powershell.nu -OU "OU=Non Existing OU,DC=powershell,DC=nu"
PS > $distinguishedNameDoesntExist
</strong>
True

<strong>
PS > $distinguishedNameDoesntExist = $Null
</strong>
</pre>
<p />
This time the variable $distinguishedNameDoesntExist was set to True, which means that the OU does not exist and it&#8217;s available for creation. I also set the Variable to $Null so that i can reuse the function.</p>
<p />
Moving on. If the $distinguishedNameDoesntExist equals $True we can start building up the OU Structure. In the script, there&#8217;s a paramter called -Domain which takes the domain name as an argument. In my examples I&#8217;m going to use the powershell.nu domain. Setting this as an argument is similar to creating a Variable holding the domain name:</p>
<pre>
<strong>
PS > $Domain = "powershell.nu
PS > $Domain
</strong>
powershell.nu
</pre>
<p />
With this information we can create a Connection string that we can use when connecting to Active-Directory. We can make use of the methods() withing System.String to alter the string as we want it. I&#8217;m using Replace() and Insert() to get the result I want:</p>
<p />
<pre>
<strong>
PS > $Connection = ($Domain.Replace(".",",DC=")).Insert(0,"LDAP://DC=")

PS > $AD = [adsi] $Connection
PS > $AD
</strong>

distinguishedName
-----------------
{DC=powershell,DC=nu}
</pre>
<p />
Now that we&#8217;ve set up a connection we can start creating an OU. It&#8217;s pretty straight forward, nothing fancy here:</p>
<p />
<pre>
<strong>
PS > $OU = $AD.Create("OrganizationalUnit", "ou=$Series")
PS > $OU.SetInfo()

PS > $OU.put("l", $Location)
PS > $OU.put("Description", $Starship)
PS > $OU.setinfo()
</strong>
</pre>
<p />
When creating Child OU:s, we need to alter the Connection string so that we connect to the OU that we&#8217;ve just created, here&#8217;s an example on doing that:</p>
<p />
<pre>
<strong>
$NewConnection = "LDAP://OU=" + $Series + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
$NewOU = [adsi]$NewConnection
</strong>
</pre>
<p />
Now we can start creating Child OU:s that are structured after our purpose:</p>
<p />
<pre>
<strong>
$Users = $NewOU.Create("OrganizationalUnit", "ou=Users")
$Users.SetInfo()

$Users.put("l", $Location)
$Users.put("Description", $Starship)
$Users.setinfo()
</strong>
</pre>
<p />
This describes the steps that I&#8217;ve set up in the Script. Running the script in the test environment would look like this:</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou01.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou01-500x318.jpg" alt="add-stou01" title="add-stou01" width="500" height="318" class="alignnone size-large wp-image-627" /></a></p>
<p />
If i repeat the script, the Check function finds that the top OU:s already exists and the following is returned to the host:</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou02.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou02-500x319.jpg" alt="add-stou02" title="add-stou02" width="500" height="319" class="alignnone size-large wp-image-628" /></a></p>
<p />
Finally, taking a peek in dsa.msc.</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou03.jpg"><img src="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou03-500x292.jpg" alt="add-stou03" title="add-stou03" width="500" height="292" class="alignnone size-large wp-image-629" /></a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/add-stou.ps1">Click Here to Download the Complete Script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script is also required.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Click here to download the Csv File</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/13/part-11-adding-ou-structure-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scripting up an Active-Directory Test Environment through PowerShell</title>
		<link>http://www.powershell.nu/2009/04/11/part-10-scripting-up-an-active-directory-test-environment-through-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/11/part-10-scripting-up-an-active-directory-test-environment-through-powershell/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 21:26:05 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=613</guid>
		<description><![CDATA[The first step in building up a Test Environment is analyzing the data that we have to work with. In this case, the Star Trek Reference Csv file. Since the Csv file doesn&#8217;t say sAMAccountName or organizationalUnit I&#8217;ve to set up a routine for handling this. Based on the information, I&#8217;ve set up the following [...]]]></description>
			<content:encoded><![CDATA[<p>The first step in building up a Test Environment is analyzing the data that we have to work with. In this case, the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Star Trek Reference Csv file.</a></p>
<p />
Since the <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Csv file</a> doesn&#8217;t say sAMAccountName or organizationalUnit I&#8217;ve to set up a routine for handling this. Based on the information, I&#8217;ve set up the following rules:</p>
<p />
<h3>User Information</h3>
<ul>
<li>Common Name = Character Name</li>
<li>sAMAccountName = First 3 Characters from givenName and surName</li>
<li>userPrincipalName = sAMAccountName and Domain</li>
<li>DisplayName = Character Name</li>
<li>givenName = First part of Character Name</li>
<li>surName = Last part of Character Name</li>
<li>Description = Postition + Species</li>
<li>l = Starship</li>
<li>streetAddress = Location</li>
<li>physicalDeliveryOfficeName = Starship</li>
<li>Title = Rank</li>
<li>Department = Department</li>
<li>Company = Starship</li>
<li>mail = CharacterName and Domain</li>
</ul>
<p />
<h3>Computer Information</h3>
<ul>
<li>Common Name = Starship</li>
<li>sAMAccountName = Registry</li>
<li>Location = Location</li>
<li>Description = Starship</li>
</ul>
<p />
<h3>Group Information</h3>
<ul>
<li>Common Name = Position</li>
<li>Description = Position</li>
<li>sAMAccountName = Position</li>
</ul>
<p />
<h3>Group MemberShip</h3>
<ul>
<li>Members = Based on Users Position</li>
</ul>
<p />
<h3>Organizational Unit Structure</h3>
<ul>
<li>ou = Series</li>
<li>l = Location</li>
<li>Description = Starship</li>
<li>Child OU: Computers</li>
<li>Child OU: Groups</li>
<li>Child OU: Users</li>
</ul>
<p />
<h3>Users HomeFolder</h3>
<ul>
<li>HomeFolder = Based on Users sAMAccountName and a defined Path</li>
</ul>
<p />
Most of these steps may seem trivial and easy to script up based on a <a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Csv file</a>, but there are numerous steps to consider, for example: some Characters, such as T&#8217;pol and Phlox don&#8217;t have any surnames (at least not any surnames recorded in the Vulcan Database) so these names must be handled in the script. Another step to consider are sAMAccountNames conatining a invalid set of characters and so on. I&#8217;m going to go through each step of the scripts and explain in detail how to avoid the exceptions that we might encounter in each new post regarding the migration.</p>
<p />
The Scripts will also use the <a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">Get-AD.ps1 script</a> when chekcing if objects exist in the Domain.</p>
<p />
Next step is Part 1.1: Adding Ou Structure using Powershell</p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/02/get-ad.ps1">The Get-AD.ps1 script.</a></p>
<p />
<a href="http://www.powershell.nu/wp-content/uploads/2009/04/startrek.csv">Here&#8217;s a link to the Csv File refered to in this post.</a></p>
<p />
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/11/part-10-scripting-up-an-active-directory-test-environment-through-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Migrate From Windows Server 2003 to Windows Server 2008 R2 and Windows 7 Using PowerShell</title>
		<link>http://www.powershell.nu/2009/04/11/part-00-migrate-from-windows-server-2003-to-windows-server-2008-r2-and-windows-7-using-powershell/</link>
		<comments>http://www.powershell.nu/2009/04/11/part-00-migrate-from-windows-server-2003-to-windows-server-2008-r2-and-windows-7-using-powershell/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 20:21:54 +0000</pubDate>
		<dc:creator>Niklas Goude</dc:creator>
				<category><![CDATA[Active-Directory]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Server 2008 R2]]></category>

		<guid isPermaLink="false">http://www.powershell.nu/?p=597</guid>
		<description><![CDATA[Windows 7 and Windows Server 2008 R2 are just around the Corner. Beta Versions are very promising and, as it seems, the best OS that Microsoft has ever done! This is something that&#8217;s not easy to accomplish in the Beta stage of an OS, but Microsoft has pulled it off! The comparisons that I&#8217;ve made [...]]]></description>
			<content:encoded><![CDATA[<p>Windows 7 and Windows Server 2008 R2 are just around the Corner. Beta Versions are very promising and, as it seems, the best OS that Microsoft has ever done! This is something that&#8217;s not easy to accomplish in the Beta stage of an OS, but Microsoft has pulled it off! The comparisons that I&#8217;ve made with previous Operating Systems are entirely based on self observations.</p>
<p />
I&#8217;m hoping that alot of people share my enthusiasm regarding the Windows 7 technologies and I would like to share my Beta tests with the Microsoft Community. I&#8217;m aware that a few commands and techniques may vary from the final Release so the following posts might not be accurate when the final build of Windows 7 / 2008 R2  are released. I will try to keep these posts up to date and follow Microsfts development of Windows 7 and Windows Server 2008 R2.</p>
<p />
<h3>Scenraio</h3>
<p />
You have a Windows 2003 Active-Directory Environment that you want to Updgrade / migrate to a Windows 2008 R2 environment. Microsoft have a great tool called <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=ae279d01-7dca-413c-a9d2-b42dfb746059&#038;displaylang=en=">ADMT (Active Directory Migration Tool)</a> which allows you to perform the appropriate steps when migration from Windows 2003 to Windows 2008. But since this is a PowerShell Blog, I&#8217;m going to show examples on doing all these steps through PowerShell. I&#8217;m planning on showing the following steps:</p>
<p />
<strong>Windows 2003</strong></p>
<ul>
<li><a href="http://www.powershell.nu/2009/04/11/part-10-scripting-up-an-active-directory-test-environment-through-powershell/">Scripting up a Active-Directory Test Environment through PowerShell</a></li>
<li><a href="http://www.powershell.nu/2009/04/13/part-11-adding-ou-structure-using-powershell/">Adding Ou Structure using Powershell</a></li>
<li><a href="http://www.powershell.nu/2009/04/13/part-112-adding-users-through-powershell/">Adding Users through PowerShell</a></li>
<li><a href="http://www.powershell.nu/2009/04/13/part-113-adding-computers-through-powershell/">Adding Computers through PowerShell</a></li>
<li><a href="http://www.powershell.nu/2009/04/15/part-114-adding-groups-through-powershell/">Adding Groups Through PowerShell</a></li>
<li><a href="http://www.powershell.nu/2009/04/16/part-115-adding-group-membership-through-powershell/">Adding Group Membership Through PowerShell</a></li>
<li><a href="http://www.powershell.nu/2009/04/27/part-116-adding-homefolder-through-powershell/">Adding HomeFolder Through PowerShell</a></li>
<li><a href="http://www.powershell.nu/2009/06/05/joining-a-windows-7-client-to-a-domain-through-powershell/">Joining a Windows 7 Client to a Domain through PowerShell</a></li>
</ul>
<p />
<strong>Windows 2008 R2</strong></p>
<ul>
<li>Gathering information from a 2003 Active Directory Domain through PowerShell</li>
<li>Migarting OU Structure to a Active-Directory 2008 R2 Server Through PowerShell</li>
<li>Migarting Users to a Active-Directory 2008 R2 Server Through PowerShell</li>
<li>Migarting Computers to a Active-Directory 2008 R2 Server Through PowerShell</li>
<li>Migarting Groups to a Active-Directory 2008 R2 Server Through PowerShell</li>
<li>Migarting Group Membership to a Active-Directory 2008 R2 Server Through PowerShell</li>
<li>Migrating HomeFolders to a Active-Directory 2008 R2 Server Through PowerShell</li>
<li>Migrating a Windows 7 Client to a Active-Directory 2008 R2 Server Through PowerShell</li>
<p></lu></p>
<p />
Note that all steps are built from a test environment and may require slight adjustments to fit your environmnent.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershell.nu/2009/04/11/part-00-migrate-from-windows-server-2003-to-windows-server-2008-r2-and-windows-7-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
