Wednesday, September 30, 2009

Enable SCCM OSD Task Sequence to determine location

So after weeks of messing around with VB Script and PowerShell, I've finally found a solution to allowing a task sequence in SCCM to "learn" where it's at automatically. Here's some background information to know where this is coming from...

One of my SCCM Site Servers manages workstations in two different Active Directory sites. One site sits in the Eastern Standard time zone, while the other is in the Arizona time zone. Up until now, all my task sequences have had to be duplicated, one for each time zone, all of which advertised to the Unknown Computers collection. Needless to say, this made a mess of a list when you would boot a computer into WinPE to image the workstation. The end goal that I wanted was one task sequence to be advertised to the Unknown Computers collection and it just automatically go when a computer boots to WinPE, assigning time zones and computers names according to the physical location of the workstation.

So, with knowing what I wanted in mind, I started searching for how I could do it. I knew right off the bat that I would need to create a condition in the task sequence. At first I tried create a WMI condition, but that didn't work for whatever reasons, so I started looking into task sequence variables. I quickly found how to set a task sequence variable in VBScript, and started messing with creating a VBScript that could get the IP address of the workstation it ran on, then determine what site it's in and assign the TS variable accordingly. Unfortunately I suck at VBScript, and had to keep going to a friend for assistance. After a week of that and still no solution I decided to go after PowerShell. I started out in PowerShell having it query WMI for the IP address, then using If Then statements to determine what site it was in. At the end if the site was columbus, the TS Variable would be made Columbus, if the site was Pheonix, obviously the TS Variable was that as well. Below is the code at that point.

Location1.ps1 (Stripped down version)
$wmi = gwmi -q "Select * from Win32_NetworkAdapterConfiguration where IPEnabled = True"
    if ( $wmi.IPAddress -like "10.15.20*")
        {$local = "Columbus"}
    else
        {$temp = "NotColumbus"}
             
   if ( $wmi.IPAddress -like "10.15.36*")
        {$local = "Phoenix"}
    else
        {$temp = "NotPhoenix"}
       
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$tsenv.Value("location") = "$local"

The above script works fine it your dealing with workstations with only 1 NIC 100% of the time. If at any time a workstation with more than 1 NIC (even wireless cards (laptops)) try to run this, they fail. I believe they fail because the second NIC (even though it's not plugged into anything or connected to a wireless network) is still IPEnabled and that's what the above script looks for. At that point I got a suggestion off Experts Exchange to have it exclude adapters that have an IP Address of 0.0.0.0. At first I thought this would work great. Half way through testing it I realized that it wouldn't fix the issue because there's no IP address assigned to the second network card. But, below is the modified part of the original script. 

location2.ps1 (only the modified section)

 $wmi = gwmi -q "Select * from Win32_NetworkAdapterConfiguration where IPEnabled = true" | ? {$_.IPAddress -ne "0.0.0.0"}

After the above also wasn't working, I decided I needed to go a differant direction with how I was pulling the IP Address information. I tried to change the way I was querying WMI, but that didn't work. Finally, I ran accross this script that used ipconfig in PowerShell, then captured the IP address. I thought it threw before wasting time on yet another script, and figured it should work. Go figure, it did. Works great, and now I have a solution to my original issue of wanting just one task sequence for multiple time zones. Below is the new script.  


location3.ps1 (the one that ended up working, stripped down version)
$IP = ((ipconfig |findstr [0-9].\.)[0]).split()[-1]

    if ( $IP -like "10.15.20*")
        {$local = "Columbus"}
    else
        {$temp = "NotColumbus"}
                  
   if ( $IP -like "10.15.36*")
        {$local = "Phoenix"}
    else
        {$temp = "NotPhoenix"}
       
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$tsenv.Value("location") = "$local"


In case anyone was also wondering how I placed this in my task sequence, I shall show you.

Here is a screen shot of the top part of my task sequence.




The TS starts off with your normal restart the computer, and wipe the disc. When it comes to installing an OS, I'm installing an OS package, not an image. (Due to the wants/needs of the company) It installs the Windows XP SP3 package, applies Windows Settings and sets the time zone to Eastern Standard at that point. It then (skip a few tasks...) installs .NET 3.5, PowerShell v2, and applies  PowerShells execution policy. It reboots to apply all the new shit I just did, then runs "Discover Location". At that point, it's running the above script. Then right below that you see two folders with tasks. This should be obvious, but I'll say it anyways... if the TS Variable produced by the script reads Arizona, then the Arizona folder runs and the Columbus folder is skipped. If the TS Variable produces Columbus, the Arizona folder is skipped and the Columbus folder is ran. Each folder has Task Sequence Variable conditions that make this happen. In case your imagination isn't going yet, you can use this same idea here to install different software based on a location as well. Pretty sweet.

On another topic, I found this sweet thing for iPhones. If you're running version 3.0 (and if you're running 3.1 you can always downgrade...) you can get tethering on your phone by going to "help.benm.at/help.php" on your phones browser. As long as you have an unlimited data plan (which I'm not sure if AT&T offers anything but that for the iPhone) you can then tether your iPhone to your computer via USB or Bluetooth for internet access.

Enjoy

Tuesday, September 29, 2009

More PowerShell

So I've been working more with PowerShell today... not on the creating a local user stuff that I should prolly focus more on, but other cool stuff you can do. I think all together I've got scripts now that can set printer permissions, set folder permissions, reboot the system, send emails, and plenty more. At the end of this are the scripts themselves for anyone to see and use. I'm currently working on one that will take the IP address of a computer and turn it into an SCCM variable. I thought I had it nailed down, but ended up I didn't. I think I've since corrected the issue, and I'm currently testing it in a Hyper-V virtual machine to find out. That will prolly come tomorrow.

I came across an interesting article today. It is basically saying that disc encryption isn't as secure as people thought. Pretty interesting.... makes me love the fact that the government has my information on laptops with encryption like this.
http://www.wired.com/threatlevel/2008/02/researchers-dis/

Also found this, it's nice to see.
http://www.wired.com/threatlevel/2009/08/churchill/

Last but not least, I found this. I haven't tested it or played around with it, but it looks as if it's free antivirus software from Microsoft as long as you have a legit copy of Windows.... I have a non-profit I work with that might be interested in this....
http://www.microsoft.com/security_essentials/


The Scripts
Setting Printer Permissions
gwmi -class Win32_Printer -comp ServerName | % { $_.Name} | % { subinacl.exe /printer \\ServerName\$_ /grant=DomainName\GroupName=F}
# F means full control
# M means manage
# P mean print

Setting folder permissions
 $acl = Get-Acl c:\temp
$permission = "domain\user","FullControl","Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl c:\temp

Reboot a system
$server = gwmi Win32_operatingsystem -computer Your_Servername
$server.reboot()

## to know what else is availabe run the following
# $server | get-member

Send an email
$SmtpClient = new-object system.net.mail.smtpClient
$SmtpServer = "YOUR_SERVER_IP"
$SmtpClient.host =
$SmtpServer


$From = "FROM_ADDRESS"
$To = "SEND_TO"
$Title = "SUBJECT"
$Body = " BODY_OF_EMAIL"
$SmtpClient.Send($from,$to,$title,$Body)  


 
 
Enjoy

Monday, September 28, 2009

Loaner Laptops and Auto Logon

So I ended up taking last Friday off from work, and had a great 3 day weekend. However before taking it off, I acknowledged to myself that something would break, and alot of work would be backed up on Monday to do. So when I came into work today, I wasn't surprised with the stuff to do.

The first thing I did was checkup on the status of the two SCCM Site Servers I manage. The one had all green check marks, while the other was mostly red. After digging into the logs on the SCCM side of things, I found that the C:\ drive had 256KB of free space left. Obviously something was wrong... After remoting in and digging some more, I narrowed the space hog down to C:\Windows\System32 (which scared me a little bit). After going folder by folder I found that the folder LogFiles had eaten up about 10GB worth of space... Ends up that since SCCM uses IIS, and that IIS by default logs a bunch of shit to the C:\Windows\System32\LogFiles directory, that by leaving this unattended, I ran out of space.

The second thing that came up was a laptop that was imaged last Friday and didn't auto logon. When I was told of this I remembered that I had modified the task sequences to send email notifications using PowerShell, so I figured that something didn't go right and the auto logon registry file never got imported. As I thought, I was correct. The task sequence failed at installing .NET 2.0. Since I had not tested the task sequence, I was to blame on this. On the machines I had tested this on, Windows XP SP3 was automatically/manually installed, while this TS was using .wim images that already had .NET 2.0. I'm assuming that the images already had .NET 2.0 and the step that installed it failed because it was already installed. So I corrected this (so I thought) by removing all the images from the TS and replacing them with the XP SP3 install. That corrected the .NET installation fine, but when it came to the auto logon, that was a failure. Ends up that the .wim images I configured a long time ago had a local user account, so now that I'm installing XP SP3 base, there's no local account. My task was now to find a way to script in to create a local user account. I'm aware of the VB scripts and batch files that can do this task, but I wanted to have it done using PowerShell. So I dove into hours of looking up how to do it. I ended up finding a way that worked fine on my workstation running Windows 7 RTM, and the page on Microsoft claimed this would work on XP, but it didn't. The TS ran the PowerShell script fine, and finished imaging the laptop but when it came time to reboot, then auto logon, no local user account was found. So while I continue to find a way to get PowerShell to create a user account on Windows XP, the rest of you guys out there working with companies that are willing to get off the XP platform can use my time spent on configuring a script for yourself and copy n' paste the below.


Here is the script you run to create a local user account called "User"

param($computer="localhost", $user="user", $password="")
$objOu = [ADSI]"WinNT://$computer"
$objUser = $objOU.Create("User", $User)
$objUser.setpassword($password)
$objUser.SetInfo()
$objUser.description = "Test User"
$objUser.SetInfo()

$objUser = [ADSI]("WinNT://$computer/User")
$objGroup = [ADSI]("WinNT://$computer/Administrators")
$objGroup.PSBase.Invoke("Add",$objUser.PSBase.Path)


Here's the script that will add that local user you just made to the local Administrators account.

$sysname = gwmi -q "Select Name from Win32_ComputerSystem"
$admgrp = [ADSI]”WinNT://$($sysname.Name)/Administrators,group”
$admgrp.add("WinNT://$($sysname.Name)/user")


Enjoy

Saturday, September 26, 2009

The first blog...

I took work off today, so i got nothin really... but i was surfing MSNBC and found this crazy ass looking lizard. Looks like this thing dropped right out of space!