Getting Our Computername in a PowerShell Script

There are lots of reasons why you may want to get the name of your computer while you are executing a PowerShell script, from a parameter you want to pass to a cmdlet or function or for generating a filename.

Thankfully, PowerShell makes it easy.

Just like our old friend, cmd.exe, PowerShell makes the system-level environment variables available. Unlike cmd.exe, PowerShell doesn’t make them available by surrounding the environment variable by a percentage symbols. Instead, PowerShell uses a provider. This provider makes Environment variables look like a file system and allows you to access (or set) their contents by reading (or writing) that content.

For example, to examine all environment variables and see their contents in cmd.exe, you enter:

set

To get the equivalent output in PowerShell (including the variables being sorted by name), you enter:

dir env: | sort Name

In cmd.exe, to display the value of COMPUTERNAME, you enter:

echo %COMPUTERNAME%

In PowerShell, you enter:

gc env:computername

Or the long form of:

get-content env:computername

And to store the value of the computername into a variable in PowerShell:

$computer = gc env:computername

We’ll use this in my next post.

Until next time…

As always, if there are items you would like me to talk about, please drop me a line and let me know!


Follow me on twitter: @EssentialExch

Exchange Connections – Fall 2008

Next week, in Las Vegas, Nevada is the semiannual Connections conference. The Connections conference is a technical conference covering SQL Connections, Windows Connections, Exchange Connections, etc. There are lots of individual tracks, both for IT Pros and Devs.

I’ll be speaking next week at the conference, delivering three Exchange presentations:

EXC10: Exchange 2007 and Windows 2008: Backups the Easy Way (75 minutes)
In this presentation I’ll show you how to use the native Windows tools present in Windows 2008 to make Exchange 2007 backups AND to restore them. I’ll cover some theory, some philosophy, and lots of PowerShell.

EXC11: SMB Exchange Operations (60 minutes)
In this presentation I’ll discuss so key factors of Exchange day-to-day operations that affect the Small Business

EXC12: Building an Exchange Test Environment in a Hurry (75 minutes)
In this presentation I’ll discuss some of ways in which you can quickly generate a virtualized Exchange test environment. After all, all the time you spend building, is less time you can spend testing.

You can see the Event Schedule here and general conference information here.

Please come say “hi”. Even better – attend my presentations!

Until next time…

As always, if there are items you would like me to talk about, please drop me a line and let me know!


Follow me on twitter: @EssentialExch

Accessing a Web site with PowerShell

This is just another quick sample of what you can do in PowerShell by leveraging the .Net framework.

Need to access a website? No problem. System.Net.WebRequest to the rescue!

Note that you can specify credentials, read all the data, follow the links, etc. Just depends on how far you want to go…

function start-http([string]$url)
{
	$routine  = "start-http:"

	trap
	{
		log $routine "Trap: access URL $url."
		log $routine "Error = $_"
		log $routine $_.InvocationInfo.PositionMessage
		continue
	}

	$request  = [System.Net.WebRequest]::Create($url);
	$request.UseDefaultCredentials = $true

	$response = $request.GetResponse()
	if ($response)
	{
		log $routine "response statuscode = " $response.StatusDescription
		log $routine "response characterset = " $response.CharacterSet
		log $routine "response length in bytes = " `
			$response.ContentLength.ToString()

		$response.Close()
	}
}

Until next time…

As always, if there are items you would like me to talk about, please drop me a line and let me know!


Follow me on twitter: @EssentialExch

Groups and their Membership

I’m working with a new client and this client is a “wholly owned subsidiary” of another company and is getting ready to be spun off as their own company.

One of the things we are doing is configuring their network to be standalone and not part of the corporate Active Directory. That involves creating users, group, moving computers, installing a new Exchange organization, etc. etc.

But sometimes it’s the simple things that bite you…

We’d gotten an export of the OU for the subsidiary out of corporate in a CSV file – every object, every attribute. That was a mess in-and-of itself, but at least all the data was there.

So we started importing the data. And it broke.

Huh? We’d done this before and no problem. What was going on here?

Like I said – the simple things…

This set of users and groups were using embedded groups. Sometimes up to five levels deep. (That is, a group within a group within a group within a group within a group.)

Well, you can’t assign a group membership to a group that doesn’t exist! Seems obvious, in retrospect.

The solution? Go through and harvest all groups FIRST – just create the groups in Active Directory. Then, go back through and assign membership to the groups.

Here is a somewhat sanitized version of the code we used. On the first pass, it creates groups. On the second pass, it will assign membership to the groups. This shows a number of PowerShell techniques in group management – including creating groups, checking for membership in a group, and adding members to a group.

Also note: there are several places where this script could be optimized. But I was more interested in clarity (since, as a consultant, I won’t be there forever!).

I hope you find this useful for your scripts!

set-variable ADS_GROUP_TYPE_DOMAIN_LOCALGROUP 1          
set-variable ADS_GROUP_TYPE_GLOBAL_GROUP      2          
set-variable ADS_GROUP_TYPE_LOCAL_GROUP       4          
set-variable ADS_GROUP_TYPE_UNIVERSAL_GROUP   8          
set-variable ADS_GROUP_TYPE_SECURITY_ENABLED -2147483648 

$groupType = $ADS_GROUP_TYPE_GLOBAL_GROUP –bor $ADS_GROUP_TYPE_SECURITY_ENABLED

$csv = import-csv GroupsOnly.csv
#
# Each line contains the dn, the name, the description if one exists, and the member list
# with the dn of each group member. The member list has each member separated by a semi-colon.
#
foreach ($line in $csv)
{
	$dn = $line.dn
	$adsPath = "LDAP://" + $dn
	$objGroup = [ADSI]$adsPath
	if ($objGroup.Name)
	{
		# the above verifies that the group exists. Note that 
		# ADSI is "smart". It doesn't actually access AD and 
		# fill the property cache until you read an attribute
		# from the object.
		"Exists: " + $line.Name
		if ($line.member.Length -gt 0)
		{
			$i = 0
			$members = $line.member.Split(";")
			$lower   = $dn.ToLower()
			foreach ($member in $members)
			{
				$objMember = [ADSI]("LDAP://" + $member)
				if ($objMember.Name)
				{
					# check to see if member is already in group
					[bool]$already = $false
					$userGroups = $objMember.memberOf.Value
					if ($userGroups)
					{
						foreach ($usergroup in $userGroups)
						{
							if ($userGroup.ToLower() -eq $lower)
							{
								$already = $true
								break
							}
						}
					}
					$objMember = $null
					if ($already)
					{
						"`tAlready in group: $member"
					}
					else
					{
						$objGroup.Add(("LDAP://" + $member))
						if ($?)
						{
							"`tAdded to group: $member"
							$i++
						}
						else
						{
							# should be an error displayed on the PowerShell window
							"`tCouldn't add to group: $member"
						}
					}
				}
				else
				{
					# member specified in CSV doesn't exist in Active Directory
					"`tObject doesn't exist: $member"
				}
			}
			"`tadded $i members"
		}
		else
		{
			# members element of the CSV was empty
			"`tno members specified for group"
		}
		$objGroup = $null
	}
	else 
	{
		"Creating " + $line.Name

		$parent = "LDAP://" + $dn.SubString(1 + $dn.IndexOf(","))
		$object = [ADSI]$parent
		$child  = $object.Create("group", "CN=" + $line.Name)

		$child.Put("groupType",      $groupType)
		$child.Put("sAMAccountName", $line.name)
		$child.Put("name",           $line.name)

		if ($line.description.length -gt 0)
		{
			$child.Put("description",    $line.description)
		}

		$child.SetInfo()
		$child = $null

	}

	sleep -milli 500
}

$csv = $null

Until next time…

As always, if there are items you would like me to talk about, please drop me a line and let me know!


Follow me on twitter: @EssentialExch

I Have a Logo!

In case anyone besides me is counting, I’ve been at this (consulting, writing, speaking, etc.) for 10 months now. I’m having a blast. I wish I’d done this years ago.

Two months ago I took on a partner and we formed Smith Consulting d/b/a The Essential Exchange as a legal entity (as opposed to the sole proprietership I was previously).

After several weeks of back-and-forth, we finally came up with a logo today, and I’m very pleased with it. It will replace the generic icons you see on this blog fairly soon (image manipulation is not my strong suit). Here it is:


Follow me on twitter: @EssentialExch