Detecting if the install is occuring on a 64 bit or 32 bit machine

Ok, so NSIS has most the 64 bit functionality available for their installers.

I need to write a registry key to the 64 bit registry on 64 bit machines.

I may need to install to Program Files or Program Files (x86).

If on 64 bit workstation you need to install to Program Files (x86) that is done by default because the $PROGRAMFILES constant goes to the Program Files (x86) directory.

So a simple solution that should be obvious is to check for something that is on a 64 bit machine that is not on a 32 bit machine.  Lets make a list of such differences.

Files

  1. c:\Program Files (x86) – Since this is just a folder, it could exist on a 32 bit machine, though that would be unlikely.
  2. c:\windows\SysWow64

Registry key

  1. HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node – This is a 64 bit registry and does not exist in 32 bit operating systems.

So some of these are susceptible to be “faked”.  I could see some idiot writing an installer on Windows 7 and hard coding the Program Files (x86) directory so it is installed there even on 32 bit systems.  The SysWow64 directory seems more safe and it exists on Vista, Windows 7, and 2008.  I don’t have XP or 2003 64 bit machines so someone can check for me. It seems that the registry key is also likely to be a safe check.

You can check any of these you want. 

Here is how you would change which registry to work with.

	IfFileExists $WINDIR\SYSWOW64\*.* Is64bit Is32bit
	Is32bit:
		SetRegView 32
		GOTO End32Bitvs64BitCheck

	Is64bit:
		SetRegView 64

	End32Bitvs64BitCheck:

That fixes the registry keys. So if you only care about the registry you are fine. However, you software will still install to the Program Files (x86) directory. To fix both, you could place the following code in BOTH the .onInit and the un.onInit functions.

	; Install to the correct directory on 32 bit or 64 bit machines
	IfFileExists $WINDIR\SYSWOW64\*.* Is64bit Is32bit
	Is32bit:
		MessageBox MB_OK "32 bit"
		SetRegView 32
		StrCpy $INSTDIR "$PROGRAMFILES32\LANDesk\Health Check"
		GOTO End32Bitvs64BitCheck

	Is64bit:
		MessageBox MB_OK "64 bit"
		SetRegView 64
		StrCpy $INSTDIR "$PROGRAMFILES64\LANDesk\Health Check"

	End32Bitvs64BitCheck:

Don’t forget to comment out the usual place that INSTDIR is configured.

Anyway, that seems to work.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.


Google voice: Is it a good way to send a text message from a computer?

I just sent a text using Google voice to tell someone not to pick me up at 6:45 am.  Usually online texting tools never work for me.  Somehow,  I think Google Voice is different.

Anyway, if my friend/co-worker knocks at my door at 6:45 am, then I will complain and update this post with a big negative.  If it works, it will get a big positive.

Yes, Google Voice worked!

I tried a half a dozen online message tool and this one was the only one that got the IM through.


Notepad++ and the XML Tools plugin

Ok, so I do a lot with Xml files.  Between working with my company’s product LDMS and all the Xmls it uses, to my own code using Serialization, I seem to always have an Xml file open.

I hate it when I open and Xml File and it is all on one line.  Or every element is a separate line but not a single line is indented.

Visual Studio can fix these for me rather easily.  But I have a lot of different machines in my lab and often work in other’s labs, or on customer’s computers while remote controlling them for support reasons. I can’t just quickly download an install Visual Studio. While yes, there is a free Express Edition version, it is just an overkill for the simple job of making an Xml file look pretty in text.  I need a small simple, quick to download and install tool.

The solution was right in front of me the whole time: Notepad++ and the XML Tools plugin

I always use Notepad++ as my random text editor on windows.  I already use its Compare plugin constantly, so I am very familiar with it.  It finally donned on me to check if it had an plugin that could help me with Xmls and sure enough, it did.

The XML Tools plugin, has almost all the features I wanted.

Notepad++ is just over 3 megabytes and download rather quickly.  The XML Tools plugin is not installed by default but can quickly be installed using the Plugin Manager.  Don’t worry about the additional download, the XML Tools plugin is only just over 300 kilobytes.

So I can now prettify my Xml files with a small, quick to download and install, windows tool.

Here is the menu this plugin provides, so you can see a list of some of the features.

So the Pretty pring (XML only – with line breaks) will take an Xml that is all on one single line, and expand it to have line breaks and also give it the proper indents.

There is also a tool to make sure the Syntax is correct.

The only feature I want that it doesn’t have is a tool to sort child elements and attributes.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.


Options for serializing an Array or List when using Serializable?

Lets say you have to implement Xml Serialization on your objects. Many of your exiting Xml files have Lists. However, what if you are working with existing Xml files and you don’t get to reformat them? So you have to make the List in your object react the way it already looks in possible poorly designed Xml Files.

Ok, so off the top of my head, I can think of many ways that a List of objects could be displayed in XML (and there are probably more). For simplicity’s sake, I am going to use String objects for this, but this goes along with any object.

So how does Xml Serialization hold up when confronted with existing Xml files and existing lists?

Well, lets first show you some example Lists in Xml and then lets see what types are supported.

Type 1 – Grouped Lists

Status: Supported – This is the default way Xml Serialization stores lists in Xml files.
Xml Design: Excellent.

The object elements are contained in a parent element. As shown, each String element is inside the Strings (notice it is plural) element.

<RootElement>
  <Strings>
    <String>Some string 0.</String>
    <String>Some string 1.</String>
    <String>Some string 2.</String>
    <String>Some string 3.</String>
    <String>Some string 4.</String>
  </Strings>
</RootElement>

Type 2 – Grouped Lists numbered

Status: Unknown – I haven’t found a way to do this yet, but I am not ready to say it can’t be done.  If it can’t be done, I think it “should be” supported.
Xml Design: Average. I am not sure if you can serialize this. Someone designing an Xml without serialization in mind would not think this design is wrong.

Same as above only each element is numbered incrementally from 0. (Or it could start at 1, right?)

<RootElement>
  <Strings>
    <String0>Some string 0.</String0>
    <String1>Some string 1.</String1>
    <String2>Some string 2.</String2>
    <String3>Some string 3.</String3>
    <String4>Some string 4.</String4>
  </Strings>
</RootElement>

Type 3 – Flat List

Status: Supported – If you add [XmlElement] above the property, then this is the format you get.
Xml Design: Excellent. This is a standard supported format.

There is just a list, with no parent attribute containing the list items.

<RootElement>
    <String>Some string 0.</String>
    <String>Some string 1.</String>
    <String>Some string 2.</String>
    <String>Some string 3.</String>
    <String>Some string 4.</String>
</RootElement>

Type 4 – Flat List numbered

Status: Unknown – I haven’t found a way to do this yet, but I am not ready to say it can’t be done. If it can’t be done, I think it “should be” supported.
Xml Design: Average. I am not sure if you can serialize this. Someone designing an Xml without serialization in mind would not think this design is wrong.

Same as the Flat list above only each element is numbered incrementally from 0. (Or it could start at 1, right?)

<RootElement>
    <String0>Some string 0.</String0>
    <String1>Some string 1.</String1>
    <String2>Some string 2.</String2>
    <String3>Some string 3.</String3>
    <String4>Some string 4.</String4>
</RootElement>

Type 5 – Attribute Lists

Status: Broken but working – If you put [XmlAttribute] before and Array or List, beware. It seems it uses space as the delimiter. I can’t seem to find a way to change the delimiter.
Xml Design: Poor. You can serialize this, but it deserialize the same way as it serializes.

A single attribute that contains a list. Obviously the object can’t be complex to match this type.  String works, but a complex object has to be an element not an attribute.

I can already see that this method would be tough to use. Right away I am wondering seeing the problem of using white space as a delimiter. However, quotes are important too. Xml Serialization automatically replaces quotes with the following string:

"

I would have thought since it uses a space as a delimiter that it would have replaced white space with some similar character entity string, but it did not.

<RootElement Strings="Some string 0. Some string 1. Some string 2. Some string 3. Some string 4.">
</RootElement>

Type 6 – Attribute Lists numbered

Status: Unknown – This is what I expected when I used the [XmlAttribute] tag but instead I got Type 5.  I have seen this in Xml files, so supporting it would be nice.
Xml Design: Average.  If a List exists that is always expected to have only one to five elements, I see nothing wrong with this design.

A separate, numbered attribute for each element in the list.

<RootElement String0=Some string 0." String1="Some string 1." String2="Some string 2." String3="Some string 3." String4="Some string 4."
</RootElement>

Type 7 – Delimited text in an element

Status: No supported – This just is not how it is designed to work, nor should it every work this way.
Xml Design: Poor – This defeats the whole purpose of an Xml.

This assumes that the list is inside a single element and has some kind of delimiter. Below the delimiter is a new line character. (Let’s assume that we expect white space at the front and end of the string to be trimmed and blank lines to be ignored.)

<RootElement>
  <Strings>
    Some string 0.
    Some string 1.
    Some string 2.
    Some string 3.
    Some string 4.
  <Strings>
</RootElement>

Conclusion

Type 1 and Type 2 are the ideal methods and work perfectly for me.

Types 2, 4, 6 should be supported if they aren’t already.  Maybe there is a way to do these that I don’t know about.

Type 5 seems to work but doesn’t and it is really disappointing that the [XmlAttribute] tag works this way instead of like Type 6.

Type 7 is bad and you pretty much are left to fixing this with manual code and not using Xml Serialization.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.


How to create a custom class template for Xml Serializable classes?

Ok, so you don’t always want a default class template for every type of class.  I have to create a bunch of classes that implement Serializable and if the class template assumed this, that would be great.  However, I don’t want my default class template to assume this.

So here is what I did broken down into four simple steps.

  1. Open or create a c# project.
  2. Create a class file.
  3. Add the text and the variables to replaced.
  4. Export the item as a template.

Step 1 – Open or create a c# project.

Ok, so any project will do.  I used an existing project, but you can create a new one if you want.  Any C# project should allow this to happen.

Step 2 – Create a class file.

In one of my C# projects in Visual Studio, I created a new class called XmlClass.cs.

Step 3 – Add the text and the variables to replaced

I put the following text into my new class:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace $rootnamespace$
{
	[Serializable]
	public class $safeitemrootname$
	{
		#region Member Variables
		#endregion

		#region Constructors

		/*
		 * The default constructor
 		 */
		public $safeitemrootname$()
		{
		}

		#endregion

		#region Properties
		#endregion

		#region Functions
		#endregion

		#region Enums
		#endregion
	}
}

Step 4 – Export the item as a template

  1. In Visual Studio, chose File | Export Template.  This starts a wizard that is extremely easy to follow.Note: If you have unsaved files in your project, you will be prompted to save them.
  2. Chose Item template, select your project, and click Next.
  3. In the next screen there was a tree view of check boxes for all my objects.  I checked the box next to my XmlClass.cs.
  4. In the next screen, provide references.Note: I added only System and System.Xml.
  5. In the next screen, provide a Template name and a Template description.
  6. Click finish.

You should now have the option under My Templates when you add a new item to your project.

This class will be  useful and will save you and your team some typing when you are in the class creation phase of your project and you are creating all your Serializable classes.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.


Old Games…very old…1991…on 5.25" Floppies

Hey all,

Guess what gifts my brother brought me yesterday?  Yes, he cleaned out some old DOS games from his closet.  Some of the games I thoroughly loved:

  • Advanced Dungeons & Dragons’ Eye of the Beholder II – The Legend of Darkmoon
  • Nephi’s Quest – A mormon version of Kings Quest.

Unfortunately my Kings Quest set wasn’t found, though my brother has this if I want it, and Bard’s Tale II wasn’t found.

So I instantly thought of two problems I had to solve:

  1. How to read the 5.25″ floppies
  2. How to get a DOS system that isn’t so fast the games are unplayable.

Reading the 5.25 floppy drives

Yes, they are on 5.25″ floppies.  So after about 20 minutes of looking online for a USB 5.25″ floppy drive, I gave up.

So my options are:

  1. Get an old system with a floppy drive that still works.
  2. Send my floppies to a company that will migrate them to a CD at $5 a floppy.
  3. Find someone who has already moved the software from the floppies…

Yeah, one and two just weren’t for me, so the alternative was my only option.

Alternative to Reading the 5.25 floppy drives

Ok, so I almost gave up, when my decided that some one out that had a copy of the game downloadable right.  I mean, these games are 20 years old.  They are collectable. So somebody has to have them online.  Since I purchased a license in 1991, I thought I would not be breaking any laws downloading them.

Turns out I didn’t really have to worry about legalities and copyrights.

I found this site: http://www.abandonia.com/

Yes, Abandonia is the land of “abandonware”.  According to them, many of these games no longer have a copyright and are free to download, play, distribute, etc…

So I downloaded my Advanced Dungeons & Dragons’ Eye of the Beholder II – The Legend of Darkmoon game immediately.

How to get a DOS system that isn’t so fast the games are unplayable

Well, my first thought was VMWare, but again, Abandonia helped me out here.  There is a DOS Emulator called DOS Box.

I installed DOS Box on my Windows 7 box at home, with worry that it wouldn’t work well on Windows 7 64 bit, but to  my surprise, it worked well.

I do want to find a way to make the screen bigger.  And it would be cool to have a DOS VM along with DOS Box to test if it is better or worse, but hey this is sufficient for now.

Other Abandoned Games

There were many other abandoned games, such as the first Eye of the Beholder game as well as Eye of the Beholder III.  Also, Bards Tale I, II, III, and hundreds more.

So if you are looking for a blast from the past with one of your favorite games, check it out.


Changing the prop snippet for creating a Property in C#

Ok, so it is very common for the c# member variables to start with either an _ (underscore) or an m.  So when creating a property, you can save a lot of time by changing it to assume this as well.

For example, your class may look as follows:

namespace AgentConfigurationPlugin
{
    public class Class1
    {
        #region Member Variables
        String _MemberString;
        int _MemberInt;
        #endregion

        #region Constructors

        /*
		 * The default constructor
 		 */
        public Class1()
        {
        }

        #endregion

        #region Properties
        public String MemberString
        {
            get { return _MemberString; }
            set { _MemberString = value; }
        }

        public int Memberint
        {
            get { return _MemberInt; }
            set { _MemberInt = value; }
        }
        #endregion
    }
}

Note: I use the _ character even though it is hard to type (being up to the right of my pinky finger), so if you prefer, use the letter “m”, which is easy to type (being just below my pointer finger) and it also stands for “member variable”.

        #region Member Variables
        String mMemberString;
        int mMemberInt;
        #endregion

Anyway, whether it is an “m” or “_” or any other character, it is common to prefix member variables. So it would be useful if the property snippet assumed that prefix character as well.

The default snippet for creating a Property is located here:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC#\Snippets\1033\Visual C#\prop.snippet

The contents looks as follows.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
	<CodeSnippet Format="1.0.0">
		<Header>
			<Title>prop</Title>
			<Shortcut>prop</Shortcut>
			<Description>Code snippet for an automatically implemented property</Description>
			<Author>Microsoft Corporation</Author>
			<SnippetTypes>
				<SnippetType>Expansion</SnippetType>
			</SnippetTypes>
		</Header>
		<Snippet>
			<Declarations>
				<Literal>
					<ID>type</ID>
					<ToolTip>Property type</ToolTip>
					<Default>int</Default>
				</Literal>
				<Literal>
					<ID>property</ID>
					<ToolTip>Property name</ToolTip>
					<Default>MyProperty</Default>
				</Literal>
			</Declarations>
			<Code Language="csharp"><![CDATA[public $type$ $property$ { get; set; }$end$]]>
			</Code>
		</Snippet>
	</CodeSnippet>
</CodeSnippets>

Change it to be like this:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
	<CodeSnippet Format="1.0.0">
		<Header>
			<Title>prop</Title>
			<Shortcut>prop</Shortcut>
			<Description>Code snippet for an automatically implemented property</Description>
			<Author>Microsoft Corporation</Author>
			<SnippetTypes>
				<SnippetType>Expansion</SnippetType>
			</SnippetTypes>
		</Header>
		<Snippet>
			<Declarations>
				<Literal>
					<ID>type</ID>
					<ToolTip>Property type</ToolTip>
					<Default>int</Default>
				</Literal>
				<Literal>
					<ID>property</ID>
					<ToolTip>Property name</ToolTip>
					<Default>MyProperty</Default>
				</Literal>
			</Declarations>
			<Code Language="csharp"><![CDATA[public $type$ $property$
		{
    			get { return _$property$; }
    			set { _$property$ = value; }
		}
$end$]]>
			</Code>
		</Snippet>
	</CodeSnippet>
</CodeSnippets>

The key section that fixes this is:

			<Code Language="csharp"><![CDATA[public $type$ $property$
		{
    			get { return _$property$; }
    			set { _$property$ = value; }
		}
$end$]]>

Or if you use “m” instead of “_” as I do, of course you would replace the “_” with an “m”.

			<Code Language="csharp"><![CDATA[public $type$ $property$
		{
    			get { return m$property$; }
    			set { m$property$ = value; }
		}
$end$]]>

Now when you create a member variable and then a property that matches it exactly except for the prefix character, the works is done for you, making you a more efficient programmer.

You may want to change the propg snippet as well.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.


How to query a SQL database in C#?

How to query a SQL database in C#? or How to execute a database query against a database in C#?

Having used other languages where this is much simpler, I was surprised at how “not simple” this was in C#. I expected it to be a little more complex than in some scripting language such as PHP, but it was way more complex.

It is nice to run the Query and store the results in a DataTable, so that is what my example shows.

There are a few simple steps to remember.

  1. Create a String to hold the database connection string.
    (Note: If you don’t know the proper format for a connection string use SqlConnectionBuilder.)
  2. Create a SQL connection object.
  3. Open the SQL connection.
  4. Create a String to hold the query.
  5. Create a SqlCommand object and pass the constructor the connection string and the query string.
  6. Use the above SqlCommand object to create a SqlDataReader object.
  7. Create a DataTable object to hold all the data returned by the query.
  8. Use the DataTable.Load(SqlDataReader) function to put the results of the query into a DataTable.
  9. Do something with the data in your DataTable here. For example, it is common to use a foreach loop to do something with each row.
  10. Close the SQL connection.

Here is how I do it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace CountRows
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a String to hold the database connection string.
            // NOTE: Put in a real database connection string here or runtime won't work
            string sdwConnectionString = @"Data Source = ServerName; user id=UserName; password=P@sswd!; Initial Catalog = DatabaseName;";

            // Create a connection
            SqlConnection sdwDBConnection = new SqlConnection(sdwConnectionString);

            // Open the connection
            sdwDBConnection.Open();

            // Create a String to hold the query.
            string query = "SELECT * FROM MyTable";

            // Create a SqlCommand object and pass the constructor the connection string and the query string.
            SqlCommand queryCommand = new SqlCommand(query, sdwDBConnection);

            // Use the above SqlCommand object to create a SqlDataReader object.
            SqlDataReader queryCommandReader = queryCommand.ExecuteReader();

            // Create a DataTable object to hold all the data returned by the query.
            DataTable dataTable = new DataTable();

            // Use the DataTable.Load(SqlDataReader) function to put the results of the query into a DataTable.
            dataTable.Load(queryCommandReader);

            // Example 1 - Print your  Column Headers
            String columns = string.Empty;
            foreach (DataColumn column in dataTable.Columns)
            {
                columns += column.ColumnName + " | ";
            }
            Console.WriteLine(columns);

            // Example 2 - Print the first 10 row of data
            int topRows = 10;
            for (int i = 0; i < topRows; i++)
            {
                String rowText = string.Empty;
                foreach (DataColumn column in dataTable.Columns)
                {
                    rowText += dataTable.Rows[i][column.ColumnName] + " | ";
                }
                Console.WriteLine(rowText);
            }

            // Close the connection
            sdwDBConnection.Close();
        }
    }
}

So now the results are stored in a DataTable.

You can now access each row of data using the DataTable.Rows collection.

 

Return to ADO.NET and Database with C#


NSIS or WiX?

Hello everyone,

I want to do a quick comparison of NSIS and WiX.  Of course, NSIS creates and executable and WiX creates an MSI, so there will have to be some discussion about whether there really are any benefits to an MSI over an EXE installer.

As many of you know, I work for LANDesk.  In 2008/2009 I developed a plugin for my company’s software.  I built the plugin in C#.  I used Visual Studio to create the plugin.

I wanted an installer that created the install package whenever ran a build in Visual Studio.

I succeeded in doing this using NSIS (Nullsoft Scriptable Install System).

Ok, so since I have a nice working solution, I am not going to change my plugin to use a different installer, even if my NSIS and WiX evaluation shows WiX to be better.  However, on future projects where a solution isn’t yet in place, or when recommending  a solution to others, I may decide to use the better one of the two.

P.S. If there is a third installer tool that is free that you think is better, feel free to comment about it.

Also, I obviously bit off more than I can chew with this post, so it is unfinished.  Of course, there is no reason that new experiences can’t lead me to update this or that comments cannot help me finish this.

NSIS (Nullsoft Scriptable Install System)

NSIS is script-based.

See the list of features here:
http://nsis.sourceforge.net/Features

It also has a lot of users.
http://nsis.sourceforge.net/Users

For my plugin, I actually created the .nsi script by hand the first time and thought it decently complex. However, shortly thereafter an Eclipse plugin was created, and I created a sample with the Eclipse plugin and modified it and it is rock solid.

Anyway, now I have a project that included my .nsi file, I was able to use the command line tool, makensis.exe, to run with two parameters: the .nsi file and the output file name.

"C:\Program Files\NSIS\makensis.exe"  "$(ProjectDir)Installer\LANDesk Support Tools.nsi" "$(ProjectDir)Installer\LANDesk Support Tools_Beta_6.exe"

I am extremely happy with NSIS.

I like it for the following features:

  1. It was easy to use (especially with the Eclipse plugin)
  2. It created a small installer.
  3. It runs silently when passed the -S parameter.
  4. There was lots of documentation.
  5. There were plenty of add-on features.
  6. I had the option to include all files in a folder in my installer or specify the files individually (same with the uninstaller).  This is nice because if I create a new file in a folder that is already picked up by the installer, I don’t have to change the installer or uninstaller at all.
  7. Support for other languages was rather easy to add into my installer.
  8. It was simple to integrate with Visual Studio (add a single command in the post-build section).
  9. Notepad++ has colored syntax for it (though unfortunately Visual Studio does not but I was able to change the default tool to open it with to be Notepad++)
  10. It has an intuitive method for creating Install Sections.
  11. I can provide my installer script open source and anyone who wants to can edit and rebuild the installers
  12. The NSIS community is huge.
  13. You don’t need to be a developer to learn to use NSIS (I gave it to two non-developers and they had solutions in little time (less than two days of work).

Some Negatives…

  1. I couldn’t quickly find a way to automate the installer with a progress bar, only completely silent.

Windows Installer XML (WiX) toolset

Ok. So I’ll be honest.  I am not on the MSI bandwagon.  What features does an MSI really give me.  I find that most people say the prefer an MSI when when pinned down, they are using basic features that NSIS provides ten times easier and when they need a more complex feature, they are writing a custom action and adding it to the MSI which is not any better than adding a custom action to an NSIS installer.

I hear arguments about it being easier to push and MSI with Active Directory, but if you can’t push a .exe with a /S parameter just as easily with Active Directory, you are probably not a very versatile AD administrator. Not to mention AD is not a very good software distribution tool to begin with. Most Desktop Management tools, such as LANDesk, are much better for the job. Besides, LANDesk and the competitors all push EXEs just fine and just as easily as they push MSIs, so the whole MSI vs. EXE is just not really a big deal like some may have you believe.

The one big deal is that MSI is a standard and so every MSI will have some default features.  These are quite good:

  1. Mostly the same command line parameters for all MSI files everywhere (though you can add more and man properties can be changed with command line too)
  2. The ability to change a property in the command line.
  3. The ability to change a lot of properties in a transform file and call the MSI with the transform file.

But are those features really an improvement on NSIS.  For example, NSIS uses the /S switch to silence and install, which is just as easy as use the /q switch for an MSI and actually a lot of installers use /S so it is very common.

Is it really easier to create a property in an MSI than to just add a supported command line parameter in an NSIS installer.  Maybe not.  However, if a public property exists, a user can change it even it the developers didn’t really know a customer would want to do that.  With NSIS, there is no such ability.

Some negatives

  1. Documentation is scarce and when it is there is scattered.
  2. Most large installers cannot be completed with an MSI and end up wrapped up in a .EXE anyway and then it is harder to pass parameters to the MSI because you have to use the /v switch and quoting becomes and issue.
  3. Development is difficult and has a high learning curve (yet again, the scattered and scarce documentation compounds this problem)
  4. You pretty much have to be a developer to make MSIs and this doesn’t change just because you use WiX (I couldn’t hand WiX to someone and expect a working installer in as little as two days as I did with NSIS)

Building an Installer

Ok, so lets choose some key general features and decide a winner.

Ease of use

I have to say that the well documented and large community base NSIS has, added to the fact that you don’t have to be a developer to use it, makes it a clear winner of the ease of use category.

Winner: NSIS

Customizable

To be determined…

Language Support

To be determined…

Maintainability/Scalability

To be determined…

Using the Installer

Lets pick out some key features for an end user.  Which installer is better for them?

End User Ease of use

To be determined…

Speed of Installer

To be determined…

Enterprise Features

Lets talk about enterprise features and pick a winner for those features too.

There are two key features that an Enterprise needs an installer to support:

  1. Automated installation
  2. Silent installations

No, these are not the same.  Technically a silent installation is an Automated installation, but an Automated installation is not necessarily silent.  There may be times when you want to show a progress bar.

Automating the Installation

Both NSIS and WiX can create installers that can be automated.  Both support automation by default. With both, care must be taken with custom actions to make them also automated.

There are times when an install should be automated but show a progress bar and/or a success or failure when finished.  This is common with install on demand or install on first use functions such as LANDesk’s Launch Pad and similar solutions.  The idea is that the icon or shortcut is there, but the software isn’t installed until first use.

MSI files and there for WiX have the following supported functions for automating and Silencing an MSI.

Display Options
	/quiet
		Quiet mode, no user interaction
	/passive
		Unattended mode - progress bar only
	/q[n|b|r|f]
		Sets user interface level
		n - No UI
		b - Basic UI
		r - Reduced UI
		f - Full UI (default)
	/help
		Help information

So I had a hard time finding whether NSIS could do this level of different UI states.  Basically, I found the silent switch, but not a switch for an automated install with progress showing.

Winner: MSI

Silencing the Installation

Both NSIS and WiX can create installers that can be silent.  Both support Silent installs by default.  However, with both, care must be taken with custom actions to make them also silent.

Silencing the install is very common.  When a corporation pushes out software, the last thing they want to do is have the user see it and create a call storm to the help desk just to ask what is going on, and then of course ever subsequent computer problem is related to the newly deployed software in the end user’s mind (even when there is no possible way the new software could have caused them to be missing some emails 🙂

Overall Winner: Tie


How to login to the new Family Search web site for the first time?

Section 1 – How the General Public Obtains an Account?

The Church of Jesus Christ of Latter-day Saints allows anyone with the desire to access and use the genealogical information on their site, even if they have no affiliation with their church at all.  All you have to do is create an account.

Note: If you are a baptized member of The Church of Jesus Christ of Latter-day Saints, go to Section2.

  1. On your computer, open a web browser (Internet Explorer, MSN, Firefox, Safari, Google Chrome, Opera, etc.
  2. Type in http://new.familysearch.org into your browser and press Enter.  This will take you to the front page.
  3. Click the link on the bottom right called: Register for the new Family Search.  This takes you to the next page.
  4. Check the radio button called: FamilySearch Account (for the general public)
  5. Fill out the form.
  6. Click Register.
  7. The next page informs you that a verification email has been sent.
  8. Now go check your email.
  9. You email should have an email address from the LDS Church.Note: If you do not see an email, check your spam folder.
  10. Once you have found the email, click the link in the email to confirm your membership.

You now have a username and password to access this site:

Section 2 – How baptized members obtain an account?

The section explains to members of The Church of Jesus Christ of Latter-day Saints how to access the new Family Search site.  If you are not a member of The Church of Jesus Christ of Latter-day Saints, please go to Section 2.

Note: Download this in a Microsoft Word document with screen shots here: How do church members access the LDS Stake and Ward web site and the new Family Search web site

Members of The Church of Jesus Christ of Latter-day Saints can login to the new Family Search with their account on lds.org that lets them access the LDS Stake and Ward Web Site.  If you already have an account and can already access the LDS Stake and Ward Web Site, then simply go to http://new.familysearch.org and login with the same user name an password.

If you don’t have an account for the LDS Stake and Ward Web Site, then you should obtain one.

Before you begin gather the following two pieces of information:

  • Membership record number
  • Date of Birth

Note: This data is on your Individual Ordinance Summary sheet. If you do not have this sheet, request it from one of the ward clerks.

How to create for yourself a login username and password for both the LDS Stake and Ward Web Site and the new Family Search?

  1. On your computer, open a web browser (Internet Explorer, MSN, Firefox, Safari, Google Chrome, Opera, etc.
  2. Type in http://www.lds.org into your browser and press Enter.  This will take you to the Church’s global home page.The home page is laid out with three columns with many links to resources for you.
  3. On the far right column, click on the link to Stake & Ward Web Sites.
    This opens the Stake and Ward Web Site Sign In page.  This page has two fields for a username and password.
    If you already have a username and password you can login to both LDS.org and new Family Search.
  1. Click on the Obtain an LDS Account link on the left below the login text fields.
    You are taking to the LDS Membership Info page.
  1. Enter your Membership Record number. If you don’t have this, you can ask your bishopric or membership clerk.
  2. Enter your Day of Birth.
  3. Enter the letters you see on the image (security feature).  These letters are difficult to read. Don’t feel bad if you get them wrong once or twice, as everyone usually does.
  4. Click Next Step.  It tries to detect who you are based on membership record information.
  5. Click Yes if it is you.
  6. The next screen has a form where it prompts for your email address.
  7. Enter your email address twice as shown.
  8. Scroll down.
  9. Provide a Username and a password. Please store this information so you do not forget it.
  10. Click Next Step.
  11. Now go check your email.
  12. You email should have an email address from the LDS Church.Note: If you do not see an email, check your spam folder.
  13. Once you have found the email, click the link in the email to confirm your membership.

You now have a username and password to access these sites:


Connecting to Active Directory with Kerberos on FreeBSD

So, I am trying to get Active Directory integration with FreeBSD and I have been researching this for a while as I have stated.
http://rhyous.com/2010/01/13/researching-the-process-for-integrating-freebsd-with-active-directory

I don’t have it all integrated yet. I keep running into road blocks.

First, I want to be able to do integration with Kerberos alone.

One part that is really easy is connecting to active directory with kerberos.

Step 1 – Collect Active Directory information.

Active Directory Domain LD.LAB
AD Domain Controller vmdc.ld.lab
Domain Admin user name administrator
Domain Admin password pw

Step 2 – Create the /etc/krb5.conf

Here is mine. Supposedly this is case sensitive, so make sure to match the case.

[libdefaults]
  clockskew = 300
  default_realm = LD.LAB

[realms]
  LD.LAB = {
    kdc = vmdc.ld.lab
    default_domain = LD.LAB
    kpasswd_server = vmdc.ld.lab
  }

[domain_realm]
  .LD.LAB = LD.LAB

Step 3 – Acquiring a ticket

  1. Use kinit and a domain user and password to acquire a certificate.# kinit administratorEnter the password when prompted.
  2. Use klist to list the kerberos tickets.

However, once I have this working, I don’t know how to change authentication using nsswitch.conf and /etc/pam.d/sshd or system to make it work.

I assumed I wouldn’t need to change nsswitch.conf and that for Step 4 I would just have to uncomment the pam_krb5.so lines in the the /etc/pam.d/sshd and /etc/pam.d/system but unfortunately, that isn’t enough.  Authentication is not working.

I can’t seem to find much documentation on pam and kerberos in FreeBSD.  I have tried to add “debug” to the lines in the /etc/pam.d/sshd and /etc/pam.d/system but if that is adding more logging then I am not seeing it.


BSD Magazine releases its May 2010 Issue.

Hello all,

BSDMag just released the may issue. Get it here.

http://bsdmag.org/magazine/1067-embedded-bsd


How to get the parent process that launched a C# application?

Hey all,

I have a process that is a C# process.  I need to do something different if someone just double-clicks the application than if it is launched by a certain other process.  So I decided to check the parent process.

I couldn’t find a simple C# only method. But I did find a code snippet that works. There were actually lots of posts on that provided the following code snippet or variations thereof, so I consider it to be public domain.  So obviously I didn’t write this part.

        private static Process GetParentProcess()
        {
            int iParentPid = 0;
            int iCurrentPid = Process.GetCurrentProcess().Id;

            IntPtr oHnd = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

            if (oHnd == IntPtr.Zero)
                return null;

            PROCESSENTRY32 oProcInfo = new PROCESSENTRY32();

            oProcInfo.dwSize =
            (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(PROCESSENTRY32));

            if (Process32First(oHnd, ref oProcInfo) == false)
                return null;

            do
            {
                if (iCurrentPid == oProcInfo.th32ProcessID)
                    iParentPid = (int)oProcInfo.th32ParentProcessID;
            }
            while (iParentPid == 0 && Process32Next(oHnd, ref oProcInfo));

            if (iParentPid > 0)
                return Process.GetProcessById(iParentPid);
            else
                return null;
        }

        static uint TH32CS_SNAPPROCESS = 2;

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESSENTRY32
        {
            public uint dwSize;
            public uint cntUsage;
            public uint th32ProcessID;
            public IntPtr th32DefaultHeapID;
            public uint th32ModuleID;
            public uint cntThreads;
            public uint th32ParentProcessID;
            public int pcPriClassBase;
            public uint dwFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szExeFile;
        };

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);

        [DllImport("kernel32.dll")]
        static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

        [DllImport("kernel32.dll")]
        static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
    }

I took this code snippet and improved upon it and made myself the following static class. This class more easily exposes:

  • Parent Process Id
  • Parent Process name
  • Parent process executable name
  • Full path to parent process executable
  • Directory name where the parent process executable resides
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Runtime.InteropServices;

namespace ParentProcess
{
    public class ParentProcess
    {
        public static String ProcessName
        {
            get { return GetParentProcess().ProcessName; }
        }

        public static int ProcessId
        {
            get { return GetParentProcess().Id; }
        }

        public static String FullPath
        {
            get
            {
                return GetParentProcess().MainModule.FileName;
            }
        }

        public static String FileName
        {
            get
            {
                return System.IO.Path.GetFileName(GetParentProcess().MainModule.FileName);
            }
        }

        public static String DirectoryName
        {
            get
            {
                return System.IO.Path.GetDirectoryName(GetParentProcess().MainModule.FileName);
            }
        }

        private static Process GetParentProcess()
        {
            int iParentPid = 0;
            int iCurrentPid = Process.GetCurrentProcess().Id;

            IntPtr oHnd = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

            if (oHnd == IntPtr.Zero)
                return null;

            PROCESSENTRY32 oProcInfo = new PROCESSENTRY32();

            oProcInfo.dwSize =
            (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(PROCESSENTRY32));

            if (Process32First(oHnd, ref oProcInfo) == false)
                return null;

            do
            {
                if (iCurrentPid == oProcInfo.th32ProcessID)
                    iParentPid = (int)oProcInfo.th32ParentProcessID;
            }
            while (iParentPid == 0 && Process32Next(oHnd, ref oProcInfo));

            if (iParentPid > 0)
                return Process.GetProcessById(iParentPid);
            else
                return null;
        }

        static uint TH32CS_SNAPPROCESS = 2;

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESSENTRY32
        {
            public uint dwSize;
            public uint cntUsage;
            public uint th32ProcessID;
            public IntPtr th32DefaultHeapID;
            public uint th32ModuleID;
            public uint cntThreads;
            public uint th32ParentProcessID;
            public int pcPriClassBase;
            public uint dwFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szExeFile;
        };

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);

        [DllImport("kernel32.dll")]
        static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

        [DllImport("kernel32.dll")]
        static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
    }
}

This makes it easier for me to simply include the class above in my code and make simple calls:

String exename = ParentProcess.FileName;
String FullPathToExe = ParentProcess.FullPath;
String DirectoryInWhichExeResides= ParentProcess.DirectoryName;

…and the pid and process name, etc…

I hope this helps you.

References
http://www.facebook.com/note.php?note_id=73447531256
http://www.debugging.com/bug/6657
http://www.eggheadcafe.com/software/aspnet/35541264/how-to-get-the-parent-pro.aspx


No Copyright.


Generic XML Serializer Class for C# and an XML Serialization usage example

UPDATE: This is now part of the EasyXml NuGet package. There is also an EasyXml.Sources NuGet package.

Hey all,

Today I was working on XML Serialization.

After learning how to do it, I discovered it takes four lines of code to write an XML and four lines of code to read in an XML.

However, I prefer one line of code to four so I made a Serializer.cs class with two static functions.

After thinking about it, I made these classes generic so they work with any type. I hope this helps someone.

using System;
using System.IO;
using System.Xml.Serialization;

namespace BlogTool
{
    public class Serializer
    {
        #region Functions
        public static void SerializeToXML(T t, String inFilename)
        {
            XmlSerializer serializer = new XmlSerializer(t.GetType());
            TextWriter textWriter = new StreamWriter(inFilename);
            serializer.Serialize(textWriter, t);
            textWriter.Close();
        }

        public static T DeserializeFromXML(String inFilename)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(T));
            TextReader textReader = new StreamReader(inFilename);
            T retVal = (T)deserializer.Deserialize(textReader);
            textReader.Close();
            return retVal;
        }
        #endregion
    }
}

So now if you have a class, you can easily serialize it to and from an XML with a single line.

Here is an example Project that contains these files:

  • Blog.cs
  • BlogList.cs
  • Program.cs
  • Serializer.cs

Blog.cs

using System;

namespace BlogTool
{
    [Serializable()]
    public class Blog
    {
        #region Member Variables
        String mBlogUrl;
        String mCategory;
        #endregion

        #region Constructors
        public Blog()
        {
        }

        public Blog(String inURL, String inCategory)
        {
            mBlogUrl = inURL;
            mCategory = inCategory;
        }
        #endregion

        #region Properties
        public String BlogUrl
        {
            get { return mBlogUrl; }
            set { mBlogUrl= value; }
        }

        public String Category
        {
            get { return mCategory; }
            set { mCategory= value; }
        }
        #endregion
    }
}

BlogList.cs

using System.Collections.Generic;

namespace BlogTool
{
    [Serializable]
    public class BlogList
    {
        #region Member Variables
        List mBlogs = new List();
        #endregion

        #region Constructors

        /*
		 * The default constructor
 		 */
        public BlogList()
        {
        }

        #endregion

        #region Properties
        public List Blogs
        {
            get { return mBlogs; }
            set { mBlogs = value; }
        }
        #endregion
    }
}

Program.cs

namespace BlogTool
{
    class Program
    {
        static void Main(string[] args)
        {
            BlogList bloglist = new BlogList();
            Blog b1 = new Blog("http://rhyous.com","Software");
            Blog b2 = new Blog("http://www.alittletipsy.com", "Crafts");
            bloglist.Blogs.Add(b1);
            bloglist.Blogs.Add(b2);
            Serializer.SerializeToXML(bloglist, "FavoriteBlogs.xml");
        }
    }
}

Serializer.cs

using System;
using System.IO;
using System.Xml.Serialization;

namespace BlogTool
{
    public class Serializer
    {
        #region Functions
        public static void SerializeToXML(T t, String inFilename)
        {
            XmlSerializer serializer = new XmlSerializer(t.GetType());
            TextWriter textWriter = new StreamWriter(inFilename);
            serializer.Serialize(textWriter, t);
            textWriter.Close();
        }

        public static T DeserializeFromXML(String inFilename)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(T));
            TextReader textReader = new StreamReader(inFilename);
            T retVal = (T)deserializer.Deserialize(textReader);
            textReader.Close();
            return retVal;
        }
        #endregion
    }
}

Ok, so now that you have the files, you can run this program.

In the bin\debug or bin\release directory where you executable is placed when you build, you will see the FavoriteBlogs.xml file. The XML should look as follows:

<!--?xml version="1.0" encoding="utf-8"?-->

      http://rhyous.com
      Software

      http://www.alittletipsy.com
      Crafts

I know, this is not written very well as a walk-thru, but I wrote it fast. Maybe I will clean it up later.

Update: 5/8/14

namespace Rhyous.EasyXml
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Text;
    using System.Threading;
    using System.Xml;
    using System.Xml.Serialization;

    [ExcludeFromCodeCoverage]
    public static class Serializer
    {
        #region Functions

        /// <summary>
        /// This function writes the serialized XML to the file name passed in.
        /// </summary>
        /// <typeparam name="T">The object type to serialize.</typeparam>
        /// <param name="t">The instance of the object.</param>
        /// <param name="outFilename">The file name. It can be a full path.</param>
        /// <param name="inOmitXmlDeclaration"></param>
        /// <param name="inNameSpaces"></param>
        /// <param name="inEncoding"></param>
        public static void SerializeToXml<T>(T t, string outFilename, bool inOmitXmlDeclaration = false, XmlSerializerNamespaces inNameSpaces = null, Encoding inEncoding = null)
        {
            MakeDirectoryPath(outFilename);
            var ns = inNameSpaces;
            if (ns == null)
            {
                ns = new XmlSerializerNamespaces();
                ns.Add("", "");
            }
            var serializer = new XmlSerializer(t.GetType());
            var textWriter = (TextWriter)new StreamWriter(outFilename);
            if (inEncoding != null && inEncoding.Equals(Encoding.UTF8))
                textWriter = new Utf8StreamWriter(outFilename);
            var xmlWriter = XmlWriter.Create(textWriter, new XmlWriterSettings { OmitXmlDeclaration = inOmitXmlDeclaration });
            serializer.Serialize(xmlWriter, t, ns);
            textWriter.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="outFilename"></param>
        private static void MakeDirectoryPath(string outFilename)
        {
            var dir = Path.GetDirectoryName(outFilename);
            if (dir != null && !Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
        }

        /// <summary>
        /// This function returns the serialized XML as a string
        /// </summary>
        /// <typeparam name="T">The object type to serialize.</typeparam>
        /// <param name="t">The instance of the object.</param>
        /// <param name="inOmitXmlDeclaration"></param>
        /// <param name="inNameSpaces"></param>
        /// <param name="inEncoding"></param>
        public static string SerializeToXml<T>(T t, bool inOmitXmlDeclaration = false, XmlSerializerNamespaces inNameSpaces = null, Encoding inEncoding = null)
        {
            var ns = inNameSpaces;
            if (ns == null)
            {
                ns = new XmlSerializerNamespaces();
                ns.Add("", "");
            }
            var serializer = new XmlSerializer(t.GetType());
            var textWriter = (TextWriter)new StringWriter();
            if (inEncoding != null && inEncoding.Equals(Encoding.UTF8))
                textWriter = new Utf8StringWriter();
            var xmlWriter = XmlWriter.Create(textWriter, new XmlWriterSettings { OmitXmlDeclaration = inOmitXmlDeclaration });
            serializer.Serialize(xmlWriter, t, ns);
            return textWriter.ToString();
        }

        /// <summary>
        /// This function deserializes the XML file passed in.
        /// </summary>
        /// <typeparam name="T">The object type to serialize.</typeparam>
        /// <param name="inFilename">The file or full path to the file.</param>
        /// <returns>The object that was deserialized from xml.</returns>
        public static T DeserializeFromXml<T>(String inFilename)
        {
            if (string.IsNullOrWhiteSpace(inFilename))
            {
                return default(T);
            }
            // Wait 1 second if file doesn't exist, in case we are waiting on a
            // separate thread and beat it here.
            if (!File.Exists(inFilename))
                Thread.Sleep(1000);

            // File should exist by now.
            if (File.Exists(inFilename))
            {
                var deserializer = new XmlSerializer(typeof(T));
                var textReader = (TextReader)new StreamReader(inFilename);
                var reader = new XmlTextReader(textReader);
                reader.Read();
                var retVal = (T)deserializer.Deserialize(reader);
                textReader.Close();
                return retVal;
            }
            throw new FileNotFoundException(inFilename);
        }

        /// <summary>
        /// This function deserializes the XML string passed in.
        /// </summary>
        /// <typeparam name="T">The object type to serialize.</typeparam>
        /// <param name="inString">The string containing the XML.</param>
        /// <returns>The object that was deserialized from xml.</returns>
        public static T DeserializeFromXml<T>(ref string inString)
        {
            if (string.IsNullOrWhiteSpace(inString))
            {
                return default(T);
            }
            var deserializer = new XmlSerializer(typeof(T));
            var textReader = (TextReader)new StringReader(inString);
            var retVal = (T)deserializer.Deserialize(textReader);
            textReader.Close();
            return retVal;
        }
        #endregion

        #region UTF8StringWriter
        public sealed class Utf8StringWriter : StringWriter
        {
            public override Encoding Encoding { get { return Encoding.UTF8; } }
        }

        public sealed class Utf8StreamWriter : StreamWriter
        {
            public Utf8StreamWriter(string file)
                : base(file)
            {
            }

            public override Encoding Encoding { get { return Encoding.UTF8; } }
        }
        #endregion
    }
}

Sources:
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
http://www.switchonthecode.com/tutorials/csharp-tutorial-xml-serialization


fdisk failure re-installing PCBSD 8

Ok, so I have an IBM T40 and I am installed PC-BSD 8.  Then for fun, I downloaded a more recent snapshot (PCBSD 8-Stable) and installed that.

However, woe is me, I ran into this FreeBSD bug: 131087. This prevents me from using my Wireless, which on a laptop is a show stopper.

So I got out the release version of the PCBSD 8 installer and tried to install again, however, now it fails.

Here is the log:

Running: find-update-parts
kern.geom.debugflags: 0 -> 16
Cleaning up ad0
Running: dd if=/dev/zero of=/dev/ad0 count=2048
2048+0 records in
2048+0 records out
1048576 bytes transferred in 0.391058 secs (2681383 bytes/sec)
Running fdisk on ad0
Running: fdisk -I /dev/ad0
fdisk: invalid fdisk partition table found
fdisk: Class not found
******* Working on device /dev/ad0 *******
ERROR: The slice ad0s1 doesn't exist! FDISK Failure
Running: umount /cdmnt-install
umount: /cdmnt-install: statfs: No such file or directory
umount: /cdmnt-install: unknown file system

So obviously something is broke with the partition table.  I am not sure if this can be duplicated but it sure is annoying.
So how do I fix this?  Well, right now I decided to use dd to wipe my drive.

dd if=/dev/zero of=/dev/ad0 bs=4096k

That took something more than an hour and then I reinstalled an all worked fine.

Anyway, I wonder if there is a bug with the installer that caused this or if this is a result of the multiple crashes that occurred due to the iwi bug that causes kernel panic.