# Monday, March 12, 2007

I've been involved in an Active Directory Migration lately and one of the things that was taking a lot of time was finding the groups for a group of users and then finding the nested groups. Why, you might ask? Well in this particular instance it was easier for us to migrate groups first than users but we had to make sure we got all the groups for the users we wanted to migrate moved over first.

The first part of the script involves search Active Directory for the user we wish to find group membership for. This is pretty easy:
#Setup Tasks
$query = new-object system.directoryservices.directorysearcher
$root = [adsi]""

#Setup for Query
$query.searchroot=[adsi]$("LDAP://"+$root.distinguishedName)
$query.Filter = "(&(objectCategory=user)(objectClass=person)(samAccountName=$accountName))"
$query.SearchScope="Subtree"

The next thing to do after we find the user is to get the memberOf Property:
$ADobject.psbase.Properties["memberOf"]

So I found it was easy enough to get a list of groups for a user but how could a get a list for several users without getting duplicates? The logical thing seemed like a hashtable:
$groups = @{}
foreach ( $user in $users ) {
   
foreach ($group in Get-Groups $user
   {
      
$groupName=$($group.split(",")[0]).split("=")[1]
      
if(!$groups.Contains($groupname)){$groups.Add($groupname,$group)}
   }
}

The Properties["memberOf"] returns a collection of distinguished names, (CN=GroupName,OU=Groups,DC=domain,DC=local), so the above code splits up that string to extract the groupName to be the key for the hashtable and then the DN as the value. After this it is simply a case of connecting to each group and listing the memberOf property to see if there is any nested groups.

The code will only check 1 level deep so if you have a chain of nested groups you'll have to check it manually.

To Run the script just run .\GetGroups "username1","username2","username3". Please let me know what you think.

FindNestedGroups.ps1.txt (.91 KB)
posted on Monday, March 12, 2007 9:58:11 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]
# Thursday, January 18, 2007

The final version of BDD 2007 has been released. Get it here.

posted on Thursday, January 18, 2007 10:30:01 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]
# Saturday, January 06, 2007

Today I reach a greater level of frustration than I had in a long time. After installing Vista Ultimate, eagerly wanting to try out some new Media Center bits, I found I could not connect to a network share. Simple enough I thought, typing in \\WinXP\c$ yielded a password prompt but after the correct password still didn't let me in.

I jumped to the conclusion that some new fancy Vista security 'thing' was stopping my connecting to my XP machine. After wasting almost the entire afternoon and another fews hours in the evening I had nothing. Still Vista would just continue to prompt for a password. I tried separte accounts, enabling netbios, installing updates, anything I could think of even a re-install.

After installing the new Network Monitor 3 and doing a capture I found that it was failing NTLM negotiation, then it clicked. Check the time!!! As it turns out I had the right time, just I was 5 days out....grrr.

So the moral of the story, Keep it simple and look for the obvious problems.

posted on Saturday, January 06, 2007 12:21:12 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]
# Monday, December 11, 2006

Microsoft have just released BDD 2007 RC1. BDD 2007 give best practice guidance on how to deploy Windows Vista and Office 2007.

Information about the technologies used in BDD 2007 are at http://www.microsoft.com/technet/windowsvista/deploy/depenhnc.mspx.

Go to https://connect.microsoft.com to download.

posted on Monday, December 11, 2006 8:37:51 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]
# Thursday, December 07, 2006

Kelly keeton was nice enough to fix a bug in my css that cause the Project84Grass theme to look a little weird in IE7. Thanks mate!! I'll post the update theme as a zip file later today.

posted on Thursday, December 07, 2006 12:12:27 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]

I've been doing some work with Zero Touch Installation lately and have certainly come across my fair share of problems. Fortunately you can get a lot of debugging information out of ZTI. THere is a great article OSD and ZTI Troubleshooting Tips that has some excellent tips on debugging.

One thing that I found that caused me grief for at least a few hours was the 80004005 error. According to the article mention above the causes are commonly:
-Wrong PackageID in customsettings.ini
-Failure to resolve MP or DP using FQDN
-Missing NIC drivers in Winpe

I found that I got this error because osd.debug existed on the machine I was testing on. If you're testing your deployment CD's make sure you do a diskpart first or at least remove osd.debug.

posted on Thursday, December 07, 2006 11:12:13 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]
# Tuesday, July 18, 2006

To mount an SDI file so that you can work with it you usually use the utility called sdiloader.exe that comes with the Windows XP Embedded Tools. Where's the fun in that I say!!

Create on of these guys:

Set oSDIMount = CreateObject("SDIAUT.SDIMountedDisks")

And then you can use:
oSDIMount.Add sTempImage
and
oSDIMount.Remove index-1

I've provided an example script so you don't have to do any real coding: MountSDI.vbs (2.22 KB)

posted on Tuesday, July 18, 2006 4:54:58 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [5]

Continuing on from my first post Creating SDI Images using VBScript I am going to look at a more complete example here. I've also attached a working script.MakeSDI.vbs (4.76 KB)

Previously we saw that you can create a new SDI image doing the following:
Set oSDIFile = oSDI.CreateImage(sImage, SDICREATENEW)
Now this isn't really all that useful because without a disk blob inside the SDI file you cannot partition and format the SDI file.

Now I'll leave it to someone more knowledgable than myself to explain exactly what a DISK blog is but you create one by using oSDIFile.Blobs.Allocate DISK, nLo, nHi. The signature for Allocate is:

Sub Allocate(ByVal ldwType As Long, ByVal ldwSizeLowPart As Long, [ByVal ldwSizeHighPart As Long])

Confused?? I was but if you take a look in SDIMgr.swf from the Windows XP Embedded Tools you'll be able to extract just the bits you need. I've provided them below and don't forget the example script that is attached.

Sub CreateDisk(sSize)
   
Dim nSize 'size in MB
   
Dim sHex 'size as Hex
   Dim nLo 'Low DWORD
   
Dim nHi 'High DWORD
   
Dim oBlob 'DISK Blob

   'Get the size in MB
   
nSize = GetSizeInMB(sSize)

   'Convert to hex
   
sHex = Right("00000000" & Hex(nSize), 8)

   'Form the Low DWORD
   
nLo = CLng("&h" & Right(sHex, 3) & "00000")
   
nHi = CLng("&h" & Left(sHex, 5))

   'Create a DISK Blog
   
oSDIFile.Blobs.Allocate DISK, nLo, nHi

   Set oBlob = FindBlob(oSDIFile)
   oBlob.Attribute = 0

End Sub

Function GetSizeInMB(sData)
   
Dim sTemp : sTemp = Trim(sData)
   
Dim lTemp : lTemp = CLng(sTemp)

   GetSizeInMB = lTemp \ 1048576
End Function

Function FindBlob(oSDIFile)
   
Dim oBlob
   
Set FindBlob = Nothing

   For Each oBlob In oSDIFile.Blobs
      
If oBlob.Type = DISK Then Set FindBlob = oBlob : Exit Function
   
Next
End Function

Enjoy!

posted on Tuesday, July 18, 2006 4:44:55 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]

When you create an SDI image with the view of using it to create a bootable Windows PE or Bart PE disk one of the steps is to use diskpart or Device Manager to partition and format the image. Recently I tried to automate this process to my own demise. In the diskpart script that I used I had the line select disk 1, which was a terrible idea because when I ran it on another machine it formatted the HDD. Oops!

To get around this I thought I'd ask WMI what the index of my SDI Disk is before running diskpart, the result:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery( _
   
"SELECT * FROM Win32_DiskDrive WHERE Caption = 'SDIDisk'",,48)

For Each objItem In colItems 
   WScript.Echo "-----------------------------------"
   WScript.Echo "Win32_DiskDrive instance"
   WScript.Echo "-----------------------------------"
   WScript.Echo "Index: " & objItem.Index
   WScript.Echo "Name: " & objItem.Name
   WScript.Echo "Partitions: " & objItem.Partitions
   WScript.Echo "Size: " & objItem.Size
Next

Index is the Property that matches up with the Disk# you see in Device Manager. Keep in mind that if you have a couple of SDI images loaded you'll get them all back. In my script I've used the Partition Property to distinguish between an SDI I have just created and one that I left mounted previously.

posted on Tuesday, July 18, 2006 3:55:31 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]
# Friday, July 14, 2006

I have been using SDI Images to make fast-loading Windows PE and BartPE boot disk using a technique I found over here: http://www.myitforum.com/articles/8/view.asp?id=8832

Typically you need to use SDIMgr.wsf and SDILoader.exe that come with Windows XP Embedded to create SDI file and mount them. This however is not the only way. All you need is a file called sdiaut.dll and of course the SDI driver. If you've installed the Windows XP Embedded tools as per the article above you'll have both of these.

sdiaut.dll is the SDI Automation dll and can be instantiated by like so:

Dim oSDI : Set oSDI = CreateObject("SDIAUT.SDI")

To Create an SDI Image it is as simple as:

Const SDICREATENEW = 1
Dim oSDI : Set oSDI = CreateObject("SDIAUT.SDI")
Dim fs : Set fs = CreateObject("Scripting.FileSystemObject")

'Create the SDI File
If fs.FileExists(sImage) Then
   WScript.Echo "File Already Exists deleting..."
   
fs.DeleteFile sImage, True
End If

Dim oSDIFile : Set oSDIFile = oSDI.CreateImage(sImage, SDICREATENEW)


WScript.Echo "BootCodeOffset: " & oSDIFile.BootCodeOffset
WScript
.Echo "BootCodeSize: " & oSDIFile.BootCodeSize
WScript
.Echo "DeviceID: " & oSDIFile.DeviceId
WScript
.Echo "DeviceModel: " & oSDIFile.DeviceModel
WScript
.Echo "DeviceRole: " & oSDIFile.DeviceRole
WScript
.Echo "FilePath: " & oSDIFile.FilePath
WScript
.Echo "MDBType: " & oSDIFile.MDBType
WScript
.Echo "RuntimeGUID: " & oSDIFile.RuntimeGUID

Set oSDIFile = Nothing ' Close the file

Pretty cool hey!

posted on Friday, July 14, 2006 10:18:56 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0]