January 2008 - Posts

I've been using Vista for a long time, since fairly early in the beta process. After the relearning associated with the various changes in menus and the start menu, I've had good luck with it. I'm one of those rare folks - I really like Vista.

My main complaint has always been about it being sluggish compared to Windows XP.

As many of my regular readers know, I recently became an independent consultant. For the first time in many years, I had to go out and purchase my own laptop and software. I was very careful, of course, about spending my own money. :-)

I got a Vista laptop, with 2 GB RAM and a 64-bit capable processor. However, I stayed with the standard 32-bit version of Vista.

Being a consultant, I often need to build virtual machines and have multiple virtual machines open at the same time. When you are doing that, 2 GB of RAM doesn't go far! So, I upgraded my laptop to 4 GB.

However, I was immediately disapointed - Vista only saw 3.2 GB! While that was an improvement, I wanted that 800 MB back!

I won't go into the various reasons as to why a 32-bit OS will probably not recognize all 4 GB of available RAM. It has to do with I/O space, page remapping, user space vs. kernel space, and loads of other esoteric items that I'm not sure I completely understand myself. However, suffice it to say that I expected some loss, but I was only expecting a loss of around 250 MB, which is pretty typical for an Intel server grade chipset and 4 GB RAM.

However, in the new laptop, I went with an AMD Turion, which is a 64-bit consumer grade chipset, with loads and loads of expansion capability - all of which uses up I/O space. Bah.

So, a couple of days ago, I gritted my teeth, downloaded Vista 64-bit and went for it.

As you may or may not be aware, there is not a real "upgrade" from 32-bit Vista to 64-bit Vista. You must boot from a 64-bit CD-ROM. All of the user profiles are moved, the Windows directory is renamed to Windows.old, the registry is re-initialized, Program Files are renamed and removed, etc. It is effectively a completely new installation of the Operating System, with some pieces saved. You have to re-install everything. Much more of a migration than an upgrade.

So, before I "went for it", I made some fairly extensive preparations:

  • I made a list of all installed programs
  • I made a list of all installation keys
  • I checked all of the programs and downloaded new copies of them, paying special attention to those having 64-bit editions
  • I went to the laptop vendor site and downloaded all of their 64-bit drivers
  • When I couldn't find drivers there, I went to the part manufacturer's site and got the drivers there
  • When THAT failed, I searched until I found a missing driver (my laptop is not a Dell, but in one specific case, the only place I could find a 64-bit version of a driver I needed was on the Dell support site - and it worked fine!).
  • I cleaned up my laptop, removing unused programs and various other junk
  • I made multiple backups of my data - including my user profile (which contains Documents and Outlook OSTs and other stuff)

Then, I stuck the CD in and followed the bouncing balls.

Vista 64-bit came up about an hour later. And then I started installing drivers. After about another hour and a half of installing a driver and then rebooting (lather, rinse, repeat), I had all of my hardware back and I was back on the Internet. Another hour of installing Office Professional, Project, Visio, Daemon Tools, PowerShell and OneNote - and I was back and could work.

The most stressful moment came when I renamed my old profile \Windows.old\users\michael to \Users\Michael and then rebooted. Would everything come back? And yes, it did - with one notable exception.

Passwords. Passwords to everything (Outlook, Windows Mail, Internet Explorer, etc.) had to be re-entered. Not really a shocker. Since there is a new registry in the machine, and a new machine-key was generated during the installation, all of the old cryptographic information that was stored was invalidated.

Was it worth it?

A resounding yes!

I have all my RAM - and you know what? Vista is NOT sluggish anymore. It is as responsive as Windows XP ever was. I wish I had done it when I first got the laptop. It's great.

Everything I want to do seems to work fine. Granted, it'll take a week or two until I actually install everything I use; but all of my main tools work.

Try it - you might like it too!

Posted by michael | 5 comment(s)
Filed under:

In this post, I began talking about licensing of the various Unified Communications (UC) products, starting with Exchange Server. I followed that with this post discussing licensing for the next of the UC products - Office Communication Server.

As part of that second post, I promised that if people wanted to know about Microsoft Office SharePoint Server (MOSS) licensing, I'd write that up before closing out the series. I wish my fingers had never typed that sentence! :-) After I did the research, that article has proven fairly difficult to assemble and write.

SharePoint is a full product suite. Licensing for SharePoint is even more convoluted than your normal Microsoft licensing mumbo-jumbo. Regardless, let's dive right in.

Remember: I am not a lawyer. Nor am I a Microsoft Licensing expert. The information in this post comes from various publicly available Microsoft websites as of the date I authored the post. For further information contact Microsoft Licensing at http://microsoft.com/licensing.

SharePoint comes in five editions, one of which isn't labeled as part of the SharePoint Suite, although it is. Those editions and their estimated retail price (in US dollars) are:

SharePoint Edition Cost
Windows SharePoint Services 3.0 "free"
Microsoft Office SharePoint Server 2007 $4,424
Microsoft Office SharePoint Server 2007 for Search Standard $8,213
Microsoft Office SharePoint Server 2007 for Search Enterprise $57,670
Microsoft Forms Server 2007 $4,424

There are also a number of Client Access Licenses (CALs) that may be needed by a company in order to use these products. The CALs associated with the SharePoint Suite are:

Client Access License Cost
Windows Server CAL $27
Microsoft Office SharePoint Server 2007 CAL, Standard Edition $94
Microsoft Office SharePoint Server 2007 CAL, Enterprise Edition $75
Microsoft Office Forms Server 2007 CAL $54
Office SharePoint Designer 2007 $187

Please note that items I have not included above include Windows Server licenses, SQL Server licenses, and SQL Server CALs; all of which would be part of any MOSS deployment.

did choose to include a Windows Server CAL in the above list to press home the point that all SharePoint users are authenticated Active Directory users and thus require a Windows Server CAL (the only exception is when you purchase a Internet Connector license - but we will not cover those in this article).

Also note that while Windows SharePoint Services 3.0 (WSS) is no additional cost, it does require that you have valid licenses for Windows Server 2003 and each WSS user does require a Windows Server CAL.

Microsoft has designed the SharePoint suite around eight key pillars of functionality. They are:

  • Collaboration
  • Portal
  • Search
  • Content Management and Workflow
  • Business Processes and Forms
  • Business Intelligence
  • SharePoint Management
  • SharePoint Platform Capabilities

WSS is the "little brother" of the SharePoint family. It includes the basic SharePoint Management tools and all of the Collaboration capability available in the other more feature-rich products. In every other way, it falls short. For Search, only site search is available. For Portal capabilities, only Microsoft Office integration is present. For Content Management, only a document information panel is available. The list goes on.

Having said that, WSS is the base of all the other products in the suite. All of the MOSS capabilities have WSS at the bottom. From little acorns do mighty oak trees grow... Given WSS and the Office SharePoint Designer 2007 product (plus Visual Studio 2005, I'm sure!), you could eventually grow your own version of MOSS. I suspect the build-vs-buy equation is pretty easy to calculate though!

The "step up" from WSS is to Microsoft Office SharePoint Server. With a few notable exceptions discussed below, it includes the full capabilities of the SharePoint suite, dependent on licensing. To use MOSS requires that you purchase the server license plus the Standard CAL. A Standard CAL is required for each user, of course.

If you want more features, then you purchase the Enterprise CAL. As we've seen in the other UC products, the Enterprise CAL is additive - that is, it adds features on top of the Standard CAL, but each user requiring the Enterprise feature set must have both the Standard CAL AND the Enterprise CAL.

The Enterprise CAL adds rights for you to use Line of Business data integration capabilities, Business Intelligence capabilities, which include the performance management dashboard and web-based spreadsheets, and electronic forms. And, if you've purchased one of the search capable server products, the search capability.

The electronic forms piece of the Enterprise CAL is significant. The Enterprise CAL includes a Microsoft Office Forms Server 2007 CAL. However, if you just want the MOFS capability without the rest of the Enterprise capabilities, you can purchase the MOFS licenses separately. Do note that using MOFS (or the forms capabilities with the Enterprise CAL) requires that your Microsoft Office clients have Infopath capabilities (which is an entirely other kettle of fish).

The final additional capability we haven't discussed is Search. The two final MOSS editions add integrated Enterprise Search capabilities into the MOSS product suite. This means that the MOSS engine has the capability of scanning local and remote locations and indexing documents, databases, images, media, etc. in those locations and making that index available for searching. The Search Standard MOSS edition only supports 500,000 items. The Search Enterprise MOSS edition supports an "infinite" number of indexed items.

Without one of the Search Editions, all of the other SharePoint editions will only provide "site search" - that is, searching the items that are part of the various SharePoint sites.

That concludes this SharePoint article. I think we'll have two more licensing articles before we conclude this series: one on Internet connector/Processor licenses, and then one showing a couple of fully priced out solutions.

If you ever have articles that you would like to see written, please leave me a message on the blog, or send me an e-mail directly to michael at TheEssentialExchange dot com.

References for today's article:
How to Buy Microsoft Office SharePoint Server 2007
Microsoft Office SharePoint Server Editions
Microsoft Office SharePoint Server 2007 products comparison
How to Buy Microsoft Office SharePoint Server 2007
Microsoft Office SharePoint Server 2007 ad Related Technologies Pricing

Posted by michael | 2 comment(s)

Windows Vista service pack 1 is due "any time now". Various on-line blogs and articles are saying anywhere from February 1 to February 15, although Microsoft could wait all the way until the end of March and still meet their "Q1 2008" official time-line.

Vista will be released via Microsoft Update, WSUS, and System Center Essentials. However, there is a problem... Windows Server 2003 sp1 and Windows Server 2003 sp2 cannot verify the electronic signature on files as large as the service pack! Once you approve the update, you will download the service pack, verification will fail, and you'll download it again... not a loop you want to get into with WSUS.

There is a hotfix. This falls into the "get it, install it, don't forget it" category.

The hotfix is KB 938759, "You cannot distribute or install a software package in Windows Server 2003 if the software package contains a very large signed file".

This is from the System Center Essentials Team Blog.

Posted by michael | with no comments
Filed under: ,

Marc Maiffret and I recently had a conversation on an e-mail based discussion forum. Marc is one of the founders of eEye (who produce the Blink and Retina digital security products) and he has recently gone out on his own again. I asked Marc about reproducing that conversation and he said "ok". See the meat of the thread below (read from the bottom up!):

From: Marc Maiffret [mailto:marc@marcmaiffret.com]

Sent: Thursday, January 24, 2008 7:36 PM

Subject: RE: [OT] Gmail in the workplace


I had been trying to avoid a blog for a long time because a lot of people

end up blogging about the weather and funny things their cat does and I

didn't want to turn into one of those people for the same reasons I don't

like watching TV. But alas I made a new year's resolution to get off my bum

and finally create a blog to have an answer for everyone I run into at

conferences. Will be live on marcmaiffret.com next week, and probably look

about as ugly as the current page. :-)

 

You could probably link to the email in the sunbelt mail archive (if there

is one) or otherwise go ahead and copy and paste away, there are no lawyers

in this house.

 

-Marc

 

-----Original Message-----

From: Michael B. Smith [mailto:michael@TheEssentialExchange.com]

Sent: Thursday, January 24, 2008 1:37 PM

Subject: RE: [OT] Gmail in the workplace

 

I can assure that at least the Exchange MVPs have seen the writing on the

wall.

 

Microsoft has increased the "cost of entry" to Exchange 2007. Not for the

basic features - the cost is the same for those, except for hardware

replacement. But to use the more advanced capabilities - the need for true

administration and cost of the feature content has increased. We've

discussed this quite a bit among ourselves.

 

In the short term, there is also no question that based on the

cost-benefit-ratio associated with Exchange (and unified communications in

general) that Microsoft is driving small business to hosted Exchange and to

Microsoft Live, depending on the feature set the business requires. I've

written several articles on this, from a forward looking perspective. I've

not been as quite hardcore as you are below!

 

In the short-term for medium business, I'm not sure MSFT has decided

themselves. Centro is great. Exchange is an integral piece of that product.

 

In the long-term, well, I can't say.

 

Good post. Have you blogged it? I'd like to link to it. :-)

 

Regards,

 

Michael B. Smith

MCSE/Exchange MVP

http://TheEssentialExchange.com

 

-----Original Message-----

From: Marc Maiffret [mailto:marc@marcmaiffret.com]

Sent: Thursday, January 24, 2008 4:20 PM

Subject: RE: [OT] Gmail in the workplace

 

I figured we would have more emails like this by now but I guess Google Apps

and Windows Live are walking instead of running.

 

The reality is that a lot of people who depend on Microsoft and small

business consulting are going to slowly see a drop in the requirements (time

you can bill for) in consulting and maintaining SMB organizations. That is

the one thing that Microsoft does not tell all of its die hard MVP's about

as it relates to its Microsoft Live initiatives.

 

In order for Microsoft Live to be successful it means creating a web

business infrastructure that an average joe business guy can use himself,

self maintaining system etc... It cannot be said any more clearly than for

Microsoft Live business services to be successful they must make the need

for companies like g2support to be extremely minimal. I know that sounds

harsh but if you talk with the business folks at Microsoft Live, look at

their product strategy and how they measure success, it simply is this way.

 

If Microsoft is successful then the idea of selling, setting up, and

supporting a company with SBS or Exchange and whatever else is going to be a

thing of the past. Obviously there will still be network maintenance and

what not but even things like backup will soon be nicely rolled into

Microsoft and Google online services therefore not requiring companies like

yours to do it for people. Again I am not trying to be harsh but realistic

about what is coming, or at least what Microsoft and Google would like to

have.

 

See at the end of the day when your consulting at a place like a small

mortgage company the reality is that that mortgage company does not want to

have to bother with you or any of the other hassles of technology. They just

want to deal with mortgages as that is how they make money. So if they can

get a hassle free (as MS and Google market it) solution that is also cheaper

than what you are charging them then they are all for it. And Microsoft and

Google obviously look at it as new revenue streams and while some people

might think "but they wouldn't put me out of business I've been a loyal bla

bla bla" ... well it's just business and the current idea of both the small

mortgage company and Microsoft/Google is that companies like yours do not

need to be part of the equation as it is cheaper for the mortgage company

and new money for Microsoft/Google.

 

Change is coming, and a lot of it, and if I was a company that has been

capitalizing off of SMB IT management of Windows environments I would start

thinking about the future, the changing landscape, and new ways to generate

revenue. Again I don't think it is going to happen tomorrow so I am not

shouting fire or trying to sound scary. But it is coming and you should

definitely be forward thinking about it as Oliver is doing here.

 

Of course the rate at which this change comes will depend on the technology

progress that Google and Microsoft make. Right now Google Apps is pretty

weak and simply an email system with not much else. Microsoft's offering has

a bit more bells and whistles but that is just because they are giving you a

hosted SharePoint system on top of email and they tailored some of the

SharePoint functionality to give the appearance of their solution having

more meat than it really does.

 

Now of course one man's downside is another man's upside.... there is a lot

of money to be made in this new world that is on its way if you adapt

yourself. At the end of the day people will pay you to help make them more

money or streamline their business, which helps make them more money. And as

I said there are a lot of things lacking with Microsoft Live and Google Apps

and the right minded people could capitalize a lot on those lacking features

and functions. Such as helping that mortgage company have better integration

between their Microsoft Live service and salesforce.com or whatever else

comes to mind.

 

I know that this does not answer your original question but that is because

I think you are asking the wrong questionSleep. In business if you are not a

company that can affect change then you should strive to embrace it. I have

seen more companies fail because of lack of fluidity than anything else.

While you can get some short term mileage out of learning how to sell people

on SBS, even though the market is moving towards Google Apps and Microsoft

Live, you will suffer in the long run. So get the team together for a brain

storming session, and get the google alerts going for Google Apps and

Windows Live to start learning about what others are doing to capitalize and

adapt.

 

-Marc Maiffret

www.marcmaiffret.com

 

 

Posted by michael | 2 comment(s)

In Part 1 of this mini-series I presented the beginnings of a database layer supporting three different database architectures, that could easily be extended to handle more database engines. In Part 2 we built on Part 1 and discussed variable handling techniques.

In this article, Part 3, we'll build on Parts 1 and 2 to display techniques for searching, creating, modifying, and deleting data using this database layer.

First, while we haven't covered DDL - Data Definition Language - the part of SQL that deals with the creation of databases, tables, indexes, etc. - we need at least one table with which to practice. Here are the three sets of DDL that will create our practice table for each interesting platform. You'll note that all three are actually quite similar, but every single one is a little different. There are also some differences in how Access specifically handles NULLs; but that does not come into play in this example.

# create database and table for MS-SQL Server
CREATE DATABASE [SampleDB]
GO
USE [SampleDB]
GO
CREATE TABLE [Users] (
  [ID] int NOT NULL IDENTITY(1,1),
  [Name] varchar(255) default NULL,
  [Email] varchar(255) default NULL,
  [Approved] bit NOT NULL,
  PRIMARY KEY  ([ID])
)
GO
#
# now some test records
#
INSERT INTO [Users] ([Name], [Email], [Approved]) VALUES ('Michael B. Smith', 'michael@TheEssentialExchange.com', 1)
INSERT INTO [Users] ([Name], [Email], [Approved]) VALUES ('John C. Doe',      'john@cvilleswings.com',            0)
INSERT INTO [Users] ([Name], [Email], [Approved]) VALUES ('Jane E. Doe',      'jane@msmithome.com',               1)
GO

# create database and table for mysql
CREATE DATABASE `SampleDB`;
USE `SampleDB`;
CREATE TABLE `Users` (
  `ID` int NOT NULL auto_increment,
  `Name` varchar(255) default NULL,
  `Email` varchar(255) default NULL,
  `Approved` boolean NOT NULL,
  PRIMARY KEY  (`ID`)
);
#
# now some test records
#
INSERT INTO `Users` (`Name`, `Email`, `Approved`) VALUES ('Michael B. Smith', 'michael@TheEssentialExchange.com', TRUE);
INSERT INTO `Users` (`Name`, `Email`, `Approved`) VALUES ('John C. Doe',      'john@cvilleswings.com',            FALSE);
INSERT INTO `Users` (`Name`, `Email`, `Approved`) VALUES ('Jane E. Doe',      'jane@msmithome.com',               TRUE);

# create database and table for ms-access
# Access doesn't recognize "create database" or "use"
# you must do them manually or via ADO.
#
# CREATE DATABASE [SampleDB];
# USE [SampleDB];
#
# create table
#
CREATE TABLE [Users] (
  [ID] counter NOT NULL ,
  [Name] varchar(255),
  [Email] varchar(255),
  [Approved] bit NOT NULL,
  PRIMARY KEY  ([ID])
)
# 
# now some test records
#
INSERT INTO [Users] ([Name], [Email], [Approved]) VALUES ('Michael B. Smith', 'michael@TheEssentialExchange.com', TRUE)
INSERT INTO [Users] ([Name], [Email], [Approved]) VALUES ('John C. Doe',      'john@cvilleswings.com',            FALSE)
INSERT INTO [Users] ([Name], [Email], [Approved]) VALUES ('Jane E. Doe',      'jane@msmithome.com',               TRUE)

For use of the database layer, in this article I showed using global variables to maintain database state. I continue using that mechanism for modification of values in each table. For each table, I establish a set of global variables. To wit:

$global:SampleUsersID       = $null
$global:SampleUsersName     = $null
$global:SampleUsersEmail    = $null
$global:SampleUsersApproved = $null

Now, each time I want to transfer a record from the Users table or to the Users table, the code will go through the global variables. Let's take a look at the code that retrieves a record first.

function dbTransferUsersToGlobal($result)
{
	$global:SampleUsersID       = $result.Item("ID")
	$global:SampleUsersName     = $result.Item("Name")
	$global:SampleUsersEmail    = $result.Item("Email")
	$global:SampleUsersApproved = $result.Item("Approved")
}

The function dbTransferUsersToGlobal will be called after a dbExecute routine has been called. For example, to display all of the records in the Users table, we would execute this code:

function dbDisplayAllUsers
{
	$result = dbExecute ("SELECT * FROM " + (dbQuote "Users"))
	if (!$result)
	{
		"The query returned no records from the Users table."
	}
	else
	{
		if ($result.Count -gt 1)
		{
			foreach ($rec in $result)
			{
				dbTransferUsersToGlobal $rec
				"ID=$SampleUsersID Name=$SampleUsersName Email=$SampleUsersEmail Approved=$SampleUsersApproved"
			}
		}
		else
		{
			dbTransferUsersToGlobal $result
			"ID=$SampleUsersID Name=$SampleUsersName Email=$SampleUsersEmail Approved=$SampleUsersApproved"
		}
	}
}

dbOpen
dbDisplayAllUsers
dbClose

Executing queries is just that simple. Obviously, for efficiencies sake, you would open the database at the beginning of a program and close it at the end of a program, not do an open and close for each query. You will note some minor differences in the results output by the database engines. Both MS-Access and MS-SQL Server treat the boolean values as booleans, and output 'TRUE' or 'FALSE' for the [Approved] column. However, MySQL will output '0' for 'False' and '1' for 'True'. I find this most interesting, as MySQL supports using TRUE and FALSE in the INSERT statement whereas MS-SQL does not. (And in one of the rare cases where MS-Access has a feature that MS-SQL does not, MS-Access allows it as well.)

The mechanisms we've established so far for accessing the ODBC layer of the database allow us fine grained control of the results from the queries. This can come in quite handy. Of course, the power of SQL comes into play when we can create records and when we can make conditional queries. To create a record, we follow the same ideas as we've seen so far. For example, see this routine:

function dbCreateUsers
{
	# we depend on the auto-increment functionality to set the ID
	# variable automagically
	$q  = "INSERT INTO " + (dbQuote "Users") + " ("
	$q += (dbQuote "Name") + ", " + (dbQuote "Email") + ", " + (dbQuote "Approved")

	$q += ") VALUES ("

	$q += (dbText $SampleUsersName    ) + ", "
	$q += (dbText $SampleUsersEmail   ) + ", "
	$q += (dbBool $SampleUsersApproved) + ")"

	#log "dbCreateUsers:" ("query='" + $q + "'")

	$result = dbExecuteNonQuery $q
	if ($result -lt 0)
	{
		throw ("Failed creating Users record.")
	}

	return $result
}

dbOpen
$global:SampleUsersApproved=0
$global:SampleUsersEmail='jack@example.com'
$global:SampleUsersName='Jack Spratt'
dbCreateUsers
dbClose

Deleting a record is almost exactly the same. However, unless we intend to delete all of the records in a table then we must specify a condition to be satisfied to delete the record. Since the ID variable is the primary key of the table, it is the most efficient value to use. However, you can use any column in a table for a deletion condition. However, if you are going to commonly use a particular column for searching or deletion, then it should be added into an index and that index used to speed searching.

Here is an example routine for executing a deletion.

function dbDeleteUsers([int]$id)
{
	$q  = "DELETE FROM " + (dbQuote "Users") + " "
	$q += "WHERE " + (dbQuote "ID") + "=" + (dbInt $id)

	#log "dbDeleteUsers:" ("query='" + $q + "'")

	$result = dbExecuteNonQuery $q
	if ($result -ne 1)
	{
		throw ("dbDeleteUsers failed. result = $result")
	}

	return $result
}

dbOpen
# delete the "Jack Spratt" record
dbDeleteUsers 4
dbClose

And finally, last but certainly not least, we need to have a way to update an existing Users record. The same issues mentioned before regarding use of the ID column apply to updates as well as deletes. If you have been following along with these examples, then the ID value for "John C. Doe" is 2. But we've just discovered that his middle initial is "A." So, we execute the code below to correct this problem.

function dbUpdateUsers([int]$id)
{
	$q  = "UPDATE " + (dbQuote "Users") + " SET "

	$q += (dbQuote "Name"    ) + " = " + (dbText $SampleUsersName)     + ", "
	$q += (dbQuote "Email"   ) + " = " + (dbText $SampleUsersEmail)    + ", "
	$q += (dbQuote "Approved") + " = " + (dbBool $SampleUsersApproved) + " "

	$q += "WHERE " + (dbQuote "ID") + "=" + (dbInt $id)

	#log "dbUpdateUsers:" ("query='" + $q + "'")

	$result = dbExecuteNonQuery $q
	if ($result -lt 0)
	{
		throw ("Failed updating Users record. result = $result")
	}

	return $result
}

dbOpen
$result = dbExecute ("Select * from " + (dbQuote "Users") + " WHERE " + (dbQuote "ID") + "=2")
dbTransferUsersToGlobal($result) $global:SampleUsersName = "John A. Doe" dbUpdateUsers 2 dbDisplayAllUsers dbClose

I hope you've enjoyed this introduction to using PowerShell for cross-platform data access. If there are any other topics that you would like me to cover, please leave me a message on the blog, or shoot me an e-mail directly at: michael at TheEssentialExchange dot com. Thanks for reading!

Posted by michael | 2 comment(s)
Filed under: ,

In yesterday's post http://theessentialexchange.com/blogs/michael/archive/2008/01/22/DML-with-PS-_2D00_-Part-1.aspx, I promised that we would talk more about DML with PowerShell.

In writing resilient code, the database layer has to be prepared to deal with NULL, invalid variables, missing variables, etc. PowerShell's NULL experience is pretty decent, but like any language, it has it's quirks and has to be specfically handled for the difference between variable types.

Thankfully, the "normal" sets of variables that you use in a database are pretty small. For my use, I got by with BOOLEAN, INTEGER, VARCHAR, and DATE.

In every case, before I create a DML statement, I evaluate the variables to be used in the DML statement. First, I determine if the value of the variable is null. If not, I cast the variable to the variable type I need. Then, I convert that variable to the format required for the particular database engine.

The dbInt routine is a good example:

#
# dbInt
#
# This routine ensures that a integer/number variable is properly returned. If
# the value is zero or NULL then a zero is returned.
# 
# Note that some database engines do not support a NULLable integer.
#
function dbInt($i)
{
	if ($i)
	{
		$ii = $i -as [int]
		$result = $ii.ToString()
	}
	else
	{
		$result = "0"
	}

	log "dbInt:" ("result=" + $result)

	return $result
}

I start by checking to see whether the variable has a value. In this case, $i might not return true for two reasons. It could either have a value of zero, or it could be NULL. Some database engines do not support having a simple type as NULL. In that case dbInt simply returns a value of zero. Note that the return value is a string.

If the parameter has a value, the parameter is cast to an integer using the PowerShell -as operator and then the ToString() method is executed against the resultant value and the string value is returned.

Finally, the result of the routine is written to a log file, and the result is returned to the caller.

The rest of the routines are below. Note that the dbDate routine is required to treat each database engine differently, as each requires different formating to store a date in the database! Also note that the dbText routine handles quoting properly in order to guard against certain SQL injection attacks.

In the next (final) post in this short series, I'll show how to use these routines in creating "safe DML".

#
# dbDate
#
# This routine ensures that a date variable is formatted properly
# for the database platform being utilized, and if the variable is
# null, that a NULL is returned.
#
function dbDate($d)
{
	if ($d)
	{
		$date = $d -as [DateTime]
		switch ($dbChoice)
		{
			$dbAccess
			{
				$result = "#" + $date.ToString() + "#"
			}
			$dbMSSQL
			{
				$result = "'" + $date.ToString() + "'"
			}
			$dbMySQL
			{
				## MySQL demands a certain date-format
				$result = "'" + $date.ToString("yyyy-MM-dd HH:mm:ss") + "'"
			}
			Default
			{
				throw ("Bad dbChoice value $dbChoice in dbDate")
			}
		}
	}
	else
	{
		$result = "NULL"
	}

	log "dbDate:" ("dbChoice=" + $dbChoice + ", result='" + $result + "'")

	return $result
}

#
# dbText
# 
# This routine ensures that a text/string/varchar variable is properly quoted
# or a NULL is returned for an empty string.
#
# Note that some database platforms do not support a zero length string.
#
function dbText($s)
{
	if ($s)
	{
		$str = $s -as [string]
		if ($str.Length -gt 0)
		{
			$result = "'" + $str.Replace("'", "''") + "'"
		}
		else
		{
			$result = "NULL"
		}
	else
	{
		$result = "NULL"
	}

	log "dbText:" ("result=" + $result)

	return $result
}

#
# dbBool
#
# This routine ensures that a boolean/yes-no variable is properly returned. If
# the value is $false or NULL then False is returned - otherwise True.
#
function dbBool($b)
{
	if ($b)
	{
		$bb = $b -as [bool]
		if ($bb)
		{
			$result = "True"
		}
		else
		{
			$result = "False"
		}
	}
	else
	{
		$result = "False"
	}

	log "dbBool:" ("result=" + $result)

	return $result
}
Posted by michael | 1 comment(s)
Filed under: ,

In this article I discussed how to used ODBC to access three different database platforms: Microsoft Access, Microsoft SQL Server, and MySQL. In that article, I noted that there were some interesting challenges that come into play when generating SQL statements.

Today I want to talk about the next layer up - the construction of the intermediate data access layer. In case it isn't clear, I am developing what I consider to be an "industrial strength" application that handles errors and recovery as much as possible.

Each database platform has a separate set of reserved words. This can significantly complicate the construction of statements that select, update, create, and/or delete data. These statements are collectively known as DML - Data Manipulation Language. It is possible to investigate every single command, table names, and column names - and try to keep it current for all versions of each piece of software - but you might (I did) find it easier to escape all of the potential reserved words. That means - escape all the table names and column names.

You can review the reserved words for several versions of the databases at these websites:

In Microsoft Access and Microsoft SQL, square brackets will work. In MySQL, grave accents (that is, left single quotes) are required. A sample escaped select statement for Microsoft Access and SQL Server might look like this (you should join this all on one line):

SELECT * FROM [Subscriber] WHERE ([EMailAddress]='michael@theessentialexchange.com' AND [MailingListID]=2)
For MySQL, the statement would look like this:
SELECT * FROM `Subscriber` WHERE (`EMailAddress`='michael@theessentialexchange.com' AND `MailingListID`=2)
Personally, I find the Microsoft Access/SQL Server statement easier to read. The difference between single quotes and grave accents are small and difficult for my eyes to recognize. In my data access layer, I've chosen to hide the quoting in a function I named dbQuote. It is quite direct. Continuing to use the $dbChoice variable defined in the first post, we can decide which quoting elements to use for our database platform. The routine comes out like this:
#
# dbQuote
#
# This routine ensures that a table or column name is properly
# quoted for the database platform being utilized. Unlike the
# column values, $word may not be NULL.
#
function dbQuote([string]$word)
{
	if (!$word)
	{
		throw ("dbQuote: table/column name may not be null.")
	}
	# square brackets work for MS-SQL and MS-Access
	$start = '['
	$end   = ']'

	if ($dbChoice -eq $dbMySQL)
	{
		$start = $end = '`'
	}

	$result = $start + $word + $end

	log "dbQuote:" ("result='" + $result + "'")

	return $result
}

The log function has not yet been presented. However, it simply writes a record to a log file on disk that looks like this:
2008-01-21 23:33:11Z dbQuote: result='[Subscriber]'
The dbQuote function is used in the construction of all DML statements. For example:
$q = "SELECT "
$q += (dbQuote "EMailAddress" ) + ","
$q += (dbQuote "MailingListID") + " "
$q += "FROM "
$q += (dbQuote "Subscriber")

which creates a select statement like this:
SELECT [EMailAddress], [MailingListID] FROM [Subscriber]
for Microsoft Access and Microsoft SQL Server. For MySQL we get this:

SELECT `EMailAddress`, `MailingListID` FROM `Subscriber`
Of course, you don't have to use as many source-lines in PowerShell to create the DML as I did. You can put it all in one. However, you may find when you come back to edit that select statement that if it's all in one line it's harder to find and edit!

However, dealing with table names and column names in DML is only half the story. Dealing with arbitrarily valued row items which may be NULL or contain escaped characters or managled dates are the other part of the story.

We'll deal with those in the next post in this series.

Posted by michael | 1 comment(s)
Filed under: ,

Almost everything you can buy in the server market these days is 64-bit capable - whether AMD or Intel. Almost.

Much of what you buy in the desktop market is 64-bit capable - whether AMD or Intel. Much.

Why do you care? Exchange Server 2007 is only supported in production on 64-bit servers running 64-bit versions of Windows Server 2003 (and soon Windows Server 2008). However, 32-bit versions of Windows Server 2003 can also be installed on 64-bit hardware. And that doesn't count! You need a 64-bit OS to make Exchange Server 2007 happy!

So, if there is any question in your mind about whether your hardware can support a 64-bit operating system, this is how you find out!

In PowerShell, it's easy. Here is a sample:

PS C:\>gwmi win32_processor | fl AddressWidth,DataWidth,Architecture,Manufacturer,MaxClockSpeed

AddressWidth  : 32
DataWidth     : 64
Architecture  : 9
Manufacturer  : AuthenticAMD
MaxClockSpeed : 1900

PS C:\>

The most important value here is the Architecture property. A value of 9 is "x64". A value of 0 is "x86" and a value of 6 is "Itanium". There are other historical values (Alpha, MIPS, etc.) but current versions of Windows don't run on those processors. This sample is an x64 processor.

This sample is from my laptop. To decode it a little bit, we see an AddressWidth of 32. This defines the width of a pointer variable for the currently loaded operating system. This tells you that I'm running a 32-bit OS (Windows Vista, in this case).

The DataWidth value of 64 tells you how wide the bus is that moves data into the processor. It also is the maximum possible value for AddressWidth. If a 64-bit OS is loaded, AddressWidth and DataWidth are both 64.

My laptop processor is from AMD, and is a dual-core processor. Each processor has a maximum clock speed of 1.9 Ghz.

Intel processors have "GenuineIntel" for the manufacturer field.

To summarize: you need an Architecture value of 9 and a 64-bit version of Windows Server 2003 installed to be able to install Exchange Server 2007 (for production use!).

Posted by michael | with no comments

In this post, I discussed the various ways that Exchange Server accesses Active Directory.

In large environments, Exchange Server has the capability of stressing the domain controllers (especially global catalog servers) that it uses, based on the number of queries that Exchange Server (and Outlook) make to the global catalog. In this case, "large" is defined as any environment that makes extensive use of features that may require access to the Active Directory. A typical recommendation is that (when using x86 domain controllers) you dedicate one global catalog server for every four Exchange Servers. If you are using 64-bit domain controllers, that ratio can be changed to 1-in-8.

In order to optimize access to Active Directory, Exchange Server maintains a set of caches. These caches are used to store the results of queries from Active Directory, for a period of time. However, these caches can get in the way of an administrator getting their job done. It is rare the administrator that has made a security change to a user object and wonders why it doesn't seem to work...or has increased the quota for a mailbox and wonders why it doesn't take effect.

The reason? Cache lifetimes.

DSAccess (discussed in the post linked above) maintains a cache of user objects. The Exchange Information Store maintains a cache of mailbox information. The DSAccess cache, by default, times out in five minutes. The information store mailbox cache, by default, times out in two hours. The concept behind this tiering is that mailbox information, being a small subset of the information that a user object contains, is not likely to change very often in comparison to the entire user object.

In a dynamic Exchange environment, that assumption is probably wrong for some small set of user and mailbox objects. If you make a change to Exchange attributes on a user or group or contact, you certainly do not expect to wait up to two hours for that change to take effect.

The Exchange Information Store also maintains yet another cache of mailbox quotas and limits. This cache is fed from the mailbox information cache. By default, this cache is also updated only each two hours. This means that, if you change a logon quota, it will normally take about two hours for that change to be reflected for the user. In the very worst case, it could take up to four hours and five minutes.

Your alternative is to restart the information store (the MSExchangeIS service). If you aren't aware of this limit, you will likely eventually get to that step (or the step of rebooting the server) as you sit around wondering what you have forgotten to change after updating the user quotas and seeing that they are not taking effect.

Neither of these alternatives is really acceptable. Therefore, in Exchange 2000 Server Service Pack 3 and Exchange Server 2003 RTM and in Exchange Server 2007 RTM, Microsoft provided registry keys that can affect the lifetime of each individual cache, as well as some basic guidelines about acceptable values for the cache lifetimes. The recommended values show tiering as well. They are:

  • DSAccess user object cache - 5 minutes
  • Mailbox information cache - no recommendation
  • Mailbox quota and limit cache - 20 minutes

Microsoft documentation warns that if you set the lifetimes to "very low values" that this can have performance implications for your Exchange server(s).

To test the above statement, I set the DSAccess user object cache lifetime to 5 seconds on a test dual-processor Exchange server with 4 GB of RAM and about 1,000 user objects. The information store pegged one processor at 100% utilization. So... they are right. Don't do that.

To find ideal values for your environment may require experimentation. However, I have had good success with these values:

You can use registry editor to set these values. See Microsoft KB 327378 (Exchange 2000 and Exchange 2003 mailbox size limits are not enforced in a reasonable period of time; fix requires Exchange 2000 SP3) for information about how to do that. For Exchange Server 2007, refer to this technet article. However, you may find it easier and less error prone to use the registry files I provide here. For DSAccess, place the following lines into a file named DSAccess-cache.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MSExchangeDSAccess\Instance0]
"CacheTTLUser"=dword:000000b4


Please note that the blank lines (lines 2 and 5) are significant and should not be deleted. The CacheTTLUser value is set to 180 seconds (which is three minutes or 0x0b4 in hexadecimal) in this example. To set the value to 300 seconds (which is five minutes) change the final 0b4 to 12c.

Finally, assuming that you place the file into a folder named c:\temp, execute the following command:

regedit /s c:\temp\DSAccess-cache.reg

and this will load the value into the registry of your Exchange Server.

The other two caches both exist within the Exchange Information Store and therefore the values to edit exist within a single registry key. Place the following lines into a file named ExchangeIS-cache.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MSExchangeIS\ParametersSystem]
"Reread Logon Quotas Interval"=dword:00000384
"Mailbox Cache Age Limit"=dword:0000000a


Lines 2 and 6 are significant and should be left blank and not deleted. The Reread Logon Quotas Interval value is set to 0x384 seconds (which is 900 seconds in decimal, which is equal to 15 minutes). The Mailbox Cache Age Limit value is set to 0xa minutes (which is 10 minutes in decimal).

Finally, assuming that you place the file into a folder named c:\temp, execute the following command:

regedit /s c:\temp\ExchangeIS-cache.reg

and this will load the values into the registry of your Exchange server.

Once you have made these changes, you will need to restart the Exchange Information Store service (MSExchangeIS) and the Exchange system attendant service (MSExchangeSA). Unless your server is used for other things than Exchange, you may as well reboot.

Making these recommended changes will greatly improve your administrative experience, if they are suitable in your environment.

Posted by michael | 1 comment(s)

In other words - name and attribute resolution.

Exchange Server stores almost all of its non-store-related information in Active Directory. This includes configuration for each individual Exchange server, each Virtual Server for each Exchange server, etc. Exchange places all of this information beginning at the following Active Directory location (this for example): CN=First Organization, CN=Microsoft Exchange, CN=Services, CN=Configuration, DC=TheEssentialExchange, DC=com.  For your Exchange organization the first node (CN=First Organization) may be different and the last nodes (DC=TheEssentialExchange,DC=com) will definitely be different.

The Exchange information will be located in the root domain of any forest where Exchange Server is installed. The information is part of the Configuration naming context and thus will reside on every domain controller.

If you use any LDAP (Lightweight Directory Access Protocol) query tool (ADSI Edit and LDP are both included as part of the Windows Server Support Tools, and Softerra's LDAP Browser is another really good tool), you will see that the structure of the information for the Exchange organization matches closely to that of the information as presented in Exchange System Manager (in Exchange 2003; less so in Exchange 2007).

The other types of information that Exchange uses is stored within Exchange-aware objects. Users, groups, contacts, InetOrgPerson objects, etc. - each of these has attributes that Exchange is extremely interested in, plus there are many other standard attributes that Exchange will use as well (for example, a user's display name and the user's password).

Global Catalog Servers

The global catalog (GC) is an excerpt from the full Active Directory database that contains a partial copy of every single object in all domains that exist in an Active Directory forest. Included in that partial copy are a few pieces of information about each one of those objects that allow applications, such as Exchange, to make fast queries on objects, without being weighed down by the full content normally contained within the database where the objects are stored.

Since Exchange is a per-forest application, Exchange information needs to be available not only for the forest root domain, but also for every child domain that may exist. As part of the Exchange forestprep process, Exchange specific attributes were added to various objects, but quite a few attributes were also modified to add those attributes into what is called "the partial attribute set". In layman's terms, this means that those attributes are available for search and retrieval in the global catalog.

A GC server is a domain controller (DC) that has been configured to host the global catalog. Indicating that a DC should be a GC is a simple checkbox on the NTDS settings object for the server (this setting is normally configured by using the Active Directory Sites and Services tool).

GC information is made available on TCP port 3268. DC information is made available on TCP port 389. Information requested from, and updated to, GCs and DCs is done using LDAP. Exchange makes heavy use of GC servers.

DSAccess 

Exchange Server uses DCs (and thus, Active Directory in general) in three distinct ways. The process known as DSAccess prepares a list of DCs and GCs that Exchange will use (this list can be manually configured in the registry, but this is not recommended - for more information on this topic, see Microsoft KB 250570 - Directory service server detection and DSAccess usage). Most requests made by Exchange services are cached by DSAccess for a period of time in order to improve performance and end-user experience. How to modify that cache timeframe will be shown in the next blog post.

All Exchange services that need access to Active Directory do so (directly or indirectly) via DSAccess. They may contact Active Directory independently, but they will receive the list of DCs and GCs to use from DSAccess. Other services will use DSAccess directly.

Global Catalog

Almost all user-initiated requests made by Exchange or by an email program communicating with Exchange, such as Outlook, target global catalog servers to obtain their information. This is typically user names, email addresses, aliases, home Exchange servers, etc. Some information is first retrieved via a GC and then by contacting an appropriate DC to gather data not held in the global catalog.

Domain Controller

If the service requesting information via DSAccess has enough information to direct an information request to a specific domain, some requests may be shortcut and not be directed first through a GC server. In certain situations (such as the expansion of group membership in domain local groups), this can represent a performance improvement.

Configuration Controller

While all DCs have a copy of the configuration naming context, because of replication latency all copies of the configuration naming context may not be precisely the same within a certain period of time. Therefore, DSAccess refers all configuration naming context updates and queries to a single DC, to ensure that the data returned and updated is consistent. If Exchange needs to update Active Directory, it will always use that configuration DC.

DSAccess scans through all DCs and GCs known by Active Directory, and preferentially uses servers that are in the same Active Directory site and that respond quickly (that is, in less than two seconds). DSAccess repeats the discovery process every 15 minutes. More information on the DSAccess topology discovery process is available in the Exchange Server 2003 Technical Reference Guide, available at http://microsoft.com/downloads via this download link.

If Exchange Server is installed on a domain controller, all three types of Active Directory access mediated by DSAccess will go to a single DC - the DC that Exchange is installed upon. If Exchange Server is installed on a member server, the list of DCs chosen is somewhat random, dependent upon the number of DCs and GCs in a given site.

DSProxy and the Name Service Provider Interface (NSPI)

DSProxy is primarily used to support old versions of Outlook (versions that were out before Active Directory was released). Versions of Outlook that old presume that the Exchange Server is running all of the LDAP directory services as well, since for Exchange Server 5.5 and all prior releases of Exchange Server, that was true. DSProxy runs on the Exchange Server and forwards any directory service requests from client computers to NSPI on an appropriate GC server.

Newer versions of Outlook will usually connect to DSProxy only once - in order to receive a referral to a GC that Exchange uses. This happens during the creation of a user's profile. Once that information is received, Outlook stores the information in the user's profile and that GC is used for future requests. New versions of Outlook will also connect to DSProxy if they attempt to connect to a GC and it doesn't respond. In that case, Outlook will ask DSProxy for a new referral (to identify the current global catalog being used, refer to Microsoft KB 317209 - How to Identify your Global Catalog Server Using Outlook 2000 and Outlook 2002 - and note that this also applies to Outlook 2003).

NSPI always runs on a global catalog server and is a function of a GC, independent of Exchange Server. That is, NSPI exists on a GC even if Exchange is not installed in a domain or in a forest. NSPI is the client-focused mechanism for returning information to any MAPI request about names - both user names and address book names, as well as the contents thereof. It could reasonably be stated that NSPI is the MAPI mechanism for making LDAP queries to Active Directory. NSPI is used when configuring a user's profile and when making any address book query.

Prior to Windows 2000 Server Service Pack 3, after you made a DC a GC, you had to reboot the server in order for NSPI to begin operation. As of that service pack level, the reboot is no longer required.

Windows Internet Name Service (WINS)

WINS significantly predates Active Directory, and has its roots in MS-DOS and Windows for Workgroups. It is not a part of Active Directory. WINS operates completely separate and apart from Active Directory. However, for many current Microsoft products, such as Exchange Server 2003, WINS is still an important part of the operational and functional environment.

It is worth reminding you at this point of the number one difference between WINS and DNS - WINS supports a flat namespace and DNS supports a hierarchical namespace.

For example: in any given WINS environment, there can only be one computer named bill. In any given DNS environment, there can be many computers named bill. To wit: bill.domain1.com, bill.domain2.com, etc. ad infinitum.

WINS is based on NetBIOS, and continues several (many) of the limitations of NetBIOS, perhaps most importantly that computer names must be less than 16 characters and that all computer names must be unique within those characters.

For NetBIOS, this is true within a broadcast domain (basically, a LAN). However, WINS is a mechanism of interconnecting multiple NetBIOS broadcast domains together to have unified name resolution across all of those broadcast domains. Thus, all computer names must be unique in a WINS environment.

Exchange Server 2003 (and before) stores server names (and other things, but the server names are arguably the most important) in the configuration naming context (i.e., Active Directory) based on their short name (i.e., their WINS or NetBIOS name). This means that for Exchange 2003 to resolve (find the IP address for) those server names, it will use NetBIOS.

In some ways, using NetBIOS names was a good resolution to the particular problem of tracking down Exchange Servers, where there may be many versions of Exchange in the Exchange organization. In other ways, it has caused (and continues to cause) problems for many organizations.

What this means to you as an Exchange administrator is this: if you only have a LAN, you don't require WINS because NetBIOS broadcasts will likely handle all name resolution issues. In any larger environment using Exchange 2003 and/or clustering, Microsoft requires that WINS be installed and properly configured to deal with all name resolution issues.

Please refer to Microsoft KB 837391 (Exchange Server 2003 and Exchange 2000 Server require NetBIOS name resolution for full functionality) for more information on this issue. Also be aware that ESM (if there are multiple administrative groups) and the clustering functionality of Exchange also require WINS.

In regards to Exchange 2007, you only require WINS if you are running clustered servers on Windows Server 2003. According to pre-release documentation, WINS is not needed with Windows Server 2008 clustering.

In this post I talked about licensing vs. features for Exchange Server 2007.

In that article, I made the comment that Exchange licensing made my "head hurt". The licensing for other pieces of the "UC Wave" are just as convoluted.

Exchange Server is just one piece of the "UC Wave", where "UC" stands for Unified Communications. The other two pieces are SharePoint Server and Office Communications Server 2007.

SharePoint is about collaborative communication capabilities - bulletin boards, document sharing, shared task lists, shared calendars, and other features following that general trend.

SharePoint is available in two versions - Windows SharePoint Services 3.0 (WSS 3) and Microsoft Office SharePoint Server 2007 (MOSS 2007) which is far from free. MOSS 2007 is built on top of WSS 3.0. Many folks seem to get along just fine with WSS - including some huge companies - so we won't go into detail on SharePoint licensing costs and feature differences (if you are interested - drop me an e-mail or leave a message on the blog; if enough folks are interested, I'll author a post on that too).

The final piece of the current "UC Wave" is OCS 2007. OCS 2007 licensing is very similar to Exchange Server 2007 licensing - no real surprise there. This article is about OCS 2007. You'll note that this article is very similar to the Exchange Server article.

OCS 2007 requires a client for some features (such as presence, instant messaging, etc.) and that client is named Office Live Communicator 2007 (which we will just refer to as Communicator henceforth).

Some of the other OCS 2007 features (such as call control and software-based Voice over IP [VoIP]) do not require Communicator (but do require SOME user interface).

OCS 2007 has both a Standard Server and an Enterprise Server, similar to Exchange. Continuing with that similarity, OCS 2007 has a Standard CAL and an Enterprise CAL. At minimum, a Standard CAL is required for each user. The OCS Enterprise CAL is an additive CAL, like the Exchange Server Enterprise CAL.

The feature-content offered by the Communicator application is handled by the Standard CAL. Other OCS 2007 features require an Enterprise CAL.

Communicator licensing is not included in the CAL license or Server licenses for OCS 2007.

So, Microsoft gets you coming and going in licensing, in both OCS 2007 and in Exchange Server 2007. You must license the Server software, you must license access to the server for each user, and you must license the primary user interface to the server software.

Please note: prices are estimated retail prices in US dollars. Also please note: I am not a lawyer (IANAL). My comments are based on my understanding of publicly available information on various Microsoft web properties.

OCS 2007 Edition Cost
Office Communications Server 2007 Standard Edition MSRP US $699
Office Communications Server 2007 Enterprise Edition MSRP US $3,999


OCS 2007 Standard contains most of the features of OCS 2007 Enterprise, but is limited in terms of storage space, clustering, and highly-available option support. Thus Standard Edition is targeted at companies who can "afford downtime". Here is a table defining the primary differences:

Feature Standard Edition Enterprise Edition
Storage engine SQL Embedded/SQL Express SQL Standard/SQL Enterprise
Local storage Yes-required Not required
Clustering Not supported Supported
Highly-available Not supported Supported


Similar to the discussion of Standard vs. Enterprise for Exchange functionality; how much does downtime cost your company? If your instant messaging or telephone system are down for a reboot in the middle of the day, does that represent a minor inconvenience, or is that a critical business interruption?

If an occasional reboot isn't a problem, then with good hardware (and powerful enough hardware), Standard Edition is a reasonable choice. That choice is limited, as with Exchange Server, by your Service Level Agreement (SLA) with your clients.

Regardless of the OCS 2007 Edition, you will require Client Access Licenses and a Communicator license.

Theoretically, a Communicator license is not required if you only require Enterprise CAL functionality. However, without Communicator, you have effectively wasted the capabilities that are enabled by a Standard CAL. So realistically, a Communicator client is a requirement to obtain the full benefits of OCS 2007 (and Unified Communications).

Those costs (again, estimated MSRP) are shown below:

Description Cost
Office Communicator 2007 US $34
Standard CAL US $31
Enterprise CAL US $139


Thankfully (at least so far), there is only a single edition of Office Communicator 2007.

In a change from prior CAL offerings from Microsoft, but following the lead of Exchange Server 2007, the Enterprise CAL does not replace the Standard CAL. Instead, it is an additive CAL. You must have a Standard CAL for every Enterprise CAL. However, the reverse is not true. You can potentially choose to not offer some users Enterprise functionality.

It is interesting to note that you can use Standard CALs on Enterprise Edition and you can use Enterprise CALs on Standard Edition. They are only relevant to the feature content required by their presence.

Significant features provided by each CAL are;

Feature Standard CAL Enterprise CAL
Enterprise Instant Messaging Yes No
Presence Indication Yes No
User-to-user Voice and Audio Yes No
File transfer Yes No
Multi-user web conferencing No Yes
Application/desktop sharing No Yes
Software-base Voice over IP No Yes
Call-control and Management No Yes


Note that Unified Messaging is a feature of Exchange Enterprise CALs (and thus enabled by Exchange Server) but VoIP and Call Control are features of Office Communications Server 2007. To have a full "software PBX", excepting only the PSTN gateway, you require both Exchange and OCS 2007.

Note: The PSTN gateway is the piece of hardware that connects OCS 2007 and Exchange Server to the public telephone network.

Now that we have all that data, what can we conclude?

First, the cost of the server software for an installation of any significant size is low compared to the cost of the CALs and user software. For example, consider the possible costs for an office of 10 users.

Description Cost
OCS 2007 Standard Edition $699
OCS 2007 Enterprise Edition $3,999
10 Communicator Licenses $340
10 Standard CALs $310
10 Standard CALs plus 10 Communicator Licenses $650
10 Enterprise CALs $1,390
10 Standard plus 10 Enterprise CALs plus Communicator Licenses $2,040


The Standard CAL cost for ten users plus the cost of 10 Communicator licenses is approximately the same as the cost of the Standard Edition server software. Once you add in the cost of the Enterprise CALs, the client cost already far exceeds the cost of the server software. The additive cost for the Enterprise CALs is twice the cost of the Standard CAL and the Communicator license.

Even so, as you add users, the cost of the server software decreases quickly as a percentage of the total.

Next, similar to server software cost, the cost of server hardware decreases quickly as a percentage of the total, as the number of users grows. However, for small deployments, the cost of server hardware may significantly exceed the initial cost of the software. In the 10 user example above, the total cost of user licensing plus server licensing for Standard Server and Standard plus Enterprise CALs is approximately $2,700.

However, in early-2008 dollars, a reasonable server platform for running OCS 2007 (non-highly available) is around $5,000. This doesn't include any backup capability or highly available features; but does include plenty of memory and disk and redundant features (like dual power supplies and fans). For 10 users, that may be excessive. However, that same platform can likely support 50 users as easily as 10. The licensing cost for 50 users is $10,200. At that level, software cost far outstrips hardware cost.

Wow. As I re-read the above, prior to posting, it all sounds so dense and confusing. All I can hope is that it is less confusing that reading the Microsoft licensing pages.

Posted by michael | 6 comment(s)

My head hurts.

Microsoft licensing was messed up enough already. With the release of Exchange Server 2007, it got even more complicated.

Now, Outlook CALs aren't included in Exchange licensing. Ugh.

Oh, and then wait, to get Enterprise IM (which I had included as a part of Exchange 2000 Server), I now have to purchase Live Communication Server (LCS) 2005, or the brand-new Office Communication Server (OCS) 2007? How much is THAT gonna cost me?

Oh, and then wait - Office Live Communicator CALs aren't included in OCS licensing, either?

Oh, and wait again, I have HOW many different types of Client Access Licenses (CALs) for each Product??? And how many different Editions??? And it has to be installed on what architecture?

And Windows Server 2008 is due in less than two months? With ANOTHER gazillion different editions?

Argh.

Let's ignore Server 2008 for the minute and put these prices/features/content/choices together.

Please note: prices are estimated retail prices in US dollars. Also please note: I am not a lawyer (IANAL). My comments are based on my understanding of publicly available information on various Microsoft web properties.

The differentiation between CLIENT licenses and SERVER licenses is now crystal clear. This was not necessarily true in the past.

Exchange Edition Cost
Exchange Server 2007 Standard Edition MSRP US $699
Exchange Server 2007 Enterprise Edition MSRP US $3,999

This represents no change in Exchange Server pricing (at least MSRP) since Exchange 2000 Server. However, as always, Exchange Standard contains most of the basic features of Exchange Enterprise, but is limited in terms of storage space, clustering, and features which (for some undefinable reason) Microsoft considers advanced. Here is a table defining many of the differences:

Feature Standard Enterprise
Maximum storage groups 5 50
Maximum databases 5 50
Maximum database size 16 TB 16 TB
Local Continuous Replication (LCR) Supported Supported
Standby Continuous Replication (SCR) Supported Supported
Clustering Not supported Supported
Single Copy Cluster (SCC) Not supported Supported
Cluster Continuous Replication (CCR) Not supported Supported

It is noteworthy that Standard Edition no longer has any "real" database size limits. In Exchange Server 2003 sp2, Standard Edition supported a single mailbox database, up to 75 GB in size. Prior to that, Standard Edition was limited to a single mailbox database of 16 GB in size.

As always, the true maximum size of a mailbox database is limited by your Service Level Agreement (SLA) with your clients - how long can they afford to be down in the case of a mailbox database restoration requirement? And how long does it take you to back that data up? It's a fine line, and a topic for another blog post one day.

It arguable as to whether Enterprise Edition is any longer a need in most environments. (Clustering is almost a religious issue. It's complicated enough that in many sites using clustering, they actually have higher downtime than sites that don't use it. But those folks who use it, and use it well, can take a 99.9% uptime solution [Standard Edition on good hardware] to a 99.99% solution. It's not cheap though. With well-implemented SCR, it is possible to attain that level of uptime with Standard Edition.)

Regardless of Edition, you will require Client Access Licenses and an Outlook license.

Theoretically, an Outlook license is not required. This is because much of the functionality of Outlook is available via Outlook Web Access and because access to the various Internet protocols (IMAP, POP-3, and SMTP) are included in the Exchange Standard CAL. However, realistically, an Outlook client is a requirement to obtain the full benefits of Exchange (and Unified Messaging).

Those costs (again, estimated MSRP) are shown below:

Description Cost
Outlook 2007 US $109
Standard CAL US $67
Enterprise CAL US $36

Thankfully (at least so far), there is only a single edition of Outlook.

In a change from prior CAL offerings from Microsoft, the Enterprise CAL does not replace the Standard CAL. Instead, it is an additive CAL. You must have a Standard CAL for every Enterprise CAL. However, the reverse is not true. You can potentially choose to not offer some users Enterprise functionality.

It is extremely interesting to note that you can use Standard CALs on Enterprise Edition and you can use Enterprise CALs on Standard Edition. They are only relevant to the feature content required by their presence.

Significant features provided by each CAL are;

Feature Standard Enterprise
E-mail, tasks, calendars, contacts Yes No
Outlook Web Access Yes No
Internet protocols (IMAP, POP-3) Yes No
All database journaling Yes No
Exchange ActiveSync Yes No
ActiveSync Policies No Yes
Unified Messaging No Yes
Per-User/Per-DL Journaling No Yes
Messaging Records Management No Yes
Exchange Hosted Filtering No Yes
Forefront Security for Exchange No Yes

Note that Unified Messaging is a feature of Exchange Enterprise CALs (and thus enabled by Exchange Server) but VoIP and Call Control are a feature of Office Communications Server (more on that later).

Now, we have all that data, what can we conclude?

First: the cost of the server software for an installation of any significant size is low compared to the cost of the CALs and user software. For example, consider the possible costs for an office of 10 users.

Description Cost
Exchange Server Standard Edition $699
Exchange Server Enterprise Edition $3,999
10 Office Outlook Licenses $1,090
10 Standard CALs $670
10 Standard CALs plus 10 Outlook Licenses $1,760
10 Enterprise CALs $360
10 Standard plus 10 Enterprise CALs plus Outlook Licenses $2,120

The Standard CAL cost for ten users is approximately the same as the cost of the Standard Edition server software. Once you add in the cost of the Outlook licenses, the client cost already far exceeds the cost of the server software. The additive cost for the Enterprise CALs is relatively small (20%) for the feature content enabled.

As you add users, the cost of the server software decreases quickly as a percentage of the total.

Next, similar to server software cost, the cost of server hardware decreases quickly as a percentage of the total, as the number of users grows. However, for small deployments, the cost of server hardware may significantly exceed the initial cost of the software. In the 10 user example above, the total cost of user licensing plus server licensing for Standard Server and Standard plus Enterprise CALs is approximately $2,800.

However, in early-2008 dollars, a reasonable server platform for running Exchange Server 2007 (non-highly available) is around $5,000. This doesn't include any backup capability or highly available features; but does include plenty of memory and disk and redundant features (like dual power supplies and fans). For 10 users, that may be excessive. However, that same platform can likely support 50 users as easily as 10. The licensing cost for 50 users is $10,600. At that level, software cost far outstrips hardware cost.

As a corollary, these types of cost comparisons are what make Exchange hosting more and more attractive to the low end of the market.

Next, as Exchange matures it is adding more and more feature content. While not necessarily obvious, but nonetheless true, using that advanced feature content requires more highly trained individual.

Now, that's all for Exchange. In the next blog post, I'll cover OCS licensing costs, and finally I'll try to pull it all together.

Posted by michael | 6 comment(s)

I've recently had need to be able to access data contained in three different database platforms: Microsoft Access, Microsoft SQL Server, and Mysql AB's MySQL. Originally, I thought this was going to be a tough thing to do, but it turned out to be pretty easy. ODBC drivers are available for all three (the Access driver is installed when you install office; for SQL server, it's part of "client components; for MySQL, it is a separate download and install).

Once you have the proper ODBC driver installed, it's a matter of building the connection string for each driver. That's the most challenging piece.

What makes this easy is the ODBC support that is built into the .NET framework. Given a compliant driver and the .NET framework, all the code can be the same (other than the connection string). Note that it would certainly be possible to contruct code that works in the "native" language for each database platform. The ADODB client for Access can be accessed in PowerShell, the .NET SqlClient is available in PowerShell, and Mysql AB also makes a .NET MySqlClient available.

Using the native interfaces may be faster, I don't know. I didn't conduct speed tests and my data volume is pretty low.

There are some "gotchas" that come into play when building INSERT statements, the two biggest being reserved words and date handling. I'll write a separate article about that in the future. Access and MS-SQL are quite similar when it comes to reserved words (no surprise) but MySQL is quite different. All three engines handle dates differently!

Here is my configuration file. I call it dbConstants.ps1. In this example, it's currently configured to talk to a MySQL database server on the local host. Examples for MS-SQL and MS-Access are included.

#
# dbConstants.ps1
#

Set-Variable dbAccess  -option ReadOnly -value 1
Set-Variable dbMSSQL  -option ReadOnly -value 2
Set-Variable dbMySQL  -option ReadOnly -value 3

#
# Microsoft Office Access Example
#
#Set-Variable dbChoice -option ReadOnly -value $dbAccess
#Set-Variable dbName   -option ReadOnly -value Test.mdb
#Set-Variable dbSource -option ReadOnly -value Not-Applicable
#Set-Variable dbUser   -option ReadOnly -value Not-Applicable
#Set-Variable dbPass   -option ReadOnly -value Not-Applicable

#
# Microsoft SQL Server Example
#
#Set-Variable dbChoice -option ReadOnly -value $dbMSSQL
#Set-Variable dbName   -option ReadOnly -value Test
#Set-Variable dbSource -option ReadOnly -value .\SQLExpress
#Set-Variable dbUser   -option ReadOnly -value Not-Applicable
#Set-Variable dbPass   -option ReadOnly -value Not-Applicable

#
# MySQL Example
#
Set-Variable dbChoice -option ReadOnly -value $dbMySQL
Set-Variable dbName   -option ReadOnly -value Test
Set-Variable dbSource -option ReadOnly -value localhost
Set-Variable dbUser   -option ReadOnly -value root
Set-Variable dbPass   -option ReadOnly -value password

# for Access, dbName is assumed to be located in $pwd
# for MySQL, dbSource should be the IP address or FQDN of the computer running MySQL server
# for MSSQL, dbSource should be the name plus the instance of MS-SQL (e.g., SERVER\Instance2)
#            if not present or "Not-Applicable", then "(local)\Default" is presumed
# for MSSQL, if dbUser is something other than "Not-Applicable" then Windows Auth is used

and now for the code itself. It's pretty simple. :-)

#
# dbODBC.ps1
#

. $pwd/dbConstants.ps1

$global:MLMconnection = $null
$global:MLMcommand    = $null
$global:MLMresult     = $null

function dbOpen
{
 $global:MLMconnection = New-Object System.Data.Odbc.OdbcConnection

 $global:MLMcommand = New-Object System.Data.Odbc.OdbcCommand
 $global:MLMcommand.Connection = $global:MLMconnection

 switch ($dbChoice)
 {
  $dbAccess
  {
   $cStr = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=$pwd/$dbName;"
  }
  $dbMSSQL
  {
   $cStr = "Driver={SQL Server};Server=$dbSource;Database=$dbName;"
   if ($dbUser -eq "Not-Applicable")
   {
    $cStr += "Integrated Security=SSPI;"
   }
   else
   {
    $cStr += "UID=$dbUser;PWD=$dbPass;"
   }
  }
  $dbMySQL
  {
   $cStr = "Driver={MySQL ODBC 3.51 Driver};SERVER=$dbSource;DATABASE=$dbName;"
   if ($dbUser -ne "Not-Applicable")
   {
    $cStr += "UID=$dbUser;PWD=$dbPass;"
   }

  }
  Default
  {
   throw ("Unknown value of dbChoice $dbChoice can't open db $dbName")
  }
 }

 $global:MLMconnection.ConnectionString = $cStr
 $global:MLMconnection.Open()
 if ($global:MLMconnection.State -ne [System.Data.ConnectionState]::Open)
 {
  throw ("Cannot open $dbName")
 }
}

function dbPrepareResult
{
 if ($global:MLMresult)
 {
  if ($global:MLMresult.Gettype().Name -ne "Int32")
  {
   $global:MLMresult.Close()
  }
  $global:MLMresult = $null
 }
}

function dbClose
{
 dbPrepareResult
 if ($global:MLMcommand)
 {
  $global:MLMcommand.Cancel()
  $global:MLMcommand = $null
 }

 if ($global:MLMconnection)
 {
  if ($global:MLMconnection.State -ne [System.Data.ConnectionState]::Closed)
  {
   $global:MLMconnection.Close()
  }
  $global:MLMconnection = $null
 }
}

function dbExecute([string]$command)
{
 dbPrepareResult
 if (!$global:MLMcommand)
 {
  dbOpen
 }

 $global:MLMcommand.CommandType = [System.Data.CommandType]::Text
 $global:MLMcommand.CommandText = $command

 $global:MLMresult = $global:MLMcommand.ExecuteReader()

 return $global:MLMresult
}

function dbExecuteNonQuery([string]$command)
{
 dbPrepareResult
 if (!$global:MLMcommand)
 {
  dbOpen
 }

 $global:MLMcommand.CommandType = [System.Data.CommandType]::Text
 $global:MLMcommand.CommandText = $command

 $global:MLMresult = $global:MLMcommand.ExecuteNonQuery()

 return $global:MLMresult
}

Enjoy!

If there are things that you would like for me to write about, please let me know.

Posted by michael | 2 comment(s)
Filed under: ,

As you are probably aware, Exchange 2007 can happily co-exist with Exchange 2000 and Exchange 2003, and you can take a fairly extended time to execute your migration.

However, you can't directly upgrade from Exchange 5.5 to Exchange 2007. You have to go through Exchange 2003 first.

There is a slight "Catch 22" issue...assuming you didn't read the installation documents. What if you went ahead and installed Exchange 2007?

Once you've done that, the Exchange 2007 setup doesn't see any of the Exchange 2000 and Exchange 2003 schema changes to Active Directory and assumes a "greenfields" installation. Therefore, it goes ahead and creates the schema the way it wants it, and doesn't create the items in Active Directory that are necessary for the Active Directory Connector to work to connect to Exchange 5.5.

Now, you can't install Exchange 2000 or Exchange 2003. Their setup sees that the schema has been extended to a version beyond their's, and the organization object is present, but the organization doesn't contain some of the child objects they require - so the setup aborts.

What do you do?

First of all, you smack yourself upside the head for not reading the installation prerequisites and documentation.

Secondly, you completely remove the Exchange 2007 server installation by following this Technet article.

Thirdly, you remove the Exchange 2007 organization by following this Technet article.

Now, you can install Exchange 2000 or Exchange 2003.

But please read the documentation first! Big Smile

Posted by michael | 1 comment(s)
Filed under:

In this article, I reported that specific issues in the scalable networking pack (SNP) were corrected by an update to the Broadcomm drivers.

However, it has just recently come to my attention that another severe issue exists with the SNP - during shutdown a machine can hang and require a physical power-cycle to restore operation (a nightmare if you remotely maintain your servers!).

This is documented in KB 940202 and is not corrected by the patch contained in KB 936594.

Again, this is caused by the TCP Chimney Offload feature. Disable it by "Netsh int ip set chimney DISABLED" from a command prompt, as documented in the KB article. This command takes effect immediately and does not require a reboot of the computer.

KB 940202 does not document this as being specifically a Broadcomm driver problem, thus I would suggest you assume at this point it is an overall Windows 2003 sp2 problem and disable the feature.

Posted by michael | 5 comment(s)
Filed under:
More Posts Next page »