Coming… Later Part 2

Magicka - Red FireI was just talked into and/or talked my friends into purchasing Magicka.  That reminded me I had posted Part 1 of “How the Gold Master was Delayed” and I should look for Part 2. It’s nice to see a humorous look at a very stressful time for both the developer and the client.

Ideally you you should never be late but for a software project but if you are going to be late at least make the best of it. From the videos it sounds like the developers figured out what they had done wrong and worked out an achievable solution with Lord Pub Lisher.  I like the fact they choose to fix the bugs and polish the game rather then force it out the door.  While Magicka still has some technical issues it has sold well.

Next time I see a project running late I’ll have to remember these videos and make sure I work out a good solution with my client.  A solution that everyone can work with and keep the stress levels to a minimum.

Posted in Business Side, Fun, Software Development | Tagged , , , | Comments Off on Coming… Later Part 2

SQL Server Dependency Query

You’ve been staring at the SQL Server view vwCustomersGH for the past hour.  The view is part of a project you just started maintaining and like many views and stored procedures in the project you are sure it’s not being used anymore.  Because you are a conscientious and professional software developer you want to remove this view along with the others.  You don’t want to leave it lying around for the next developer to stumble over like you did, getting confused between the legit vwCustomers and  suspicious vwCustomersGH.  What does the GH stand for anyway?

Using Ctrl-F you quickly determine the view is not used in the code.  Actually it was used once in a class that was mostly commented out and not referenced by anything else.  You can safely remove the class.  The question is, “is the view referenced by another view in the database?”.  You have right clicked on it and see the SQL Server tells you it has no dependencies but that might not be true.

Deep repressed memories come flooding back.  You see your past fresh-faced developer self deleting a view.  So trusting that SQL Server is correct when it says nothing depends on that view.  Oh to be young and trusting again.  You watch as Fresh-Faced deletes the view, updates the SQL scripts, and commits the changes the day before the project goes live.  Sadness fills your heart knowing that the happy grin on Fresh-Faced will be replaced with shame when the project launch fails and fingers point at him.  Turns out the deleted view was being used and SQL Server was incorrect.

Back in the present you wipe away a single tear and glance around to see if anyone noticed.  You want to take the easy route and not delete the view.  “Just leave it”, a voice in your head whispers.  “No one will know and you will be long gone by the time the next developer arrives to maintain the project”.

NO! you shout, hopefully just in your head, glancing around just to be sure.  You are not a lazy scum-bag developer.  You will do the honorable thing and delete the unused view.  But how?  You jump onto the Internet, which some people call Google, and after some searching you come across a blog post from some guy in a basement.   It’s 5 paragraphs of rambling text that you quickly skim over and find at  the bottom is a query that will answer your question:

“What other database objects depend on this view I want to delete?”

The query looks like:

Select so.name
From syscomments sc
Inner Join sysobjects so ON sc.id = so.id
Where text Like '%{0}%'
And so.Name <> '{0}'

It says to replace the “{0}” with the name of the view, stored procedure, table, etc. and the query will return you all the names of all the database objects that depend on “{0}”.  You type in “vwCustomersGH” and the query returns you one record: vwClientsGH.  Darn it, you were sure it was unused.  Wait a minute, what depends on vwClientsGH and less important, what is with the GH suffix?  You run the query again with vwClientsGH and this time the query returns nothing.  A quick Ctrl-F shows the wvClientsGH view is not referenced in the code either.  Satisfied you can delete the two views, you do, run your unit tests (which Fresh-Faced didn’t have), and commit your changes.  Your QA team finds no issues with your change and the next version of the project is released.

You go home that night happy.  Knowing that you have made the next maintenance developer’s life better even if he, and no one else, knows it.

Posted in Code Examples | Tagged , | Comments Off on SQL Server Dependency Query

Holiday Cheer

Saturday Morning Productions has saved up its hard earned pennies from the proceeds of mini-compressor for its first ever Staff Christmas Party! We love parties! Well, this party will be pretty quiet since there are only 2 staff members .

In the past, we’ve worked at all sorts of firms and participated in their Christmas parties. Once, during the dot-com boom, we were both flown to Cleveland to celebrate Christmas with other employees and their spouses. We’ve also been invited snowmobiling and dinner and at the boss’s house. A more rukus one featured a fight between 2 staff members in the parking lot of a rather upscale hotel. That one was especially funny because the company had hired a band to play at the party. The band consisted of members from a local media station. The local media was ready in the parking lot to report on the brawl. Fun times.

No sireee, ours will be more subdued.

I designed the invitations to look like this:

You and your spouse are cordially invited to The
Saturday Morning Productions Christmas Party
where the food and drinks will flow freely.

 When: (Date in December that’s not too busy and babysitting is available)

Where: (A nice restaurant we’ve enjoyed in the past)

Please RSVP

Posted in Fun | Comments Off on Holiday Cheer

Kids Thinking Outside the Box – Who to Invite to Your Birthday?

My 5 year old daughter is endlessly planning her birthday parties, even 11 months and 30 days in advance.  Her recent planning session focused on who she should invite.  After going over her list of friends she paused and then asked us “can I invite Santa Clause to my birthday?”

Posted in Fun, Kids Thinking Outside the Box | Tagged , | Comments Off on Kids Thinking Outside the Box – Who to Invite to Your Birthday?

NUnit Error “Attempted to access an unloaded AppDomain”

I was plagued by the above error but found a workaround, at least one that worked for me.  It’s a one line change to the NUnit config file.  Note, this the actual NUnit config file that is installed in C:Program FilesNUnit and used by the NUnit GUI/Console executables.  Not the config file used by your NUnit project.  Find the following line and either remove it or change the value to zero:

<legacyUnhandledExceptionPolicy enabled="1" />

That’s it, just don’t forget to restart NUnit for the changes to take effect.  Also don’t forget you will need to update the NUnit-Console config file as well.  The NUnit bug report can be found here and the legacy setting can be found here.

If you are interested in more background, specifically my personal account of encountering the bug then keep reading.

It all started with the build log spitting out the following error and me getting the same error occasionally when manually running the tests:

[11:35:51]: NAnt output:
[11:35:51]: [exec] Copyright (C) 2000-2002 Philip Craig.
[11:35:51]: [exec] All Rights Reserved.
[11:35:51]: [exec] Runtime Environment -
[11:35:51]: [exec] OS Version: Microsoft Windows NT 5.2.3790 Service Pack 2
[11:35:51]: [exec]   CLR Version: 2.0.50727.3615 ( Net 2.0 )
[11:35:51]: [exec] ProcessModel: Default    DomainUsage: Default
[11:35:51]: [exec] Execution Runtime: Default
[11:35:51]: [exec] ............................
[11:35:51]: [exec] Tests run: 28, Errors: 0, Failures: 0, Inconclusive: 0, Time: 9.4689318 seconds
[11:35:51]: [exec]   Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0
[11:35:51]: [exec] Unhandled exceptions:
[11:35:51]: [exec] 1)  : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.<span style="text-decoration: underline;">[11:35:51]:
[11:35:51]: [echo] Build failed.

The program I’m working on is subject to outside rules that change frequently.  To prevent constant re-compiles and re-releases of the program whenever the rules change the end users can create/update the rules using a pseudo VB.NET syntax that gets converted into a .NET assembly.

To load the dynamic rules we have a class that creates an application domain on the fly, loads an assembly into the domain, runs some methods from the newly loaded assembly, then unloads everything.

Side Note: the reason everything is wrapped in a application domain is you can’t unload assemblies, just application domains.

To test the loading of the rules I created a NUnit test.  The TestFixtureSetUp creates the new AppDomain as such:

Dim myAppDomain As AppDomain = AppDomain.CreateDomain("NewDomain", Nothing, ads)

Dim myObject as SomeObject = CType(myAppDomain.CreateInstance("AssemblyName", "AssemblyNamespace.SomeObject ", True, BindingFlags.CreateInstance, Nothing, New Object() {assemblyFile }, Nothing, Nothing, Nothing).Unwrap(), SomeObject)

Then in the tests I do something like:

Assert.AreEqual(expectedValue, myObject.DoAction())

Then finally in the TestFixtureTearDown I have the following:

AppDomain.Unload(myAppDomain)

The error occurs after the TestFixtureTearDown is complete but only occurs intermittently.  The error still occurs if I wrap the unload in a try-catch block.  The exact error message I get is:

An unhandled System.AppDomainUnloadedException was thrown while executing this test : Attempted to access an unloaded AppDomain.

I spent more time then I should have chasing down this bug so hopefully this is helpful to you.

Posted in Code Examples | Tagged , | Comments Off on NUnit Error “Attempted to access an unloaded AppDomain”

Upgrading Mini-Compressor to .NET 4.0 Notes Addendum

You can read part one at Upgrading Mini-Compressor to .NET 4.0 Notes post.

One item that I feel has been neglected by Visual Studio is the Setup & Deployment projects.  There has been little improvements to them since Visual Studio 2003 but finally VS2010 has new “feature”:

  1. A customer installs your software using the installer created using VS2008.
  2. You upgrade your product to .NET 4.0 using VS2010 and create a new MSI.
  3. The customer runs your new MSI to upgrade their software.  After the upgrade is complete nothing is installed at all.

I really do mean nothing, no files in the Program Files folder, no registry entries, shortcuts, etc.  The old version is gone along with the new version.  It’s a great new feature, I mean bug.  The bug is known to Microsoft and you can read more about it here.  A summarized description of the error and some workarounds:

Posted by smondal on 7/22/2010 at 1:17 PM

Basically the Component GUID’s are changed when setup projects are migrated from VS2008 to VS2010. InstallValidate marks components to be installed locally, RemoveExistingProducts that run at sequence 6550 ends up removing these components.

There would be two solutions:

1.Manually change the component GUID’s to be the same as that of VS2008 (this might not be a feasible solution)

2. Resequence RemoveExistingProducts right after InstallInitialize (sequence number 1501). This ensures that older files are removed and reinstalled by the newer version.

More information about the standard sequence for MSI installers can be found here.

Some extra weirdness not in the reported bug is that the application is still listed as installed under the Add/Remove Programs (Programs and Features for Windows 7).  If you click Repair it will install correctly.

So I tried the script listed in the bug report but when it ran I got the following message:

If I clicked continue Mini-Compressor installed just fine.  I understand why the dialog box appears but in my case it won’t make any sense to the end user and closing Windows Explorer is generally not a good idea.  I don’t think the dialog is related to upgrading to Visual Studio 2010 but I still need to get rid of it.

At first I thought changing the MSIRESTARTMANAGERCONTROL property in the MSI would do work but that didn’t do anything.

After a bit more web-researching I found the File in Use Dialog exists in the Dialog table in the MSI.  What happened if I removed it?  You get error 2803: Dialog View did not find a record for the dialog.

Finally I noticed the Dialog table in the MSI has an attribute column.  The attributes control how the dialog is displayed and setting the attribute to zero solved my problem.  Now when doing an upgrade of Mini-Compressor the dialog is not displayed and the install completes successfully.  GO TEAM ME!

To automate the process I created a batch file that called both the MoveREP.js script I copied from the Connect bug report and the HideFilesInUse.js script I created.  Both files are listed below.  The batch file looks like:

cscript "%1HideFileInUseDialog.js" "%2"
cscript "%1MoveREP.js" "%2"

Then inside my VS Deployment project I set the PostBuildEvent to:

"$(ProjectDir)PostBuildEvent.bat" "$(ProjectDir)" "$(BuiltOuputPath)"

My smoke test installs are passing and hopefully my entire test plan passes with the new installer.  Wish me luck.

Appendix A: Orca

Orca is a tool from Microsoft to view and edit the tables of an MSI.  Technically you can only get it by downloading the large Windows SDK but I found just the Orac application here.

Appendix B: MoveREP.js

// MoveREP.js <msi-file>
// Performs a post-build fixup of an msi to run RemoveExistingProducts after InstallInitialize

// Workaround for a bug in VS2010 Setup projects that will remove the old version of Mini-Comp
// installed via the VS2008 MSI but not replace it with the new version.  You can read more at:
//
// https://connect.microsoft.com/VisualStudio/feedback/details/559575/problem-with-installing-and-removing-previous-versions-after-upgrading-my-setup-project-to-vs2010#details

// Where to move the RemoveExistingProducts to.  1525 is just after the
// InstallInialize action.
var newSequence = 1525;

// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyReplace        = 4

if (WScript.Arguments.Length != 1)
{
    WScript.StdErr.WriteLine(WScript.ScriptName + " file");
    WScript.Quit(1);
}

var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

var sql
var view
var record

try
{
    WScript.Echo("Updating the InstallExecuteSequence table...");

    sql = "SELECT `Action`, `Sequence` FROM `InstallExecuteSequence` WHERE `Action`='RemoveExistingProducts'";
    view = database.OpenView(sql);
    view.Execute();
    record = view.Fetch();

    if (record.IntegerData(2) == newSequence)
    throw "REP sequence doesn't match expected value - this database appears to have been already modified by this script!";

    if (record.IntegerData(2) != 6550)
    throw "REP sequence doesn't match expected value - this database was either already modified by something else after build, or was not produced by Visual Studio 2010!";

    record.IntegerData(2) = newSequence;

    view.Modify(msiViewModifyReplace, record);
    view.Close();

    database.Commit();
}
catch(e)
{
    WScript.StdErr.WriteLine(e);
    WScript.Quit(1);
}

Appendix C: HideFileInUseDialog.js

// HideFileInUseDialog <msi-file>
// Performs a post-build fixup of an msi to disable the File In Use Dialog.

// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyReplace        = 4

if (WScript.Arguments.Length != 1)
{
    WScript.StdErr.WriteLine(WScript.ScriptName + " file");
    WScript.Quit(1);
}

var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

var sql
var view
var record

try
{
    WScript.Echo("Updating the Dialog table...");

    sql = "SELECT `Attributes` FROM `Dialog` WHERE `Dialog`='FilesInUse'";
    view = database.OpenView(sql);
    view.Execute();
    record = view.Fetch();

    // Setting the dialog attributes to zero hides the dialog when the MSI
    // is running.
    record.IntegerData(1) = 0;

    view.Modify(msiViewModifyReplace, record);
    view.Close();

    database.Commit();
}
catch(e)
{
    WScript.StdErr.WriteLine(e);
    WScript.Quit(1);
}
Posted in Code Examples | Tagged , , , | Comments Off on Upgrading Mini-Compressor to .NET 4.0 Notes Addendum

Signed up for PayPal Micropayments

I just signed up for PayPal’s new Micropayments.  PayPal seems to be rolling this out slowly as you have to sign-up and then you will be notified in 2 days if you are accepted or not.  In theory it should save us a couple pennies every-time we sell a copy of Mini-Compressor.  The fixed cost per transaction is reduced from $0.30 to $0.05 but the percentage cost goes up from 2.9% to 5%.

If we are accepted I’ll post the before and after fees.  Actually, why don’t I tell you the current fees now.  For each copy of Mini-Compressor sold $0.52 to $0.59 goes to PayPal.  The amount changes depending if the customer has to pay GST (i.e. lives in Canada), the location of the customer (non USA and Canadian customers have a cross-boarder fee), and a possible currency conversion fee.  You can see a list of PayPal fees here.  Micropayments, as far as I can tell, still has all the fees listed above but with different rates.

So currently about 7% of each sale goes to PayPal.  With Micropayments this will hopefully drop to about 5.5% which is about $0.43.  It’s only a savings of ten cents or so but over time that can add up.

Posted in Business Side | Tagged , , | Comments Off on Signed up for PayPal Micropayments

Extra Memory for my Virtual Machine

All my development work is done on virtual machines (VM), Virtual Box to be exact.  In the past I’ve only needed one VM open at a time and only one version Visual Studio, or other IDE, running in the VM.  On my Core 2 Duo with 4 GB of RAM this was fine with the VM being allocated 1.5 GB of RAM.  Sometimes it would run slow but only for short durations and I could live with it.

My latest contract requires me to have two copies of Visual Studio open at the same time which brings my current setup to its knees, begging for death.  Actually, it’s begging for more memory so I bought some.

VirtualBox Main

With 8 GB of memory I can comfortably run a 2 GB Windows 7 VM for development along with running iTunes, Firefox, Word, and Visio on host without any issues.

Aside from upgrading my CPU the only other change I could make that would speed up running my virtual machines is getting an SSD hard drive.  Unfortunately they are very pricey if you want lots of storage but now they might be a reasonable alternative: hybrid hard drives.  I have my eye on the Seagate Momentus XT which has been getting good reviews.

Seagate Momentus XT

My big problem will be finding a day to reinstall everything.

Posted in Hardware | Tagged , | Comments Off on Extra Memory for my Virtual Machine

Coming… Later

A realistic video about software development:

Exclusive How the Gold Master Was Delayed: Part I

If, like me, you typically work on business software for a single large client, aside from (shameless plug) Mini-Compressor, then make the following substitutions:

Publisher –> Large Company  Buying Custom Software

Gold Master –> Release Date Promised to Customer Picked by Throwing Darts at a Calendar

Forum Troll –> Employee at Customer Company Trying to Fail Project for his/her Political Reasons

Posted in Fun, Software Development | Tagged , | Comments Off on Coming… Later

Upgrading Mini-Compressor to .NET 4.0 Notes

My notes on upgrading Mini-Compressor from .NET 3.5 to .NET 4.0 (Visual Studio 2008 to 2010) and also upgrading NUnit and NAnt.

1) Run the automated VS 2010 upgrade process.  Appears that there are no error but appearances can be deceiving.

2) Try a compile and get errors about not being about to find NUnit.  This makes sense as I upgraded NUnit on the build machine and the path had changed.  One day I should just reference the dll via a lib folder.  Update the NUnit reference and all the errors go away but…

3) Get some errors about  “The parameter to the compiler is invalid, ‘/define:=’ will be ignored.”.  After some digging find out the Compressor project contains the following in the “Conditional Compilation Symbols:

StreamReader reader = new StreamReader(project.Properties["install-proj-file"]);

That is weird but I delete it and try compiling again.

4) Only 2 warnings now and both related to the installer project.  First one is:

Build input parameter 'SupportUrl=www.saturdaymp.com' is not a web url or UNC share.

C:UsersthedudeDesktopMiniCompSourceMiniCompMiniCompInstaller32MiniCompInstaller.vdproj<em>

I wonder if I got that error in VS 2008?  I’m too lazy to check.  Add “http://” to the front of the url and error goes away.

5) One warning left, will this be the last warning?  One can hope.  The warning is:

The target version of the .NET Framework in the project does not match the .NET Framework launch condition version '3.5 SP1 Client'.  Update the version of the .NET Framework launch condition to match the target version of the.NET Framework in the Advanced Compile Options Dialog Box (VB) or the Application Page (C#, F#).

C:UsersthedudeDesktopMiniCompSourceMiniCompMiniCompInstaller32MiniCompInstaller.vdproj

So I go into all the projects and update the targeted version to .NET 4.0 Client Profile:

Set Target Framework

I also update the installer to use .NET 4.0 in the Prerequisites and Launch Conditions.  I added the Windows Installer 4.5 as well, might as well if we are upgrading everything else:

Prerequisites - .NET 4.0 Client Profile

Prerequisites - Windows 4.5 Installer

Launch Conditions for .NET 4.0 Client Profile

6) Try a recompile and get the same error.  Wait, it is slightly different.  It is complaining that one of the projects doesn’t target .NET 4.0 Client Profile:

The target version of the .NET Framework in the project does not match the .NET Framework launch condition version '.NET Framework 4 Client Profile'.  Update the version of the .NET Framework launch condition to match the target version of the.NET Framework in the Advanced Compile Options Dialog Box (VB) or the Application Page (C#, F#).

C:UsersthedudeDesktopMiniCompSourceMiniCompMiniCompInstaller32MiniCompInstaller.vdproj

Double check all the projects target framework values are set correctly.  Find out that my one C++ project also has a .NET target and it is set to .NET 4.0 but without the client project part:

Mini-Compressor C++ Target Framework

There appears to be no way in the GUI to change the target.  Wonder if VS 2008 C++ projects had a targeted framework and again I’m too lazy to check.  I also briefly wonder if this is a serious error or if Mini-Compressor would work fine even with the error.  I’m pretty sure my C++ project doesn’t use the .NET framework at all, it is a shell extension for the explorer context menu and .NET if not recommended for this.  Except now .NET 4.0 apparently plays nice with Shell Extensions.  I’ll have to investigate this further.  One change at a time.

Anyway, back on topic.  I decide to check with Mr. Know It All and after a couple tries find I can manually edit the project file to remove the warning.  More information can be found here and here.

First off notice that VS 2010 changed the C++ project file suffix from “vcproj” to “vcxproj”.  Not sure what the x is for, maybe extreme or 10?  Anyway, it’s a good thing I noticed this so I could add the new project file to source control and delete the old one.  Opening up the new and improved “vcxproj” file with Notepad I add the following to the Globals PropertyGroup section:

Updating the C++ Project File

Recompile and there are no errors.

7) Commit my changes and make sure I add the new C++ x-treme files.  Only the “vcxproj” file needs to be added.  The “vcxproj.filters” doesn’t need to be added.

8) Delete the unneeded C++ project files that where replaced by the xtreme versions.  The files I delete are:

– MiniCompShellExt.vcproj

– MiniCompShellExtPS.vcproj

– MiniCompShellExtps.def

Commit my changes.

9) Go eat some lunch.

10) Now it’s time to test the NAnt build script since we updated from 0.86 to 0.90.  Try running it and get errors about the C# script sections.  These sections do a find and replace on the version number and other files.  Getting errors about Regex not existing in the current context.

Read-up on the differences between the NAnt versions and find out that NAnt 0.90 no longer loads the System.Text.RegularExpressions namespace by default as shown in the script task documentation for 0.86 and 0.90.  To get around this problem I add both the reference and imports sections.  Both are needed, if you try just the imports, like I did at first, it dosen’t work.  The updated NAnt script looks like:

<script language="C#" failonerror="false">
  <references>
    <include name="System.dll" />
  </references>
  <imports>
    <import namespace="System.Text.RegularExpressions" />
  </imports>
  <code>
    ...
  </code>
</script>

11) Try a another build and get an error about the VS 2010 path.  Update the path and notice the NUnit path is also incorrect so I fix that as well.

<!-- Compiles Mini-Comp. -->
<target name="compile" description="Compiles the code.">
  <exec program="Devenv.com" basedir="C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDE">
    <arg line='/rebuild "${slnconfig}" "MiniComp.sln"' />
  </exec>
</target>

<!-- Run the NUnit tests. -->;
<target name="tests" description="Run the unit tests.">
  <exec program="NUnit-Console.exe" basedir="C:Program Files (x86)NUnit 2.5.7binnet-2.0" />
    <arg line='MiniComp.nunit /config:Release' />
  </exec>
</target>

12) Build again and it appears everything works.  Virtual high-five to me but just a small one as I have to test the build on the various versions of Windows.

Update (Sep 15, 2010):

13) The WPF OuterGlowBitmapEffect effect has been made obsolete.  This won’t show up as an error as the code is in the XMAL file bu the pretty glow effect around the thumbnail previews disappear.  To fix this problem you need to us the DropShadowEffect instead as outlined here.

The XAML code should look like:

<Image Name="displayImage" Grid.Column="2" Opacity="0" Width="97" Height="97">
  <Image.Effect>
    <DropShadowEffect ShadowDepth="0" Color="White" BlurRadius="30" />
  </Image.Effect>
</Image>

Update Nov 11, 2010: You can find an addendum here.

Posted in Notes | Tagged , , | Comments Off on Upgrading Mini-Compressor to .NET 4.0 Notes