Posts RSS Comments RSS 253 Posts and 411 Comments till now

Command line guide for Server Core

I have been doing a lot of server core builds as of late and here are list of commands I have found useful.

Set Interface ID
netsh interface set interface name=”Old Name” newname=”New Name”

Set IP
netsh interface ipv4 set address name=”<ID>” source=static address=<StaticIP> mask=<SubnetMask> gateway=<DefaultGateway>

Set DNS
netsh interface ipv4 add dnsserver name=”<Interface ID>” address=<DNSIP> index=1
netsh interface ipv4 add dnsserver name=”ExtraNet” address=1.1.1.1 index=1

Set Proxy
netsh winhttp set proxy proxy-server=”http=myproxy;https=sproxy:88″ bypass-list=”*.contoso.com”

Set Computer Name
# Use hostname from the command prompt to get current name
netdom renamecomputer %COMPUTERNAME% /NewName:<NewComputerName>

Join Domain
netdom join %COMPUTERNAME% /domain:<DomainName> /userd:<UserName> /passwordd:*

Set the Default scripting engine to cscript
cscript //H:Cscript

To Activate via KMS server
slmgr -ipk YQGMW-MPWTJ-34KDK-48M3W-X4Q6V
slmgr -skms <KMSServer>:1688
slmgr -ato
slmgr -ato  # Yes twice

Running Windows Update
http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx

Disable Firewall
netsh advfirewall set allprofiles state off

Allow Remote Desktop
netsh advfirewall firewall set rule group=”remote desktop” new enable=yes

Allow Remote Administration
netsh advfirewall firewall set rule group=”Remote Administration” new enable=yes

Allow Remote Firewall Administration
netsh advfirewall firewall set rule group=”Windows Firewall Remote Management” new enable=yes

Allow Ping
netsh firewall set icmpsetting 8

Connect to remote Server Core w/ out domain (this is done on management box)
cmdkey /add:<ServerCore> /user:<UserName> /pass:<password>

Export Security Policy
secedit /export /db secedit.sbd /cfg <Policy File Name>

Import Security Policy
secedit /configure /db secedit.sdb /cfg sctest.inf /overwrite

Allow Remote Disk Management
THIS HAS to be done on BOTH SIDES!!!
netsh advfirewall firewall set rule group=”Remote Volume Management” new enable=yes

Allow Remote Device Mgr
1.    On a Windows Vista or full Server installation, start the Group Policy Object MMC snap-in
2.    Connect to the Server Core installation
3.    Navigate to Computer Configuration\Administrative Templates\Device Installation
4.    Enable “Allow remote access to the PnP interface”
5.    Restart the Server Core installation
or
Via GPO

Things to Note:
– Firewall rules will have to be re-adjusted after Domain Join

Good Links for more info
Server Core Installation Option of Windows Server 2008 Step-By-Step Guide:
http://technet.microsoft.com/en-us/library/cc753802.aspx#bkmk_managingservercore

Windows Server 2008 Network Shell (Netsh) Technical Reference:
http://www.microsoft.com/downloads/details.aspx?FamilyID=f41878de-2ee7-4718-8499-2ef336db3df5

-Volume Activation 2.0 Deployment Guide
http://technet.microsoft.com/en-us/library/cc303280.aspx#

NOTE: I am not crazy… these Product keys are public record. They simply tell the host to require a KMS server to activate.
Product SKUs for Volume Licensing
==================================
Operating System Edition || Product Key
Windows Vista Business || YFKBB-PQJJV-G996G-VWGXY-2V3X8
Windows Vista Business N || HMBQG-8H2RH-C77VX-27R82-VMQBT
Windows Vista Enterprise || VKK3X-68KWM-X2YGT-QR4M6-4BWMV
Windows Vista Enterprise N || VTC42-BM838-43QHV-84HX6-XJXKV
Windows Server 2008  Datacenter || 7M67G-PC374-GR742-YH8V4-TCBY3
Windows Server 2008 Datacenter without Hyper-V || 22XQ2-VRXRG-P8D42-K34TD-G3QQC
Windows Server 2008 for Itanium-Based Systems || 4DWFP-JF3DJ-B7DTH-78FJB-PDRHK
Windows Server 2008 Enterprise || YQGMW-MPWTJ-34KDK-48M3W-X4Q6V
Windows Server 2008 Enterprise without Hyper-V || 39BXF-X8Q23-P2WWT-38T2F-G3FPG
Windows Server 2008 Standard  || TM24T-X9RMF-VWXK6-X8JC9-BFGM2
Windows Server 2008 Standard without Hyper-V ||  W7VD6-7JFBR-RX26B-YKQ3Y-6FFFJ
Windows Web Server 2008  || WYR28-R7TFJ-3X2YQ-YCY4H-M249D

More from Mr Jay Closky


More DNS settings via Registry
NOTE: use regedit.exe or reg.exe to configure

The primary DNS suffix is stored in the registry in the following location:

HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

You might want to change the values for the following registry keys:

Domain (REG_SZ)
This value contains the DNS Suffix for the Network Connection on your Server Core box. Changing it will immediately change your DNS Suffix.

SearchList (REG_SZ)
This value contains the DNS Suffix search order list. You can add DNS Suffixes here to use when searching other servers.

NetBIOS over TCP/IP:
====================
In Server Core installations of Windows Server 2008 NetBIOS? over TCP/IP (NetBT? is enabled by default when you configure IPv4 manually. You can disable it by editing the registry. The NetBIOS over TCP/IP setting is stored in the following location:

HKLM\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces

Underneath this location you’ll find a registry key (depicted as a folder) starting with tcpip_ followed by a GUID for every network connection. Find the network connection for which you want to disable NetBIOS over TCP/IP. (NetBT) In the value you’d find a REG_DWORD value named NetBiosOptions?. This value would have a value of 2. (enabled)

To disable NetBIOS over TCP/IP change the value to 0. (disabled)

DNS REGISTRATION OPTIONS:
========================
On a full installation of Windows Server 2008 there are a few options for DNS registration on the DNS tab of the advanced properties of the IP version4 configuration of a Network Connection.

In Server Core you can achieve these settings as well, but only when you set the DNS Server. (fortunately you can set it as many times as you like) Also, you have to specify DNS Suffixes first. When you set the DNS Server you can optionally use the register= switch at the end of the command. The three switch options are none, primary and both.

None
Specifying Register=None would result in your Server Core box not registering its DNS name with any of its DNS suffixes. This effectively disables Dynamic DNS Registration.

Primary
With Register=Primary your Server Core installation will register its hostname together with its primary DNS suffix with the DNS Server you set.

Both
When you tell your Server Core box to Register=Both it will register its hostname with its primary DNS suffix and the connection specific DNS suffix with the DNS Server you set.

How to get the elusive developer license for XenApp

Have you heard stories of the mystical developer license for XenApp, but couldn’t find it?
Have you ever wanted to install XenApp just to test or play with?

These question often plague my readers, but below… below you will find “The Link.” Beware! This is no ordinary link. This is a magical link that will take you on a journey. A journey in which you will find the treasure. The treasure that will finally let you take a hold of this mystical license.

Let the Quest be fulfilled! How to get an eval or a developer license for Citrix XenApp

My R2/Win7 Experience

I have now been using Windows 2008 R2 for 2 months and Windows 7 client for about a month (two weeks on my production laptop) and I have to say I am thoroughly impressed. I have beta tested every MS OS since 2000 and this is the first time I can honestly say I am excited.

Lets start with Window 2008 R2.
This OS is rock solid. They could release it now and I think it would fair very well. It has enough of a feature increase it is worth the upgrade. I was impressed with 2008 but R2 simply blows it away. It is quicker and I love the taskbar. I am a bit OCD when it comes to my computer and R2 caters to this quite nicely. I wouldn’t be fooling anyone if I didn’t say I was excited about the native Powershell support, but I think that goes without mention. All and all… it is has exceeded any expectations I had. I haven’t had a chance to play with the advance functionality that was introduced, but I plan to get to that this week.

The client…
All I can say is WOW! I think this is first time MS changed the interface in a way that was simply just better. We all know MS has a way of changing the interface that drives people crazy, but this time the changes are relatively noninvasive and worth the aggravation of learning. They truly help efficiency and finally allow keyboard jockeys to put down the mouse and move seamlessly around the screen and apps with keyboard strokes. Some of the new changes seem trivial and just eye candy, but once you get a hold of the usefulness of the new GUI it will change the way you use your computer. GUI changes aren’t the only thing that is noticeable in Win7, the performance is awesome and everything seems snappier. I haven’t got to use the enterprise usability yet, but I hope to get a beta going at work.

Both
The last thing and this goes for both R2/Win7 is User Account Control (UAC.) This was introduced in Vista and while the idea was good, the execution was… ummmm, less than grand. The new OS’s continue down the UAC path (as they should) but have made the process more intelligent and it doesn’t annoy you as much.

The Future
These products are both Beta1 and I would guess a year or so off, but if the final product is even as good as the beta… it will be awesome. Shortly, I hope to start reviewing all the new Powershell cmdlets (+100) soon.

Testing AD LDS (ADAM) replication with Powershell

Earlier this month I had a discussion with Laura (of AD Cookbook fame) regarding ADLDS and how to test convergence. After a few minutes I remembered I had a AD convergence script I wrote a while back found HERE. With a little tweaking (specifically discoverability) we converted it to test ADLDS as well. Below you will fine the result.

Parameters
Server: The ADLDS/ADAM server that hosts the application partition you want to test
DN: The distinguished name of the application partition you want to test (will try to discover)
Port: Port ADLDS/ADAM list on (Default 389)
Table [switch]: A switch that outputs an object with the results.

Note: Please feel free to provide any feedback you have regarding this. I do not use ADLDS or ADAM so other than my test environment I really cannot play with this.

The Code
Test-LDSReplication.ps1


 

Param($Server = $Env:ComputerName,
      $DN,
      $Port = "389",
      [switch]$table
      )

function Ping-Server {
   Param([string]$srv)
   $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’ and Timeout=1000"
   if($pingresult.statuscode -eq 0) {$true} else {$false}
}

$DirectoryServer = "{0}:{1}" -f $Server,$Port

$Context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer",$DirectoryServer)
$ADAM = [System.DirectoryServices.ActiveDirectory.AdamInstance]::GetAdamInstance($context)

if(!$DN)
{
    $AppPartition = $ADAM.ConfigurationSet | %{$_.ApplicationPartitions} | Select-Object -first 1
    $DN = $AppPartition.Name
    $dclist = $AppPartition.DirectoryServers | ?{$_.HostName -notmatch $Server}
}
else
{
    $dclist = $ADAM.ConfigurationSet.AdamInstances | ?{($_.Partitions -contains $DN) -and ($_.HostName -notmatch $Server)}
}

if($table)
{
    $DCTable = @()
    $myobj = "" | select Name,Time
    $myobj.Name = ("$Server [SOURCE]").ToUpper()
    $myobj.Time = 0.00
    $DCTable += $myobj
}

$timestamp = [datetime]::Now.ToFileTime().ToString()
Write-Host "`n  Modifying wwwHomePage Attribute on Object [$DN] on [$DirectoryServer] with value [$timestamp]"
$object = ([ADSI]"LDAP://$DirectoryServer/$DN")
$object.wWWHomePage = $timeStamp
$object.SetInfo()
$objectDN = $object.distinguishedname
Write-Host "  Object [$objectdn] Modified! `n"

$start = Get-Date

$i = 0

Write-Host "  Found [$($dclist.count)] LDS replicas"
$cont = $true

While($cont)
{
    $i++
    $oldpos = $host.UI.RawUI.CursorPosition
    Write-Host "  =========== Check $i ===========" -fore white
    start-Sleep 1
    $replicated = $true
    foreach($dc in $dclist)
    {
        if($server -match $dc.HostName){continue}
        if(ping-server $dc.HostName)
        {
            $DCServer = "{0}:{1}" -f $dc.HostName,$dc.LdapPort
            $object = [ADSI]"LDAP://$DCServer/$dn"
            if($object.wwwHomePage -eq $timeStamp)
            {
                Write-Host "  – $DCServer Has Object Description [$dn]" (" "*5) -fore Green
                if($table -and !($dctable | ?{$_.Name -match $dc.HostName}))
                {
                    $myobj = "" | Select-Object Name,Time
                    $myobj.Name = $dc.HostName.ToUpper()
                    $myobj.Time = ("{0:n2}" -f ((Get-Date)$start).TotalSeconds)
                    $dctable += $myobj
                }
            }
            else{Write-Host "  ! $($dc.HostName.ToUpper()) Missing Object [$dn]" -fore Red;$replicated  = $false}
        }
        else
        {
            Write-Host "  ! $($dc.HostName.ToUpper()) Failed PING" -fore Red
            if($table -and !($dctable | ?{$_.Name -match $dc}))
            {
                $myobj = "" | Select-Object Name,Time
                $myobj.Name = $dc.HostName.ToUpper()
                $myobj.Time = "N/A"
                $dctable += $myobj
            }
        }
    }
    if($replicated){$cont = $false}else{$host.UI.RawUI.CursorPosition = $oldpos}
}

$end = Get-Date
$duration = "{0:n2}" -f ($end.Subtract($start).TotalSeconds)
Write-Host "`n    Took $duration Seconds `n" -fore Yellow

if($table){$dctable | Sort-Object Time}

Regular Expression Info and Tips for Powershell

One of the most useful tools a scripter has at their disposal is Regular Expressions. The problem is that regular expressions can seem like Greek and for most folks learning them can seem an impossible task. I hope this blog post provides those people some hope as well as some tools they can use to tackle this mountain one foot at a time.

NOTE: I would like to make this blog entry as dynamic as possible, so if you have your own tips… let me know and I will add them.


Everyone is different, but this is how I went about learning Regular Expressions

  • Phase one: Learn EXACTLY what a regular expression is and what it can and can NOT do.
  • Phase two: Learn the syntax. I printed out the RegEx Cheet Sheet and use it daily.
  • Phase three: Find a purpose. I find if I actually have a problem I spend more energy on learning.
  • Phase four: Create a simple Regular Expression.
  • Phase five: Build on your Regular Expression.
  • Phase six: Trouble shooting the Regular Expression.

Useful Tips:

  • First things first… Click here and watch the vids
  • Keep a cheat sheet close at hand!
  • Take them in small bites. I hope to blog in detail about this later, but lets just say string concatenation is your friend
  • Keep it simple!
  • $matches is your friend! $matches is an object that Powershell creates when you make a RegEx call (like -match.)
  • Google It. Chances are there is Regex already out there for what you need.
  • Using Lables can save you time by extracting certain data and making it a property on $matches.
  • RichardP from IRC says “Dont eat yellow snow?” Apparently he has experience in this area.

Online Vids:
This is GREAT stuff provided by Shay (aka scriptfanatic)

Good Blog Entries:
MoW at it again.

References:
RegEx Cheet Sheet (my Favorite)
Regular-Expressions.info
Regular Expression Library

Online Regex Checkers:
RegEx Tester (my Favorite)
Regular Expression Library Tester

Books:
Mastering Regular Expressions (my Favorite)
Regular Expression Recipes for Windows Developers

Tools:
Expresso
RegEx Buddy

Getting users group membership (tokengroups)

Around the same time as I wrote my Linked-Value Attribute script I also came up with this little gem. It also uses a constructed attribute provided with Windows 2003 called “tokengroups.” (Did I mention this includes recursive groups?)

Effectively it gets the attribute which returns an array of SIDs (in byte array form) for each group. I then use a function I posted about eariler called ConvertTo-Name to convert that BYTE array into a friendly group name we humans like.

Parameters:

  • – Account: Can be User samAccountName or DN of the user
  • – Verbose: Enables verbose output

More Info:
You may notice the GetInfoEx call I make on the user object. This is because tokengroups is not an actual attribute and does not get “populated” until you specifically request it. The GetInfoEx does exactly that.

Links:
MSDN: GetInfoEx
MSDN: tokenGroups

Get-TokenGroups.ps1

Param($Account,[switch]$Verbose)

if($verbose){$verbosepreference="Continue"}

Write-Host
Write-Verbose " – Account: $Account"
Write-Verbose " – Verbose: $Verbose"

function ConvertTo-Name($sid,[switch]$FromByte) {
    if($FromByte)
    {
        $ID = New-Object System.Security.Principal.SecurityIdentifier($sid,0)
    }
    else
    {
        $ID = New-Object System.Security.Principal.SecurityIdentifier($sid)
    }
    if($ID)
    {
        $User = $ID.Translate([System.Security.Principal.NTAccount])
        $User.Value
    }
}
function GetDNfromName{
    Param($name)
    $root = [ADSI]""
    $filter = "(sAMAccountName=$name)"
    $props = @("distinguishedName")
    $Searcher = new-Object System.DirectoryServices.DirectorySearcher($root,$filter,$props)
    $Searcher.FindOne().properties.distinguishedname
}

if($Account -notmatch "CN=(.*),((OU|DC)=\w*)*")
{
    Write-Verbose " + Getting User DN for [$Account]"
    $Account = GetDNfromName $Account
    Write-Verbose "   – GetDNfromName returned [$Account]"
}

Write-Verbose " – Getting User Object"
$UserAccount = [ADSI]"LDAP://$Account"

Write-Verbose " – Calling GetInfoEx"
$UserAccount.GetInfoEx(@("tokengroups"),0)

Write-Verbose " – Getting tokengroups"
$groups = $UserAccount.Get("tokengroups")

Write-Verbose " + Processing Groups"
foreach($group in $groups)
{
    $GroupName = ConvertTo-Name $group -FromByte
    Write-Verbose "   – Found group [$GroupName]"
    $GroupName
}

Write-Host

Dealing with Parameters in Powershell

I often get asked to review code for people and I often see them use $args for argument parsing (most often with VBScript converts.) While there is nothing wrong with that method, I do not believe it is the best way. Powershell has numerous ways to pass data to scripts/functions. Today, after helping a friend understand the differences between them, I decided it would be good to blog about it.


Let’s take a look at the different ways scripts/functions can take input.



You can pass data by position parameters:

.\myscript.ps1 filename.txt corp.lab

You can pass data by named parameters:

.\myscript.ps1 -list filename.txt -domain corp.lab

Finally, you can pipe data in:

get-content filename.txt | .\myscript.ps1 -domain corp.lab


That is great… but what would the code look like foreach of these?


There is little difference between a script and a function so I will illustrate using functions.
To use positional parameters

Example: PassByPosition filename.txt corp.lab

function PassByPosition{
  "FileName: {0}" -f $args[0]
  "Domain: {0}" -f $args[1]
}



To process Named parameters you use the Param() statement included in Powershell

Example: PassByName -list filename.txt -domain corp.lab

function PassByName{
    Param($FileName,$DomainName)
    "FileName: {0}" -f $FileName
    "Domain: {0}" -f $DomainName
}



To process piped data you can do something like

Example: get-content filename.txt | PassByPipe corp.lab

function PassByPipe{
    if($input)
    {
        foreach($val in $input)
        {
            "FileName: {0}" -f $val
            "Domain: {0}" -f $args[0]
        }
    }
}

NOTE: This is not only way to process piped input, but it is the simplest example. If you would like to see a more efficient way to process look HERE.


It gets REALY cool when using them together


Using the script below you can do any of these 

UseAllThree filename.txt corp.lab
UseAllThree -list filename.txt -domain corp.lab
get-content filename.txt | UseAllThree -domain corp.lab

function UseAllThree{
    Param($FileName,$DomainName)
    if($input)
    {
        foreach($val in $input)
        {
            "FileName: {0}" -f $val
            "Domain: {0}" -f $args[0]
        }
    }
    else
    {
        "FileName: {0}" -f $FileName
        "Domain: {0}" -f $DomainName
    }
}

 

We can even have default values for the Parameters


Using the script below you can do any of these 

UseAllThreewithDefaults filename.txt
UseAllThreewithDefaults -list filename.txt
get-content filename.txt | UseAllThreewithDefaults

function UseAllThreewithDefaults{
    Param($FileName = "FileName.txt",$DomainName = "Corp.lab")
    if($input)
    {
        foreach($val in $input)
        {
            "FileName: {0}" -f $val
            "Domain: {0}" -f $DomainName
        }
    }
    else
    {
        "FileName: {0}" -f $FileName
        "Domain: {0}" -f $DomainName
    }
}

Test-CitrixHotfix

I often find the need to compare the state of my PS servers. This little script allows me to find all the Citrix hotfixes for a group of server(s), or list of server(s) that have a specific hotfix.

Parameters:
$File: The name of the file which contains a list of servers
$Filter: Name or Regex of the Hotfix(es) to return
$Server: Name of the server to check

What it returns (a custom object):
ServerName: Name of the Server with the Hotfix(es)
Hotfixes: List of hotfix names [String[]]
RawObjects: Array of MFCOM MetaFrameHotfix objects

Examples
To List all the Hotfixes on a list of servers
.\Test-CitrixHotfix.ps1 ServerList.txt

To List a Specific hotfix on a list of servers
.\Test-CitrixHotfix.ps1 ServerList.txt -filter PSE450W2K3021

To List all the hotfixes on a specific Server
.\Test-CitrixHotfix.ps1 -s Server1

To List a specific hotfix for a specific server
.\Test-CitrixHotfix.ps1 -s Server1 -filter PSE450W2K3021

The Code:

Param($file,$filter=".*",$server)

Function Ping-Server {
   Param([string]$server)
   $pingresult = Get-WmiObject win32_pingstatus -f "address=’$Server’"
   if($pingresult.statuscode -eq 0) {$true} else {$false}
}
Function Check-CitrixHotfix{
    Param([string]$server)
    $mf = New-Object -ComObject MetaframeCOM.MetaframeFarm
    $mf.Initialize(1)
    $srv = $mf.GetServer2(6,$server)
    $list = $srv.winServerObject2.hotfixes | ?{$_.Name -match $filter}
    $list
}

if($file -and (Test-Path $file))
{
    $servers = cat $file
}
if($input)
{
    $servers = $input
}

if($server){$servers += $server}

foreach($srv in $servers)
{
    if(Ping-Server $srv)
    {
        $hotfixes = Check-CitrixHotfix $srv
        $myobj = "" | Select-Object ServerName,Hotfixes,RawObjects
        $myobj.ServerName = $srv
        $myobj.Hotfixes   =  $hotfixes | %{$_.Name}
        $myobj.RawObjects = $hotfixes
        $myobj
    }
    else
    {
        write-host $srv
        write-host "————"
        write-host "Server not pingable"
    }
}

Setting lDAPAdminLimits via Powershell

I was having a conversation with a friend the other day and he brought up a question about updating the AD property lDAPAdminLimits.

The Problem
The property is stored as an array of string values (at least as far as Powershell is concerned.) The initial reaction was do try something like this $queryPolicies.lDAPAdminLimits.MaxNotificationPerConn = 30, but this assumed that MaxNotficationPerConn was a property of lDAPAdminLimits and not the actual value (or at least part of the value.)

The Solution
Use the ADSI method PutEX to modify the value. PutEx uses ADS_PROPERTY_OPERATION_ENUM to make selective changes to an existing property. In the script below, we add the new value using the Update operation and then use the Delete operation to remove the old value.

Some Examples of Use

D:\Scripts\Set-ldapAdminPolicy.ps1 MaxNotificationPerConn 45
D:\Scripts\Set-ldapAdminPolicy.ps1 MaxQueryDuration 360
D:\Scripts\Set-ldapAdminPolicy.ps1 MaxPageSize 500
D:\Scripts\Set-ldapAdminPolicy.ps1 MaxPoolThreads 8

Here is a link on how to view/set via NTDSUtil.exe
How to view and set LDAP policy in Active Directory by using Ntdsutil.exe

The Code

Param($policy=$(throw ‘$policy is required’),$count=30)
$rootDSE = [ADSI]"LDAP://rootDSE"
$config = $rootDSE.configurationNamingContext
$queryPolicies = [adsi]"LDAP://CN=Default Query Policy,CN=Query-Policies,cn=Directory Service,cn=Windows NT,CN=Services,$config"
$oldvalue = $queryPolicies.lDAPAdminLimits | ?{$_ -match $policy}
$queryPolicies.PutEx(3,"lDAPAdminLimits",@("$policy=$count"))
$queryPolicies.Setinfo()
$queryPolicies.PutEx(4,"lDAPAdminLimits",@("$oldvalue"))
$queryPolicies.Setinfo()

Bulk Imports using CSV (cross post from TurboChargeAD.org)

As some of you may know I am doing some guest blogging over at TurboChargeAD.org and below is a link to the second such article.

Here is the Link: Bulking Importing User from CSV file using Quest cmdlets

Here is the code

#Import-ADUser.ps1
#requires -pssnapin Quest.ActiveRoles.ADManagement
Param($file,$OU,[switch]$whatif,[switch]$verbose)

if($verbose){$VerbosePreference = "Continue"}

if(!(test-path $file))
{
   throw " File NOT found!"
   return
}

if(!$ou)
{
    # Setting the OU to the Users container
    $ou = "CN=Users,{0}" -f ([ADSI]"").distinguishedName[0]
}

Write-Verbose " Using File: $file"
Write-Verbose " Using OU: $ou"

foreach($user in (Import-Csv $file))
{
    $props = @{}
    # Getting a list property names.
    $propNames = $user | Get-Member -MemberType properties | %{$_.name}
    # Foreach of the property names add an entry in the hash table with
    # the key being the property name and value being the value from the object
    foreach($prop in $propNames)
    {
        # This removes quotes if they exist
    $value = $user.$prop -replace "’|`"",""
        $props += @{$prop=$value}
    }
    # Create User using the displayname as the CN
    $MyUser = new-qaduser -name $user.displayName `
                          -ObjectAttributes $props `
                          -parent $OU `
                          -whatif:$whatif `
                          -verbose:$verbose
    $MyUser
}

Next »