/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Moving to ThePowerShellGuy.com "," PowerShell Code formatting test for my new Blog "," PowerShell Code formatting test for my new Blog "," PowerShell Community Extensions V1.0 "," PowerShell : Access remote eventlogs "," Windows PowerShell Scripting Sweepstakes! "," PowerShell : making Custum Enums "," TechNet Webcast: An Overview of Windows PowerShell... "," "Windows PowerShell: TFM" goes "Gold" "," PowerShell : Advanced renaming of files "," ")

Monday, July 17, 2006

 


PowerShell and Active Directory Part 4 (TypeData)



As I have been a bit busy ...
( PoSH>ConvertTo-Fahrenheit 32 89.6 PoSH>ConvertTo-Fahrenheit 35 95 in the netherlands ;-))
part 4 is a bit later and it's not yet about the making of scripts as I decided to give some info about using Typedata with the DirectoryEntry Object first in this post.
As this is handy for commandline usage as we can hide some of the more complex Userproperties with typedata, and unlike the WTF example with the boolean I DO keep this update typedata in my profile ;-)
I only will show the adding of the typedata as the rest is covered in former posts.

PowerShel and Active Directory Part 1
Connect to a Domain (Default Naming Context) :
listing properties (format-* commands)
Using get-Member to get information about the object
returned Objects that look like collections could be wrapperobjects. [DirectoryEntries]
how to use get-member on enumerable objects [DirectoryEntries]
using the methods
listing the Child Objects
Getting a Child Object
Connect directly to a Active Directory Object using a path
PowerShell and Active Directory Part 2
Using ADAM to do some testing,
Create a User,
Create a group of users using a Loop
Create an OU or other AD object the same way.
PowerShell and Active Directory Part 3 (UserProperties)
Setting Other properties on the User.
Using ADSI to set properties using InvokeGet, InvokeSet,Invoke
Connecting to Schema using ActiveDirectorySchema class (not work on ADAM.)
how to make a quick function get-Schema
Using native ADSI methods for setting "Special Settings")
where to find More information on ADSI (accountcontrol Terminal services )
that the Invoke methods are the same a in VbScript so they could be handy for translating VbScripts also.

We will add some properties that are a bit harder to get to the DirectoryObject with a typedata file. so we can use it like this :

# update the Typedata 

PoSH>Update-TypeData C:\PowerShell\TypeData\directoryEntry.ps1xml

# reset the userAccountControl

PoSH>$mow.userAccountControl = 512

# show added properties 

PoSH>$mow | fl PasswordLastChanged,AccountDisabled,PasswordNeverExpires,userAccountControl


PasswordLastChanged  : 6/29/2006 8:47:30 PM
AccountDisabled      : False
PasswordNeverExpires : False
userAccountControl   : {512}

# using the SetScriptBlock to set the AccountDisabled bit

PoSH>$mow.AccountDisabled = $true
PoSH>$mow | fl PasswordLastChanged,AccountDisabled,PasswordNeverExpires,userAccountControl


PasswordLastChanged  : 6/29/2006 8:47:30 PM
AccountDisabled      : True
PasswordNeverExpires : False
userAccountControl   : {514}

# set Password Never Expires

PoSH>$mow.PasswordNeverExpires = $true
PoSH>$mow | fl PasswordLastChanged,AccountDisabled,PasswordNeverExpires,userAccountControl


PasswordLastChanged  : 6/29/2006 8:47:30 PM
AccountDisabled      : True
PasswordNeverExpires : True
userAccountControl   : {66050}

# Set User must change Password at next Logon 

PoSH>$mow.pwdLastSet = 0
PoSH>$mow | fl PasswordLastChanged,AccountDisabled,PasswordNeverExpires,userAccountControl


PasswordLastChanged  : 
AccountDisabled      : True
PasswordNeverExpires : True
userAccountControl   : {66050}

# UnSet User must change Password at next Logon

PoSH>$mow.pwdLastSet = -1



note that pwdLastSet we can use directly from the DirectoryEntry object but not read,
as its a largeInteger COM Object (more about that later in the series).


the DirectoryEntry.ps1xml file I made for this looks like this :

<?xml version="1.0encoding="utf-8?>
<Types>
    <Type>
        <Name>System.DirectoryServices.DirectoryEntry</Name>
        <Members>
            <ScriptProperty>
                <Name>PasswordLastChanged</Name>
                 <GetScriptBlock>
                   $this.InvokeGet('PasswordLastChanged')
                </GetScriptBlock>
            </ScriptProperty>
            <ScriptProperty>
                <Name>AccountDisabled</Name>
                 <GetScriptBlock>
                 [bool]($this.userAccountControl[0] -band 2)
                </GetScriptBlock>
                 <SetScriptBlock>
                   if ($args -eq $true) {
                     $this.userAccountControl[0] = $this.userAccountControl[0] -bor (2)
                   }
                   Else {
                     $this.userAccountControl[0] = $this.userAccountControl[0] -band (-bnot 2)
                   }
                </SetScriptBlock>
            </ScriptProperty>
            <ScriptProperty>
                <Name>PasswordNeverExpires</Name>
                 <GetScriptBlock>
                 [bool]($this.userAccountControl[0] -band 65536)
                </GetScriptBlock>
                 <SetScriptBlock>
                   if ($args -eq $true) {
                     $this.userAccountControl[0] = $this.userAccountControl[0] -bor (65536)
                   }
                   Else {
                     $this.userAccountControl[0] = $this.userAccountControl[0] -band (-bnot 65536)
                   }
                </SetScriptBlock>
            </ScriptProperty>
        </Members>
    </Type>
</Types>


You can see that if you add this update-typedata to your profile, and update it for other advanced properties when you run into them (e.g. the terminalserverproperties we did see in part 3) this will build up to a very handy AD library (till it's standard in V2) making the commandline use very easy as it is attached to the DirectoryEntryType so it works as this is standard.
so again no need to wait for V2 ;-)
In the next part I will go on with the script examples originaly planned for this post, but I found the SetScriptBlock to cool to wait and it took a bit less time.
only I could not find a way to get the args named Param([bool]$value) did not work.

Enjoy,

Greetings /\/\o\/\/
Tags :


 0 comments links to this post
 


PowerShell and MOM2005 part 2 : Updating Settings



In the Comments about my last post about PowerShell and MOM 2005
Pete Zerger asked about updating MOM by Using PowerShell. :
Based on the output of the '$mom | gm' command, it would appear we're limited to read-only? (I only see Get options, no Set options)

I will show with some examples its also possible to update MOM2005 settings with PowerShell :

I will use get/set properties (SearchForComputers property) and Methods (ComputerIncludeList) for this :

# List available groups :

PS C:\> $mom.GetComputerGroups() | ft id,name

Id                                                          Name
--                                                          ----
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxfa7c28                        Dell Computers
......

$dell = $mom.GetComputerGroup('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxfa7c28')

# Update get/set property : System.Boolean SearchForComputers {get;set;}

PS C:\> $dell.SearchForComputers
True

# Set SearchForComputers to False :

PS C:\> $dell.SearchForComputers = $false
PS C:\> $dell.Update()

# Reload the Group to check if update suceeded :

PS C:\> $dell = $mom.GetComputerGroup('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxfa7c28')
PS C:\> $dell.SearchForComputers
False

# ComputerIncludeList           Property   System.String[] ComputerIncludeList {get;}

# Use a Method to update the Included computerlist :

PS C:\> $dell.AddComputerToIncludeList('Server008')
PS C:\> $dell.ComputerIncludeList
Domain\Server001
Domain\Server002
Domain\Server012
Domain\Server003
Domain\Server004
Domain\Server027
Domain\Server036
Server008

PS C:\> $dell.update()

# and after the update and reload you can see It found the computer and did add it :

PS C:\> $dell = $mom.GetComputerGroup('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxfa7c28')

PS C:\> $dell.ComputerIncludeList
Domain\Server001
Domain\Server002
Domain\Server012
Domain\Server003
Domain\Server004
Domain\Server027
Domain\Server036
Domain\Server008




as you can see from this example its also possible to update MOM2005 settings from PowerShell and you can see that some properties are only GET but you can update them by using methods, note also the use of the Update() Method.

Enjoy,

Greetings /\/\o\/\/
Tags :


posted by /\/\o\/\/
 0 comments links to this post

Thursday, July 06, 2006

 


PowerShell Boolean FileMode



Inspired by this Nice piece of Code :

Classic WTF - What is Truth?

I came up with this TypeExtension for PowerShell :

BoolFileMode.ps1xml

<?xml version="1.0encoding="utf-8?>
<Types>
    <Type>
        <Name>System.Boolean</Name>
        <Members>
            <ScriptMethod>
                <Name>File</Name>
                 <Script>
                  if ($this -eq $false){"File Not found"} Else {$True}
                </Script>
            </ScriptMethod>

        </Members>
    </Type>
</Types>


You can load this with this command :

# Execute in same Directory as BoolFileMode.ps1xml

Update-TypeData BoolFileMode.ps1xml


So now you can do things like this :

PoSH>ls foo*


    Directory: Microsoft.PowerShell.Core\FileSystem::E:\Documents and Settings\Mow


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         5/31/2006   8:36 PM            foo
-a---          7/6/2006  10:50 PM         24 foo.txt

# Normal Boolean 

PoSH>$file = ([bool](gc foo.txt))

PoSH>$file
True

PoSH>$file = ([bool](gc foobar.txt))
Get-Content : Cannot find path 'E:\Documents and Settings\Mow\foobar.txt' because it does not exist.
At line:1 char:19
+ $file = ([bool](gc  <<<< foobar.txt))

PoSH>$file
False

# Update the Bool Type to add a FileMode

PoSH>Update-TypeData G:\powershell\BoolFileMode.ps1xml
PoSH>$file = ([bool](gc foo.txt)).file()

PoSH>$file
True

PoSH>$file = ([bool](gc fooBar.txt)).file()
Get-Content : Cannot find path 'E:\Documents and Settings\Mow\fooBar.txt' because it does not exist.
At line:1 char:19
+ $file = ([bool](gc  <<<< fooBar.txt)).file()

PoSH>$file
File Not found


very handy ;-)

# If a bool is a file its not found

PoSH>$true.file()
True
PoSH>$False.file()
File Not found


But on Second tought I did not add this to my profile, as I would Advice you to do (and in your next session this WTF ScriptMethod goes away ;-)

TypeExtensions are Powerfull, but use them with care !

Greetings /\/\o\/\/

Tags :


posted by /\/\o\/\/
 1 comments links to this post

Wednesday, July 05, 2006

 


Working with Fixed Length delimited Text files in PowerShell



As on the microsoft.public.windows.powerShell a Question was asked about working with a Fixed Length delimited Text file (Columns lined-out by spaces)Working with fixed length is a bit tricky, but you can use ADO to do this as I already did the functions to get textfile in my CSV series I came up with this Going from my CSV examples here :
working with csv files in msh part one and Part two .

In this post I will show that a one word change in those two functions and creating a schema.ini file will enable us to get Fixed Length delimited Text files into a dataset and from there into a CSV file and from the CSV file into an PsObject to work with.

Here are the 2 functions from the first CSV post on my blog we will use for this :

# I modified the connect-Csv (changed : FMT=FixedLength) to connect-txt function

function connect-txt {
  Param ($Path = ".")
  $ConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=$path;Extended properties='text;HDR=Yes;FMT=FixedLength'"
  $Conn = new-object System.Data.OleDb.OleDbConnection($connString)
  $conn.open()
  $Tables = $Conn.GetOleDbSchemaTable([System.Data.OleDb.OleDbSchemaGuid]::tables,$null)
  $Tables | select TABLE_NAME
}

# and the get-DataTable did stay the same :

function get-DataTable {
  Param ($name )
  $cmd = new-object System.Data.OleDb.OleDbCommand("Select * from [$name]",$Conn)
  $da = new-object System.Data.OleDb.OleDbDataAdapter($cmd)
  $dt = new-object System.Data.dataTable
  [void]$da.fill($dt)
  $dt.TableName = $name.split("#")[0]
  return $dt
}


You can past this 2 functions (more info in CSV posts) onto your commandline and you are ready to go.

Now for a Fixed Length file you need an SCHEMA.INI file in the same directory, and this file needs to have an entry [filename] and it needs to define the colums so lets say we have a textfile like this :

TEST.TXT

Name     Value
var1     Bar
Var123   Foo
Var2     FooBar 


and we make a schema.ini file defining the columns like this :

SCHEMA.INI

[test.txt]
Format=FixedLength

Col1=Name Text Width 9
Col2=Value Text Width 6


now after you past in 2 former functions you can do this :

# Connect to directory and load connection in $global:Conn
PoSH>. connect-txt

TABLE_NAME
----------
Test#txt

and get a datatable from it

PoSH>get-datatable Test#txt

Name               Value
----              ------
var1              Bar
Var123            Foo
Var2              FooBar

# you can work with dataset :

(get-datatable Test#txt).get_Rows() | select name

or you now can export it to CSV

PoSH>(get-datatable Test#txt).get_Rows() | export-csv -not Test.csv

and import it again with Import-csv to get an PSObject :

PoSH>import-csv Test.csv

Name               Value
----              ------
var1              Bar
Var123            Foo
Var2              FooBar

and save to an object if you find this easier to work with :

PoSH>import-csv Test.csv | select name

NAME
----
var1
Var123
Var2
PoSH>$Test = import-csv Test.csv


(changed coloring for # in filenames)

So the connect-csv function with one property changed can now do Fixed length files combined with an Schema.ini file where we can configure the columns on a file by file base.(and a import-TabDelimited version would be not hard to do from here on so I leave that up to you ;-) )
the save and import to CSV file will translate the Dataset to an PsObject with properties for the columns, so you can work with it like an object.(but the DataSet is also great to use see the CSV and other DataSet and DataTable examples on my blog (search also for out-datagrid to show it in a GUI).

an excelent article about using textfiles with ADO can be found here :( It's hidden here :MSDN Library > Web Development > Scripting but ... It's the Scripting Guy again with another great article) : Much ADO About Text Files

those to functions well give us a powerfull way to work with files lined out with spaces from PowerShell and combine and or export them (see also other examples on blog e.g. PowerShell out-DataGrid update and more Dataset utilities for a GUI and More DataTables and joining them in Monad for some combining data ).

Enjoy,

Greetings /\/\o\/\/

Tags :


posted by /\/\o\/\/
 0 comments links to this post

Tuesday, July 04, 2006

 


PowerShell and Active Directory Part 3 (UserProperties)



This is the third part in the PowerShell Active directory series,in this part we are going to do the rest of the work to completely configure a User.

*Warning* As you have RC2 Installed all my AD posts will not work anymore, it is verry confusing, but fixable if you read explaination here PowerShell RC2 and Active Directory :


As I did switch back on all my work PC's (I did call all my colleagues not to upgrade as all our AD tools are messed up, I will not update them, as I would not recommend to upgrade to RC2 of you work with AD a lot.


Part 1 and 2 you can find here :

PowerShel and Active Directory Part 1
PowerShell and Active Directory Part 2

We did create a bounce of users last time, but as I did say in last post we are not really ready yet with the users created, as we want also to fill in some more properties and enable them, you can take a user created in last post or as here start with a Fresh one.

# Make a new User called Test

$mowOu = New-Object DirectoryServices.DirectoryEntry("LDAP://OU=MowOu,DC=mow,DC=local")
$user = $mowOu.get_Children().Add("CN=Test",'user')
$user.CommitChanges()
 
# Or use an existing User :

PoSH>$user = $mowou.get_Children().find('cn=test')
PoSH>$user
distinguishedName
-----------------
{CN=test,OU=MowOu,DC=mow,DC=local}

# Or directly again :

$User = New-Object DirectoryServices.DirectoryEntry("LDAP://cn=test,OU=MowOu,DC=mow,DC=local")

# Remove it and make a new one

PoSH>$mowou.get_Children().remove($user)
PoSH>$user = $mowou.get_Children().add("cn=Test",'user')
PoSH>$user.CommitChanges()

# list all the properties :

PoSH>$user | fl *


objectClass          : {top, person, organizationalPerson, user}
cn                   : {Test}
distinguishedName    : {CN=Test,OU=MowOu,DC=mow,DC=local}
instanceType         : {4}
whenCreated          : {7/2/2006 2:10:58 PM}
whenChanged          : {7/2/2006 2:10:58 PM}
uSNCreated           : {System.__ComObject}
uSNChanged           : {System.__ComObject}
name                 : {Test}
objectGUID           : {4.0.208.232.208.190.162.64.184.228.97.225.109.37.99.125}
userAccountControl   : {546}
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.94.172.186.232.167.29.117.70.12.60.36.84.61.12.0.0}
accountExpires       : {System.__ComObject}
logonCount           : {0}
sAMAccountName       : {$T13000-LM8U3IDDHKKL}
sAMAccountType       : {805306368}
objectCategory       : {CN=Person,CN=Schema,CN=Configuration,DC=mow,DC=local}
nTSecurityDescriptor : {System.__ComObject}


After this refresh of things done in former posts and now we have a situation with a Fresh User again, we can go further adding the properties to configure the User compleetly, let's start with that SAMAccountName that is auto generated,

sAMAccountName : {$T13000-LM8U3IDDHKKL}

as we still do need it a lot in day to day work and such a generated name is not handy, so we want it to be the same as the CN lets rename it :
(note this first part does not work for ADAM users they need to use the Native Methods here, more info later in this post.).

# Change sAMAccountName

PoSH>$user.sAMAccountName = 'test'
PoSH>$user.sAMAccountName
test


Note that we do not have to call Commit Changes here, this will be done automatically the .NET DirectoryEntry wrapper-object will handle this.

Now Lets start with adding some more properties :

# Add a Property that does not exist (AD only)

$user.Department = 'foo'

PoSH>$user | fl *


objectClass          : {top, person, organizationalPerson, user}
cn                   : {Test}
distinguishedName    : {CN=Test,OU=MowOu,DC=mow,DC=local}
instanceType         : {4}
whenCreated          : {7/2/2006 2:10:58 PM}
whenChanged          : {7/2/2006 2:12:34 PM}
uSNCreated           : {System.__ComObject}
uSNChanged           : {System.__ComObject}
department           : {Foo}
......


Now you can see that, even when the property was not there before, It just got created and The Object saved again.

Now as I noted before the examples above, these will not work for ADAM users, you can still do it, but need to use Invoke or InvokeSet here as I will show below.:

# ADAM example

PoSH>$u.department = 'foo'
Exception setting "department": "The specified directory service attribute or value does not

exist. (Exception from HRESULT: 0x8007200A)"
At line:1 char:4
+ $u.d <<<< epartment = 'foo'

# Using Invoke

PoSH>$u.department
PoSH>$u.InvokeSet('department','foo')
PoSH>$u | fl *


objectClass          : {top, person, organizationalPerson, user}
cn                   : {test}
distinguishedName    : {CN=test,OU=MowOu,DC=mow,DC=adam}
instanceType         : {4}
whenCreated          : {6/28/2006 7:45:25 PM}
whenChanged          : {6/28/2006 7:45:25 PM}
uSNCreated           : {System.__ComObject}
uSNChanged           : {System.__ComObject}
name                 : {test}
objectGUID           : {0.18.124.80.174.38.202.68.189.94.92.39.181.158.201.85}
badPwdCount          : {0}
badPasswordTime      : {System.__ComObject}
pwdLastSet           : {System.__ComObject}
objectSid            :

{1.5.0.0.18.108.99.8.192.67.92.229.143.126.164.172.231.8.44.75.160.22.205.75.212.176.144.138}
objectCategory       : {CN=Person,CN=Schema,CN=Configuration,CN={95B8575E-7CB6-4F6F-8F90-

85B1EBE795FF}}
nTSecurityDescriptor : {System.__ComObject}

# We have to Manualy save here :

PoSH>$u.CommitChanges()
PoSH>$u | fl *


department           : {foo}
objectClass          : {top, person, organizationalPerson, user}
cn                   : {test}
distinguishedName    : {CN=test,OU=MowOu,DC=mow,DC=adam}
instanceType         : {4}
whenCreated          : {6/28/2006 7:45:25 PM}
whenChanged          : {6/28/2006 10:02:26 PM}
uSNCreated           : {System.__ComObject}
uSNChanged           : {System.__ComObject}
name                 : {test}
objectGUID           : {0.18.124.80.174.38.202.68.189.94.92.39.181.158.201.85}
badPwdCount          : {0}
badPasswordTime      : {System.__ComObject}
pwdLastSet           : {System.__ComObject}
objectSid            :

{1.5.0.0.18.108.99.8.192.67.92.229.143.126.164.172.231.8.44.75.160.22.205.75.212.176.144.138}
objectCategory       : {CN=Person,CN=Schema,CN=Configuration,CN={95B8575E-7CB6-4F6F-8F90-

85B1EBE795FF}}
nTSecurityDescriptor : {System.__ComObject}

# Using invoke

PoSH>$u.invoke("Put",("displayName","test"))
PoSH>$u.CommitChanges()
PoSH>$u.displayName
test

# after it is created we can directly change it in ADAM

PoSH>$u.displayName = 'Testing'
PoSH>$u.displayName
Testing


This also works in an Active Directory environment ofcourse and as we shall see later in this post, there are also uses for those InvokeGet and InvokeSet methods in Active Directory use. Also when we Enable the account and set terminal serversettings, but first lets find out what properties are available.As we are busy with a User let's find out what properties are available. We will look this up in the Active Directory Schema.For this we need another .NET class, now from the System.DirectoryServices.ActiveDirectory NameSpace the ActiveDirectorySchema Class, and as a lot of the classes in the ActiveDirectory Namespace do, it does not have a constructor (see outputbelow), we have to use a static method .

# does not work :

PoSH>New-Object System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema
New-Object : Constructor not found. Cannot find an appropriate constructor for type

System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema.
At line:1 char:11
+ New-Object  <<<< System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema

# it has no constuctors :

PoSH>[System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema].GetConstructors() 

# listing the static Methods :

PoSH>[System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema] | gm -static


   TypeName: System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema

Name             MemberType Definition
----             ---------- ----------
Equals           Method     static System.Boolean Equals(Object objA, Object objB)
GetCurrentSchema Method     static System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema GetCurrentSchema()
GetSchema        Method     static System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema GetSchema(DirectoryContextcontext)
ReferenceEquals  Method     static System.Boolean ReferenceEquals(Object objA, Object objB)

# using the static GetCurrentSchema() method

$schema = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema]::GetCurrentSchema()


Note that static methods get called with ::,and as you use get-member without the -static switch you get the Methods of the RunTime Object, (for example the get_constructors Method is very handy, but more about that in later post)
also note that this is a long type, for that I made an extension to the Tabcompletion funtion that makes it a lot easier to work with .net types directly from powershell as you could see in the Demo, you can find it here (http://mow001.blogspot.com/2006/06/powershell-tab-completion-part-4.html)
but still making a function for it is more easy, so lets turn this in to a small function :

# Shortcut function for getting Schema Object

function get-Schema [System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema]::GetCurrentSchema()}

# Get the Schema

$schema = get-Schema

# ask what it can do for us .

PoSH>$Schema | gm


   TypeName: System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema

Name                     MemberType Definition
----                     ---------- ----------
Dispose                  Method     System.Void Dispose()
Equals                   Method     System.Boolean Equals(Object obj)
FindAllClasses           Method     System.DirectoryServices.ActiveDirectory.ReadOnlyActiveDirectorySchemaClassCollectio
FindAllDefunctClasses    Method     System.DirectoryServices.ActiveDirectory.ReadOnlyActiveDirectorySchemaClassCollectio
FindAllDefunctProperties Method     System.DirectoryServices.ActiveDirectory.ReadOnlyActiveDirectorySchemaPropertyCollec
FindAllProperties        Method     System.DirectoryServices.ActiveDirectory.ReadOnlyActiveDirectorySchemaPropertyCollec
FindClass                Method     System.DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass FindClass(String
FindDefunctClass         Method     System.DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass FindDefunctClass
FindDefunctProperty      Method     System.DirectoryServices.ActiveDirectory.ActiveDirectorySchemaProperty FindDefunctPr
FindProperty             Method     System.DirectoryServices.ActiveDirectory.ActiveDirectorySchemaProperty FindProperty(
get_Name                 Method     System.String get_Name()
get_SchemaRoleOwner      Method     System.DirectoryServices.ActiveDirectory.DirectoryServer get_SchemaRoleOwner()
GetDirectoryEntry        Method     System.DirectoryServices.DirectoryEntry GetDirectoryEntry()
GetHashCode              Method     System.Int32 GetHashCode()
GetType                  Method     System.Type GetType()
RefreshSchema            Method     System.Void RefreshSchema()
ToString                 Method     System.String ToString()
Name                     Property   System.String Name {get;}
SchemaRoleOwner          Property   System.DirectoryServices.ActiveDirectory.DirectoryServer SchemaRoleOwner {get;}

# Getting the Schema of a user :

PoSH>$SchemaUser = $schema.FindClass('user')
PoSH>$SchemaUser.get_MandatoryProperties() | fl name


Name : cn

Name : instanceType

Name : nTSecurityDescriptor

Name : objectCategory

Name : objectClass

Name : objectSid

Name : sAMAccountName

# Get All Optional Properties of the User Class

PoSH>$SchemaUser.get_OptionalProperties() | ft name,Syntax,IsSingleValued,IsIndexed,IsInGlobalCatalog

Name                                     Syntax          IsSingleValued               IsIndexed       IsInGlobalCatalog
----                                     ------          --------------               ---------       -----------------
accountExpires                            Int64                    True                   False                   False
accountNameHistory              DirectoryString                   False                   False                   False
aCSPolicyName                   DirectoryString                    True                   False                   False
adminCount                                  Int                    True                   False                   False
adminDescription                DirectoryString                    True                   False                   False
adminDisplayName                DirectoryString                    True                   False                   False
allowedAttributes                           Oid                   False                   False                   False
allowedAttributesEff...                     Oid                   False                   False                   False
allowedChildClasses                         Oid                   False                   False                   False
allowedChildClassesE...                     Oid                   False                   False                   False
altSecurityIdentities           DirectoryString                   False                    True                    True
assistant                                    DN                    True                   False                   False
attributeCertificate...             OctetString                   False                   False                   False
audio                               OctetString                   False                   False                   False
.....

# Get Only Properties in Global Catalog :

PoSH>$SchemaUser.get_OptionalProperties() |? {$_.IsInGlobalCatalog}| ft name,Syntax,IsSingleValued,IsIndexed,IsInGlobalC
atalog

Name                                     Syntax          IsSingleValued               IsIndexed       IsInGlobalCatalog
----                                     ------          --------------               ---------       -----------------
altSecurityIdentities           DirectoryString                   False                    True                    True
c                               DirectoryString                    True                   False                    True
description                     DirectoryString                   False                   False                    True
displayName                     DirectoryString                    True                    True                    True
distinguishedName                            DN                    True                   False                    True
dSCorePropagationData           GeneralizedTime                   False                   False                    True
flags                                       Int                    True                   False                    True
givenName                       DirectoryString                    True                    True                    True
homePhone                       DirectoryString                    True                   False                    True
ipPhone                         DirectoryString                    True                   False                    True
isDeleted                                  Bool                    True                   False                    True
l                               DirectoryString                    True                    True                    True
legacyExchangeDN               CaseIgnoreString                    True                    True                    True
mail                            DirectoryString                    True                    True                    True
manager                                      DN                    True                   False                    True
mSMQDigests                         OctetString                   False                    True                    True
mSMQDigestsMig                      OctetString                   False                   False                    True
mSMQSignCertificates                OctetString                    True                   False                    True
mSMQSignCertificatesMig             OctetString                    True                   False                    True
name                            DirectoryString                    True                    True                    True
o                               DirectoryString                   False                   False                    True
objectGUID                          OctetString                    True                    True                    True
otherIpPhone                    DirectoryString                   False                   False                    True
ou                              DirectoryString                   False                    True                    True
partialAttributeDele...             OctetString                    True                   False                    True
partialAttributeSet                 OctetString                    True                   False                    True
primaryGroupID                              Int                    True                    True                    True
proxiedObjectName                  DNWithBinary                    True                   False                    True
replPropertyMetaData                OctetString                    True                   False                    True
replUpToDateVector                  OctetString                    True                   False                    True
repsFrom                            ReplicaLink                   False                   False                    True
repsTo                              ReplicaLink                   False                   False                    True
sAMAccountType                              Int                    True                    True                    True
securityIdentifier                          Sid                    True                   False                    True
servicePrincipalName            DirectoryString                   False                    True                    True
sIDHistory                                  Sid                   False                    True                    True
sn                              DirectoryString                    True                    True                    True
st                              DirectoryString                    True                   False                    True
street                          DirectoryString                    True                   False                    True
subRefs                                      DN                   False                   False                    True
telephoneNumber                 DirectoryString                    True                   False                    True
userAccountControl                          Int                    True                    True                    True
userCert                            OctetString                    True                   False                    True
userCertificate                     OctetString                   False                   False                    True
userPrincipalName               DirectoryString                    True                    True                    True
userSMIMECertificate                OctetString                   False                   False                    True
uSNChanged                                Int64                    True                    True                    True
uSNCreated                                Int64                    True                    True                    True
uSNLastObjRem                             Int64                    True                   False                    True
wellKnownObjects                   DNWithBinary                   False                   False                    True
whenChanged                     GeneralizedTime                    True                   False                    True
whenCreated                     GeneralizedTime                    True                   False                    True

# Or export to CSV file for later use :

$SchemaUser.get_OptionalProperties() |? {$_.IsInGlobalCatalog}| select name,Syntax,IsSingleValued,IsIndexed,IsInGlobalC
atalog | export-csv -not



Now that we did see how to use the Actice Directory Schema to look up information about the properties, lets take a look at the UserAcountControl Property and UserParameters and note the type(syntax) and Next to properties in global catalog you might also look at the indexed properties, more about that later in the series with directorySearcher.Now we did see how to get all Properties and did set them the way that we did want (think about displayname,GivenName,SN and so on),

An Other trick to get the properies is fill them from the MMC and then look at the names created in PowerShell e.g.:

# Original

PoSH>$user | fl *


objectClass                : {top, person, organizationalPerson, user}
cn                         : {Test}
sn                         : {}
description                : {}
physicalDeliveryOfficeName : {}
telephoneNumber            : {}
givenName                  : {}
initials                   : {}
distinguishedName          : {CN=Test,OU=MowOu,DC=mow,DC=local}
instanceType               : {4}
whenCreated                : {7/2/2006 2:10:58 PM}
whenChanged                : {7/2/2006 2:16:11 PM}
displayName                : {}
uSNCreated                 : {System.__ComObject}
uSNChanged                 : {System.__ComObject}
department                 : {Foo}
name                       : {Test}
objectGUID                 : {4.0.208.232.208.190.162.64.184.228.97.225.109.37.99.125}
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.94.172.186.232.167.29.117.70.12.60.36.84.61.12.0.0}
accountExpires             : {System.__ComObject}
logonCount                 : {0}
sAMAccountName             : {test}
sAMAccountType             : {805306368}
userPrincipalName          : {}
objectCategory             : {CN=Person,CN=Schema,CN=Configuration,DC=mow,DC=local}
mail                       : {}
nTSecurityDescriptor       : {System.__ComObject}

# Fill some properties in the Management Console.

PoSH>$user.RefreshCache()
PoSH>$user | fl *


objectClass                : {top, person, organizationalPerson, user}
cn                         : {Test}
sn                         : {Orsouw}
description                : {/\/\o\/\/ Test Account}
physicalDeliveryOfficeName : {PowerShell}
telephoneNumber            : {12345}
givenName                  : {Marc}
initials                   : {van}
distinguishedName          : {CN=Test,OU=MowOu,DC=mow,DC=local}
instanceType               : {4}
whenCreated                : {7/2/2006 2:10:58 PM}
whenChanged                : {7/2/2006 2:20:24 PM}
displayName                : {Marc van Orsouw}
uSNCreated                 : {System.__ComObject}
uSNChanged                 : {System.__ComObject}
department                 : {Foo}
name                       : {Test}
objectGUID                 : {4.0.208.232.208.190.162.64.184.228.97.225.109.37.99.125}
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.94.172.186.232.167.29.117.70.12.60.36.84.61.12.0.0}
accountExpires             : {System.__ComObject}
logonCount                 : {0}
sAMAccountName             : {test}
sAMAccountType             : {805306368}
userPrincipalName          : {test@mow.local}
objectCategory             : {CN=Person,CN=Schema,CN=Configuration,DC=mow,DC=local}
mail                       : {test@mow.local}
nTSecurityDescriptor       : {System.__ComObject}



We now go on to setting the password and enable the Account. The Set_Password method that is show in the get-member output will only allow you to set your own password, so we need to use the Invoke Method again to pass it to the Native COM object. You can set the Password Like This :

Now we need to enable it, as we did see from Your look in the Schema this is a Integer, we also see this as we look at it :

PoSH>$mow.userAccountControl
546


but this is a BitArray setting a whole list of settings. For more info See :

ADS_USER_FLAG_ENUM on MSDN. You can see From that MSDN entry that it is the 2nd Bit that controls "account disabled" True or False.Lets see how we can change that from PowerShell.

#Change userAccountControl BitArray

# We can go counting and come up with this

$mow.userAccountControl = 544

# Or let PowerShell do the counting.

$user.userAccountControl = $user.userAccountControl[0] -band (-bnot 2)

# We need the userAccountControl[0] as AD porerties are PropertyValueCollections
# while setting you will not notice that as this gets wrapped.

PoSH>$mow.userAccountControl[0] = $mow.userAccountControl -band (-bnot 2)
Cannot convert "System.DirectoryServices.PropertyValueCollection" to "System.Int32".
At line:1 char:59

# try a gettype :

$user.userAccountControl.gettype()


the reason behind the extra [0] will workuserAccountControl is a PropertyValueCollection, you need to set the item.

But in the ADSI COM provider are also some shortcuts available that we can use amongs others the Accountdisabled property that does the setting of the bit for us
We can use this functionality like this :

#Change userAccountControl BitArray By using ADSI COM Object Methods :

# Get

PoSH>$user.InvokeGet('AccountDisabled')
True
PoSH>$user.userAccountControl
546

# Set 

PoSH>$mow.invokeSet('Accountdisabled',$false)
PoSH>$mow.CommitChanges()
PoSH>$mow.userAccountControl
544


For a list of those ADSI properties and methods see :IADsUser on MSDN.

Also setting Terminal TeminalService settings needs to be done with invoke :

PoSH>$mow.InvokeSet('TerminalservicesHomeDrive',"z:")
PoSH>$mow.CommitChanges()
PoSH>$mow | fl *


objectClass          : {top, person, organizationalPerson, user}
cn                   : {mow}
distinguishedName    : {CN=mow,OU=MowOu,DC=mow,DC=local}
instanceType         : {4}
whenCreated          : {5/18/2006 7:18:00 PM}
whenChanged          : {6/28/2006 8:37:27 PM}
uSNCreated           : {System.__ComObject}
uSNChanged           : {System.__ComObject}
department           : {foodar}
name                 : {mow}
objectGUID           : {231.189.223.77.11.205.61.64.178.101.27.206.71.175.101.75}
userAccountControl   : {546}
badPwdCount          : {0}
codePage             : {0}
countryCode          : {0}
badPasswordTime      : {System.__ComObject}
lastLogoff           : {System.__ComObject}
lastLogon            : {System.__ComObject}
pwdLastSet           : {System.__ComObject}
primaryGroupID       : {513}
userParameters       : {                                                P?CtxCfgPresent?????CtxCfgFlags1?????Ctx
                       Shadow????*??CtxMinEncryptionLevel??&?CtxWFHomeDir???????????????????"??CtxWFHomeDirDrive???}
objectSid            : {1.5.0.0.0.0.0.5.21.0.0.0.94.172.186.232.167.29.117.70.12.60.36.84.84.4.0.0}
accountExpires       : {System.__ComObject}
logonCount           : {0}
sAMAccountName       : {lol}
sAMAccountType       : {805306368}
objectCategory       : {CN=Person,CN=Schema,CN=Configuration,DC=mow,DC=local}
msNPAllowDialin      : {False}
nTSecurityDescriptor : {System.__ComObject}

PoSH>$mow.InvokeGet('TerminalservicesHomeDrive')
Z:



You can see this is stored in a DirectoryString named userParameters that is not really readable , but again there are special Methods here for setting this in the ADSI COM object you can Use with the invoke function , for a Complete list look here on MSDN : IADsTSUserEx Property MethodsIADsTSUserEx Property Methods


We did see in this post how to fill different User Properties and how to enable the Account . And that most properties you can easy set either on the DirectoryEntry or using the Native Com Object,but there are some properties that are stored in a special object therefor the Shortcut Methods in the Com object are more handy (UserAccountControl) or Needed (TerminalService Configuration). Also in ADAM native invokes are more needed.Also if you Come from VbScript and already know the native Method this could be handy, but for the rest is nice to use the wrapped properties as we not need to worry about arrays that much, and can do some exploring in PowerShell.OK, for the first time we needed to do some documentation Lookups, for the invokes but still not that bad I think. and we have all we need for creating the user now, you might want to set some more properties like DisplayName,GivenName,SN,Description etc also but they should be easy to find and set now, in the next post I will do a roundup in some functions, and take a look at CSV import possibilities and then go on to the DirectorySearcher Object.

I know this has grown to a big post and there are some things a bit less intuitive as we would want, but thats also the case with other languages and scripting against Active Directory, this are not standard LDAP things and are about how its stored in AD, but we are a bit spoiled with the discover ability of PowerShell already ;-)I will provide more background links later, but I hope this post did clear some things up that seem a bit difficault at first but that they are not that bad, as I did see more examples and questions coming of people using PowerShell with AD in the Comments, the NG and other blogs (Also more about PowerShell in Common for example Scott Hanselmann did post a couple of cool PowerShell usages for links see : http://del.icio.us/powershell and you will see that the PowerShell fueled fire is burning harder and harder ) .

In next post I will make an example combining the Creating and configuring of a User in a Script that is using CSV files to create users.(and the Example how I did create the Users form the AdventureWorks SQL example DBase I created on my Demo DC.I promised Jeffrey Snover ;-) ). And go on to the the Searching of Objects in AD.

Enjoy,

Greetings /\/\o\/\/
Tags :


posted by /\/\o\/\/
 2 comments links to this post

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?