Monday, February 11, 2013

Group Policy Preferences with Item-Level Targeting.... watch out for Distribution Groups

I've been using IFMEMBER.EXE (from an old Windows Server Resource Kit... not even sure which version) in my login scripts for a long time.  This handy but awkward command lets you test for a user's membership in a Security Group.  I won't go into details about it here because it's not the point.  The fact that it's awkward and login scripts are growing more and more dated is important to this post, however.  Most things that you used to do in login scripts can now be handled differently.  One of the last items still in my login scripts is assigning printers based on group membership.  The reasons we need to do this are simple: people in our office need to be connected only to those printers that are near them.

As a side note, I also like to automate printer disconnection; and have found/devised a scriptable command to do this, too.  It's handy for when a printer is retired or its name needs to change for some reason.

Today I needed to restrict certain mission-critical printers in a "production" area so that only a limited group of people could print to them.  Prior to today, these were "common" printers - everyone was connected to them.  Therefore, I needed to remove the existing printer connection from everyone except those people who still need to print to those printers.  No problem for me... I whipped out my login scripts and crafted a few additional lines using a combination of the lovely IFMEMBER.EXE command and my printer disconnect script.  I also worked into the code a few lines to connect anyone to those printers who should have them.  This is being prepared for when a new person moves into or out of that functional area... all I would have to do is change their group membership and they'd either get, or have deleted, all the right printers.

Today things weren't working properly, though.  In my script I tested a new security group "PRINTERS-ASSEMBLY" (which itself contained two other groups... this is an important nuance)  and mapped or deleted printers based on the value of the environment variable ERRORLEVEL (which is how IFMEMBER.EXE works).  But it wasn't working properly for one of my users.  She didn't have the printers she was supposed to have.  So I began troubleshooting.

I narrowed down the problem to the fact that IFMEMBER did not recognize her as being in that group.  I didn't test any other users yet, as she was the only person complaining.  I reviewed the scripts and became satisfied that there were no dumb errors there... they were coded properly.  IFMEMBER simply wasn't acknowledging that the user was a member of the group.

While researching IFMEMBER in order to give myself a refresher - again looking for something dumb I might have done - I came across several articles describing something called "Item-Level Targeting" in Windows Server 2008's Group Policy Preferences.  (Here's one of them).  I had looked at Preferences before, but I was unaware of ILT.  I configured some ILT-based preferences for the printers in question and even used the "remove" option so that people who didn't need the pritners would have them removed by this same setting.  Sweet!  But it still didn't work.  Fro some reason this user was not seen as a member of the group.

At this point I will describe how the user was a member of the group.  The new group was called PRINTERS-ASSEMBLY.  It contained, among other things, a group named CLERKS.  This user was a member of the CLERKS group.  Aha!  I jumped to the conclusion that neither IFMEMBER or ILT recognized members of sub-groups.  I even confirmed this (so I thought) by adding the user directly to the PRINTERS-ASSEMBLY group.  When I did, the IFMEMBER and ILT mechanisms worked fine.  I was prepared to call Microsoft to step through all this and find out if there was anything that could be done.  Thankfully one of my more AD-savvy admins took a look at it with me, and together (I'll take part of the credit) we identified the problem... Distribution Groups.  The sub-group that the user was a member of was a Distribution Group - not a Security Group.  We had never had a need to use that group as a Security Group - it was in existence strictly for use as a handy way to e-mail a handful of people at once.  When I added it to the PRINTERS-ASSEMBLY group I didn't stop to check to see what type of group it was... I just added it and rocked on.

After fiddling around for a little while, we arrived at a great solution that just might help someone else one day, so I will outline it here.  If your ILT (or IFMEMBER) isn't returning a group membership that you know is correct, check the group's type.  If it's a Distribution Group, neither of these mechanisms will report membership.  So what do you do?  Simple:
  1. Make note of the members (and any other special properties) of the Distribution Group and then delete it.
  2. Create a new Security Group using the same name.
  3. In Exchange, create a new Distribution List from an Existing Group, and then select the newly-create Security Group.  This will create a Distribution-Enabled Security Group.  With this new entity you can both e-mail to its members and check for group membership using ILT and IFMEMBER.
If I had been creating all the groups from scratch this wouldn't have been a problem.  It's only because I was utilizing existing groups (and didn't check their type before adding them to a new group).  But it was a real problem with a pretty specific solution.

Monday, July 11, 2011

Correcting Dynamic Disk is Invalid message

This was a really odd situation in my VMware ESXi environment involving a virtual disk that needed resizing.  I needed to add a few gigabytes to a virtual hard disk, which I have done scores of times and have my process pretty well down pat.  This one was a little different and I had to do some research and obtain some new tools.

My normal process is this:
  1. Add space to the .vmdk using the vSphere Client / vCenter Console.
  2. Use the diskpart command on the server to select the disk and volume in question, then issue the extend command. 
  3. If the command cannot complete (because the disk is in use in a certain way by the server), then I have to shut down that server and add the hard disk to another virtual server (as it's D: drive, for example).  I then perform #2 above from that server's console, detach the disk, and then power up the original server.
It's one of my favorite little admin tasks to do in VMware, because I know what it would take for me to add disk space to a server in the "real world", and I giggle a little bit every time I do it.

Today when I tried to use diskpart I could not see the volume when I ran the list vol command.  I knew then that something was wrong.  I check Disk Management (it's a Windows Server 2003 machine) and saw that the disk was a dynamic disk and was "Invalid".  I had never seen that before.  I could still access the disk just fine -- I could still see and manipulate all the files on the disk... I just couldn't make any changes to the size.  I also did not recall ever converting the disk to a dynamic disk.

Now I'll fast forward to the end... there are a few resources out there for handling this situation.  The best, most concise one that I found is here.  The explanation is that a byte on the disk that identifies it as dynamic or basic has become corrupt somehow.  The HxD disk editor can be used to see the value and even make a change to it.  Be careful, though, because you can really mess things up if you aren't careful.

According to the above instructions the trick is to look at sector 0 location 1C2.  For dynamic disks this value should be 42.  For basic disks the value should be 07.  In my case the value was 07 but Disk Management was showing the disk type as dynamic.  The instructions in the link above say to only make a change if the value in 1C2 is 42 (change it to 07), so this did not fit my situation.  I did notice that the value just below it in the HxD window was 42 (location 1D2).  I decided to give it a try, so I changed the 1D2 location from 42 to 07 (to match the value in 1C2) and then my server booted just fine.

So, based on my experience I'll add that it's important for the 1C2 and 1D2 values to match.  Of course it's possible that this isn't applicable in all cases.

Sunday, July 10, 2011

Transferring a blog from Typepad to Blogger

I am sometimes asked to work on technology stuff around the house.  Surprise, surprise.  Today my wife asked me to help her transfer her blog from Typepad to Blogger/Blogspot.  I haven't fooled with blogging at all except for once before when there was some trouble with getting her Typepad blog started.  I only recall that is was a lot harder than I thought I should have been.  Lots of scripting, Linux/Web server stuff... I don't know how non-IT types get it done, as it was a real challenge for me.  Well, today I had another challenge on my hands.

She is adventurous enough to have taken the task as far as she could take it.  She was at a point where she had exported her Typepad blog posts (in an .mht file) and was trying to download the Google blog converter to convert that file to a Moveable Type file (.mt) so that the blog posts could be imported into Blogger.  Seems pretty simple, but there were several challenges.

The download file from Google's blog converter was a .gz file, and the computer where my wife blogs had no program to handle that type of archive.  I downloaded a 40-day trial of  WinRAR to handle this task, and then extracted the folder structure from the Google download file and stored it in a temporary location on the computer.  I then set about trying to use the converter.

The converter has sparse documentation but I did find a .\lib folder that has some batch files in it.  I used the one called movabletype2blogger.bat but it had errors.  Turns out I had to download and install Python (I used version 2.7).  I still received errors because the paths in the bat file were all wrong.  I pretty much hardcoded all the variable paths that the file's author had tried to make.  Here is the batch file that finally worked for me.  Note that I had installed Python into its default folder, \python27.

set PYTHONPATH=c:\python27
set BASEPATH=c:\temp\google-blog-converters-r89
set PYTHONPATH=%PYTHONPATH%;%BASEPATH%\lib
c:\python27\python "%BASEPATH%\src\movabletype2blogger\mt2b.py" %1

I continued to receive errors until I renamed the Typepad file from .mht to .mt. 

The command that I finally used was movabletype2blogger typepad-export-file.mt. run form a Command prompt, of course.  (I had to navigate to the C:\temp\google-blog-converters-r89\bin folder, first).

This produced several seconds worth of scrolling text down the computer screen because the script output was to "stdout", so I simply redirected the output to a file, like this:

movabletype2blogger typepad-export-file.mt > import-to-google.xml

A quick look at the .xml file showed that the file contained blog posts.  Success!  Seems like I'd almost be finished at this point, but no... the .xml file produced some mysterious error message with no explanation when I tried to import it into Blogger.  After some trial and error I was able to pare down the .xml file to a single post and did import it successfully.  To do so I opened a copy of the .xml file in notepad and searched for "ns0:entry" (for the beginning of a post) and "/ns0:entry" (for the end of a post).  I had to leave "</ns0:feed>" at the bottom, but I found the first "/ns0:entry" and deleted everything between it and the the "/ns0:feed" tag.  I then proceeded to use the same process to import additional posts, one at a time at first -- then several at a time.  At one point near the end of the 120+ posts the imports began failing.  I finally determined that the export from Typepad or the conversion process had placed all the comments (where people had commented on the blog posts) at the end of the .xml file, and these would not import. 

So after all that my wife's blog was up and running, but no comments from her Typepad blog were brought over.  The blog's pictures still pointed to her Typepad blog, so she had to re-point those to a different location for the pictures before she took down that blog.  There were also some minor formatting quirks that she had to work on (extra line breaks and such), but those were simply aesthetic.

So, with all that blog "piping" experience I thought I'd start up a blog and write about the experience.  Let me know if this helps you!

What this is all about

I'm a technology guy.  I sometimes tackle challenges or learn things that might be beneficial to others.  This blog is my attempt to share some of my experiences with you, in case you might have run into the same issues.  I'll keep the information here to my professional / technology life.

I'm on LinkedIn.