C# Code Sample: Rendering images in Microsoft Excel

July 25th, 2010 No comments

You may have seen examples of pixel art in Excel like these examples here and here. The way this is done is by setting the background color of each cell of the worksheet just as you would set pixel colors in a graphics editor.

I always wondered how much work it would be to import photographic images into Excel this way. Our code would have to perform these basic steps:

  • Iterate over all lines of the image
  • Iterate over all pixels in each line of the image
  • Get the color of the currently iterated pixel
  • Set the background color of the worksheet cell with the currently iterated x/y coordinates to the color of the image’s pixel
  • Set the column width and row height of the worksheet cell so that it is approximately 1 pixel big
    As it turns out, you can do this with less than 30 lines of C# code:
            private const String _bitmapFile = @"C:\Users\Public\Pictures\Wallpapers\Photo.jpg";
            private const int xlAutomatic = -4105;
            private const int xlSolid = 1;
    
            private void ThisAddIn_Startup(object sender, System.EventArgs e) {
    
                try {
                    Application.ScreenUpdating = false;
    
                    using (Bitmap bitmap = (Bitmap)Bitmap.FromFile(_bitmapFile)) {
                        // Set row heights to 1
                        for (int y = 1; y <= bitmap.Height; y++) {
                            Application.ActiveSheet.Rows[y].RowHeight = 1;
                        }
                        // Set column widths to 0.1
                        for (int x = 1; x <= bitmap.Width; x++) {
                            Application.ActiveSheet.Columns[x].ColumnWidth = 0.1;
                        }
    
                        for (int y = 1; y <= bitmap.Height; y++) {
                            for (int x = 1; x <= bitmap.Width; x++) {
                                var color = bitmap.GetPixel(x - 1, y - 1);
                                var range = Application.ActiveSheet.Cells[y, x];
                                range.Select();
                                dynamic interior = Application.Selection.Interior;
                                interior.Pattern = xlSolid;
                                interior.PatternColorIndex = xlAutomatic;
                                interior.Color = ((int)color.B * 65536) + ((int)color.G * 256) + ((int)color.R);
                                interior.TintAndShade = 0;
                                interior.PatternTintAndShade = 0;
                            }
                        }
                    }
                }
                finally {
                    Application.ScreenUpdating = true;
                }
            }

    Simply create a new Excel 2010 Add-In project in Visual Studio 2010 and paste the above code over the ThisAddIn_Startup method stub. After you have compiled the project Excel will import the image file _bitmapFile on the next startup (give it some time).

Here’s a sample of what it looks like:

Image in Excel

I know it’s not very sophisticated but it was fun to do and I learned something about VSTO 2010. If you’re looking for some really cool stuff to do with Excel I recommend you check out this 3D rendering engine made with Excel.

Categories: .NET Code Samples

Building a WHS AddIn package using a (free) graphical authoring tool

June 4th, 2010 No comments

It’s been a while since Windows Home Server MVP Sam Wood published his excellent five-part WHS AddIn development tutorial over at the Tentacle Software Blog. His tutorial covers everything from setting up your development environment (using the free Visual Studio Express) to building your AddIn installation package (using the free WiX toolset).

The WiX (Windows Installer XML) toolset is a great tool for experienced Windows Installer package (MSI) authors but it comes with a steep learning curve. Unfortunately, Visual Studio Express does not contain support for creating setup projects. This feature is reserved for Visual Studio Professional and higher editions. If you want to create your MSI packages using a graphical tool you could of course do so by choosing tools from market leaders like InstallShield from Flexera or WISE Installer from Symantec, but these are quite pricey. A couple of weeks ago I stumbled across another tool for building MSI packages from a company called Caphyon Ltd. Its name is Advanced Installer and the best thing about it: it comes in a free edition that allows us to conveniently create our WHS AddIn Windows Installer package.

In this small tutorial I want to show you how you can package your Windows Home Server AddIn as a Windows Installer package (MSI) using the free edition of Caphyon Advanced Installer.

Step 1: Download and install Advanced Installer
Advanced Installer is small and lightweight. Simply download it from here and run the installation wizard.

Download Advanced Installer  Run the Advanced Installer installation wizard

Just click through the wizard and Advanced Installer will be set up in no time.

 

Step 2: Creating our installer project

Run Advanced Installer by finishing the installation wizard or from the shortcut the installer has placed on your desktop and you will be presented with the ‘New project’ dialog.

Advanced Installer new project dialog

As you can see, Advanced Installer supports a variety of project types for all your installation needs. Only the ‘Simple’ project type is available in the free edition but this is not a problem as it offers all the functionality we will need to build our WHS AddIn package.

When you select the ‘Simple’ project type and click OK the ‘New Simple Project’ wizard is launched.

'New Simple Project' wizard

First enter the name of your AddIn and your company name. This information will later be displayed in the WHS settings dialog’s available AddIns tab.

Next, select the name and location of your Advanced Installer project file (.aip), the name for your AddIn MSI package and the folder where the MSI package should be placed when it’s being created by Advanced Installer.

Wizard product information  Wizard file locations

Now point the wizard to the folder where your Visual Studio build output is located (your HomeServerConsoleTab.*.dll) and click ‘Finish’.

Wizard build output selection

 

Step 3: Fine tune the package settings
When the wizard finishes you’ll be brought to the ‘Product Details’ sheet of your setup project. Here you can enter the product version number of your AddIn. Please note that the Windows Installer format for version numbers is major.minor.build which differs from the usual .NET assembly version format (major.minor.build.revision).

Product Details

Use the navigation pane on the left to switch to the ‘Install Parameters’ sheet. Change the Application Folder to ‘[ProgramFilesFolder]Windows Home Server’. [ProgramFilesFolder] is a symbolic name for “C:\Program Files”. By using it in your application folder setting you can make sure that your AddIn will install properly on non-english versions of the operating system, where this folder is named differently (e.g. “C:\Programme” in German). You should also set the ‘Installation Type’ to ‘Per-machine only’ so only users with administrative privileges will be able to install the package (this is not absolutely necessary since the WHS console from where your AddIn is going to be installed from is running from the Administrator account, but still….).

Install Parameters

Now under ‘Properties’ click the ‘New’ button to fire up the ‘New Property’ dialog and enter ‘WHSLogo’ as your property name and ‘1’ as your value. This setting is required for WHS to recognize your MSI package as a valid AddIn installation package. When you’re done the ‘Instal Parameters’ sheet should look like in the second screen here:

New Property Dialog  Install Parameters

You can navigate to the ‘Upgrades’ sheet if you want to see what’s in there but since Windows Home Server does not make use of the automatic upgrade feature of Windows Installer for AddIns you should just leave the setting as it is.

Upgrades

On the ‘Launch Conditions’ sheet under ‘System Launch Conditions’ you should set the minimum Windows NT version to ‘Windows Server 2003 Service Pack 2’. This is the version of Windows Server that WHS v1 is based on and setting it as a requirement will prevent your users from accidentally installing your MSI package on their client machines. Since WHS v1 only comes as 32bit operating system you can disable the Windows NT 64-bit base version requirement.

If your AddIn targets .NET Framework 3.5 you can set it as the minimum .NET version on the ‘Software Launch Conditions’ tab. This way, installation of your AddIn will only be possible on WHS machines that already have .NET Framework 3.5 installed (version 3.5 of the .NET Framework is distributed to WHS via Windows Update so it should be ok to set this requirement).

You even can define your own launch conditions on the ‘Custom Launch Conditions’ tab but that’s beyond the scope of this tutorial. See this MSDN Library topic for more information about custom launch conditions.

System Launch Conditions  Software Launch Conditions

Step 4: Complete the package definition
Now it’s time to define the real contents of your MSI package. Go to the ‘Files and Folders’ tab and review the list of files that got imported by the project creation wizard. It automatically should have imported your HomeServerConsoleTab.*.dll and the subfolders containing localization satellite assemblies (if any). You can add additional files by clicking ‘Add Files’ on the toolbar or the context menu. Please make sure that this list does NOT contain any Microsoft assemblies from the WHS SDK like Microsoft.HomeServer.SDK.Interop.v1.dll and HomeServerExt.dll as these should NEVER be redistributed with your AddIn.

If you want your installer to add or modify registry keys you can define these on the ‘Registry’ sheet.

Files and Folders  Registry

Step 5: Building your MSI package
On the ‘Media’ tab’ you can review the output folder and MSI filename settings you made earlier in the project creation wizard (and modify them, if needed). All other settings are already correct and will result in the creation of a single MSI package, so that you don’t have to change anything here.

Media Settings

Now click ‘Build’ on the toolbar or the ‘Project’ menu and wait until Advanced Installer has finished building your MSI package.

Build project  Build finished

If everything goes well the build should finish successfully and you should be able to click the link to your MSI package in the log window of the ‘Build project’ dialog. This will take you directly to the folder where your MSI package has been written to. You can now copy the MSI package to the \Software\Add-Ins share of your WHS test box to install it from the WHS console settings dialog.

AddIn installation

Bonus Step: Build automation
If you want to create an up-to-date version of your MSI package every time you build your AddIn project in Visual Studio you’ll be happy to find that Advanced Installer supports build automation from the command line (if you don’t want to use this, just skip this step).

First, create a new .bat-file using Notepad (or whichever text editor you prefer) with this content:

cd /d "C:\Program Files\Caphyon\Advanced Installer 7.6.1\bin\x86"

set MSIPROJECT="C:\Temp\Sample WHS AddIn\SampleWHSAddIn.aip"

set MSIVERSIONFILE="C:\Temp\Sample WHS AddIn\Sample WHS AddIn\bin\Release\HomeServerConsoleTab.SampleWHSAddIn.dll"

advinst.exe /edit %MSIPROJECT% /SetVersion -fromfile %MSIVERSIONFILE%advinst.exe /build %MSIPROJECT%

 

Set the correct path of your Advanced Installer installation in the first line. The second line must contain the path to your Advanced Installer project file (.aip) as defined in Step 2 of this tutorial. In line three you specify the full path of the assembly that carries the version number you want to use for your MSI package (your main assembly).

The first call of advinst.exe will instruct Advanced Installer to take the version number of the assembly you specified and set it as version number of your installer project. The second and last call of advinst.exe will then build your installation package (MSI).

Now save this .bat file as ‘autobuild.bat’ (for example) and put the full path to ‘autobuild.bat’ into the ‘Post-build event command line’ box on the ‘Build Events’ tab of your AddIn project properties window in Visual Studio:

Build events

Now every time you build your project in Visual Studio the ‘autobuild.bat’ script will be executed and your MSI package will be recreated incorporating your latest code changes.

 

Conclusion
As you have seen it’s pretty easy to create a professional MSI package of your Windows Home Server AddIn using the free edition of Caphyon Advanced Installer. I personally like this way better than fiddling around with XML and WiX. Of course there’s nothing wrong with using WiX but it’s good to know that there are other free alternatives out there for your personal (and professional) MSI packaging needs.

I’ve been working with the market leading (and quite pricey) InstallShield Premier (which has its share of annoyances and bugs) for years and I have to say that Advanced Installer has the potential to shake up the market for professional Windows Installer package creation tools. For one, this is because it comes with an ingeniously simple user interface which helps you to define your package parameters very easily. Second, it contains some productivity tools like the condition editor with condition validation functionality (not covered in this tutorial) which can be real time savers and which professional MSI developers will love (I don’t want to make this sound like a rant towards InstallShield, but condition validation is an outstanding feature InstallShield still does not have after years in the marketplace).

Now have fun exploring Advanced Installer! Stay tuned for a version of this tutorial covering the package creation for Windows Server Codename ‘VAIL’.

Categories: Windows Home Server

How to deal with “Uninstallation failed” messages when trying to upgrade to the latest version of the Advanced Admin Console AddIn

April 29th, 2010 4 comments

Yesterday I released version 0.5.2 of the Advanced Admin Console AddIn for Windows Home Server. As always I noted that you should UNINSTALL any previous version before installing the latest release. If you tried to install the latest version over an existing installation of AAC, you may find yourself now in a situation where you can’t uninstall the previous version (getting “Uninstallation failed” messages from the console) and also can’t install the new release (getting “Please uninstall previous version first” messages from the installer).

Please follow these steps to fix this issue:

  • Establish a Remote Desktop Connection (RDP) to your server (if you don’t know how to do that, please see this short How-To).
  • On your server, go to control panel –> Add/Remove programs. Find the entry for the “Advanced Admin Console AddIn” and click “Remove” to uninstall it. If you are prompted to reboot your server, really REBOOT YOUR SERVER before installing AAC again.

You can now install the latest AAC version from the console.

It’s very likely that now both (old and new) versions of AAC are now listed as installed in the settings dialog:

duplicate_addin_entry

In order to clean up this mess you can use ASoft’s Addin Cleanup Tool. Download it and read the instruction from the Readme.txt (contained in the downloaded .zip file) carefully. You can use this tool to delete the orphaned addin entry for your previously installed AAC version (0.5.0 in this example).

Categories: FAQ

Advanced Admin Console AddIn: Version 0.5.2 now available for download

April 28th, 2010 12 comments

Version 0.5.0 Beta was released back in May 2009. Since then only one bug has been reported. So I think it’s time to remove the beta tag from the Advanced Admin Console.

This release fixes a bug which caused a console crash when AAC tried to load a corrupt custom link file (see this forum thread). Also the installer has been improved. It’s no longer possible to install AAC over an existing installation. In this case you now are prompted to uninstall any existing version first.

Download Advanced Admin Console AddIn Version 0.5.2 Beta.

CRC-32 5F6395D7
   MD5 505E4E3915CAFE96971ECCE9C3D38120
  SHA1 4757DF42CFDFF0EFDAE103F3BDFB08F2FD226AB4

Important: Before installing the new release, please UNINSTALL any previous version!

As always, feedback is welcome. See the support page on how to get in touch with me.

Categories: Windows Home Server

VAIL Dashboard improvements

April 28th, 2010 No comments

Windows Home Server Codename “VAIL” is the next version of Windows Home Server, now in public beta. Just like with the “Home Server Console” in the current version, it will feature a central place of administration. In order to emphasize the evolution the console has gone through it is now named the Dashboard.

As detailed in my AAC Feature Focus article back in January, the Home Server Console runs on the server itself and its user interface is displayed on a client computer over a remote desktop session. One disadvantage of this method is that the console window has a fixed size and any application that is launched from the console is trapped within the console window:

RegeditInWHSConsole  Regedit.exe run from the Advanced Admin Console on Windows Home Server

While the VAIL Dashboard is also running on the server the Dashboard client application now utilizes a new Remote Desktop Services feature called “RemoteApp”. RemoteApp integrates the Dashboard UI into the client’s desktop, thus creating a richer and more natural user experience:

RegeditInWHSDashboard  Regedit.exe run from the Advanced Admin Console on VAIL (Client’s Regedit in background)

As you can see, the Dashboard and the server’s Regedit window are not tied together, are fully resizable and they both appear on the client’s taskbar. Notice the contrast between the Windows 7/Server 2008 R2 window styles and the Windows XP desktop theme of the client while the Dashboard and its child windows are seamlessly integrated into the desktop.

Porting Advanced Admin Console to Windows Home Server Version 2 (Codename “VAIL”)

April 27th, 2010 8 comments

As of yesterday, the next version of Windows Home Server (Codename “VAIL”) is now in public beta. The new version brings a lot of improvements and feature enhancements. One area that has completely been overhauled in VAIL is the home server console, which is now known as the Dashboard. The extensibility model of Windows Home Server has been completely redesigned in “VAIL” so that all AddIns need to be ported to the new platform.

I have already begun porting the Advanced Admin Console AddIn to Windows Home Server “VAIL”:

AACforVail

There’s still a lot of work to do, but I hope that by mid-may I can put up a public beta version for download.

WHS Developer Tip: How to communicate between your SettingsTab and your ConsoleTab

April 8th, 2010 3 comments

As an avid Windows Home Server AddIn developer you probably followed the steps from the Windows Home Server SDK which explain how to implement your own console tab and a settings tab for the WHS console settings dialog.

Now when the user makes changes to the settings on your settings tab and ultimately clicks OK or Apply you may need a way to notify your console tab of the new settings.

settings_notify

The easiest way to accomplish this is by using a singleton object which provides the necessary means of communication:

public sealed class ChangeNotifier {
    public event EventHandler Changed;

    private ChangeNotifier() {
    }
    public static readonly ChangeNotifier Instance = new ChangeNotifier();

    public void Notify() {
        OnChanged(new EventArgs());
    }

    void OnChanged(EventArgs e) {
        EventHandler handler = Changed;
        // Make a temporary copy of the event to avoid possibility of
        // a race condition if the last subscriber unsubscribes
        // immediately after the null check and before the event is raised.
        if (handler != null) {
            handler(this, e);
        }
    }
}

Simple enough! Now we can access a common instance (the singleton) from everywhere in our code by calling on ChangeNotifier.Instance. Note: If you’re not familiar with the singleton design pattern you can read more about it in this Wikipedia article.

Now there’s two things left to do: First we need to subscribe to the ChangeNotifier’s Changed event in our console tab and second we have to call the Notify() method (which will fire the Changed event) from our settings tab when setting changes are committed.

Place this code in your console tab:

ChangeNotifier.Instance.Changed += new EventHandler(ChangeNotifier_Changed);

void ChangeNotifier_Changed(object sender, EventArgs e) {
    // TODO: Apply changed settings to your console tab here
}

And this line of code could be the last statement of your ISettingsTab.Commit() implementation:

ChangeNotifier.Instance.Notify();

This is pretty much it. Every time the user clicks OK or Apply on the settings dialog of the Windows Home Server your ISettingsTab.Commit() method is called where you now call Notify() on your ChangeNotifier singleton. This will raise the Changed event which will be handled by your event handler in your console tab (or any other class in your addin) so that you instantly can apply the settings changes the user has just made.

How to implement an update check in your Windows Home Server AddIn

March 21st, 2010 No comments

So you’ve written your Windows Home Server AddIn, made it available for download and are happy that people all over the world start using it on their Windows Home Servers. But shortly after you’ve put your work out in the wild users send you emails or start complaining on WHS related forums about weird behavior of your addin or WHS console crashes. You look at your code again, determine the culprit, fix the bug and compile a new version of your addin and put it in the download section of your website or blog. But how can you notify all users of older versions of your software about the availability of the new bugfix release? Of course the easiest way to do this is by having your addin check for available updates from time to time.

I want to show you the simplest form of an update check in less than 20 lines of C# code. Before we can have a look at the code we have to ask ourselves which steps are required to perform:

  1. Determine the version of our addin that is currently running
  2. Retrieve information about the latest version of our addin from the web
  3. Compare these two versions and decide whether the currently running version is outdated
    Step one is fairly easy: By the use of System.Reflection.Assembly we can determine the version of the assembly the currently executing code resides in like so:
    // Determine the Version of your addin by getting the assembly version
    // of the assembly that contains the code that's currently being executed.
    Version currentVersion = Assembly.GetExecutingAssembly().GetName().Version;

Before we can implement Step 2 we have to decide how and where we want to store the version information of out addin on the web. For this example we simply create a single-line text file (.txt) with the version number of our latest addin build:

image

Next we place this file on our web space so that our addin can retrieve it from there. For instance the URL to the file could be http://ourwhsaddin.com/OurAddInVersion.txt.

Now we can write the code that will download the version information file and parse its contents:

// URL of the file containing the version number of the latest available
// version of your addin
String versionURL = "http://ourwhsaddin.com/OurAddInVersion.txt";

// Prepare the HttpWebRequest object for downloading the version information
// file
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(versionURL);
// Set the current addin + version number as user agent so that
// the web server logs it as the "user's browser"
req.UserAgent = "My WHS AddIn Version " + currentVersion.ToString();
// Set the cache policy so that the version informatin file is always
// downloaded and not retrieved from the local cache.
req.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
// Get the version information file by executing the web request
WebResponse resp = req.GetResponse();
Version availableVersion;
using (StreamReader sr = new StreamReader(resp.GetResponseStream())) {
    // Read and parse the version information
    string availableVersionString = sr.ReadLine();
    availableVersion = new Version(availableVersionString);
    sr.Close();
}

As you probably know web servers usually log all activity for hosted content like client IP addresses, users’ web browsers (= User Agent) locations of accessed files and so on. If you want to be able to determine which versions of your addin are performing update checks you can set the addin name and current version as user agent (see above) and you will find this information in your server logs.

The code above is pretty self-explanatory (I think). We create System.Net.HttpWebRequest object from our version file URL, set the user agent string and cache policy and execute the request by calling GetResponse() on it. We then set a System.IO.Streamreader on the response stream and read the first (and only) line from the stream (= our version information file). The next step is to convert the version string into a System.Version object by creating a new System.Version object passing the version string to the constructor.

So we have the version of our currently running code in currentVersion and the version of the latest available release in availableVersion. Our last step (Step 3) is to compare these two in order to determine whether the latest release is newer than what’s currently running:

if (availableVersion > currentVersion) {
    // A new version is available for download

}

Tadaa! That’s it! Of course you’d have to do proper exception handling which I omitted from the example in order to make the code look simple and clean.

Like I said this is the most basic form of an update check mechanism. Instead of downloading a simple text file we could set up a web service and submit more information about the current addin version when we call it. But be sure that you respect the user’s privacy, when doing this! We could also include the download URL and version history in the text file (or the web service response) and display it to the user when we notify them about the availability of an update. The possibilities are endless!

While it’s a nice feature to get update notifications I believe it would be best if the operating system would handle this and users would have a central place where they can go to update their software. However, Windows Home Server does not have such a place but the upcoming AddIn Central from HomeServerLand looks very promising and I hope that it will become this central place of addin administration.

UPDATE:

I just got notified by Björn Bürstinghaus that they are still looking for beta testers for the german version of AddIn Central. If you speak german and want to participate in the beta please visit http://blog.buerstinghaus.net/add-in-central-beta-fur-den-home-server/ and leave a comment. You’ll then be contacted by the AddIn Central team via email.

Advanced Admin Console popularity

March 20th, 2010 No comments

As you probably know, the Advanced Admin Console AddIn (AAC) checks for available updates from time to time by querying a webservice. In order to get an idea of how many people are actually using AAC I did some statistical analysis on the web server’s logs and here are the overwhelming results:

image

AAC is being used in 53 countries and by almost 13,500 people in the United States, Germany and the United Kingdom alone.

Countries with < 0.5 % of installations are filed under ‘Other’. These are (in order of number of installations): New Zealand, Spain, Portugal, Greece, Finland, Italy, South Africa, Ireland, Poland, Hungary, Brazil, Czech Republic, Slovakia, Luxembourg, Israel, Slovenia, Croatia, Iceland, Ukraine, Lithuania, Argentina, Romania, Turkey, Estonia, Zimbabwe, Bulgaria, Mexico, Malaysia, Latvia, Peru, Venezuela, Chile, Dominican Republic, Serbia and Montenegro, Bolivia, Republic of the Philippines, Jamaica, Kuwait, El Salvador

Woohoo!

Categories: Windows Home Server

Win a copy of the infamous book “Mommy, Why is There a Server in the House?”

March 9th, 2010 No comments

It’s been a while since Microsoft started their Stay-At-Home Server marketing campaign for Windows Home Server. Part of this campaign was the release of the tongue-in-cheek children’s book “Mommy, Why is There a Server in the House?”. It even was available for purchase at Amazon.com.

Mommy_3 I happen to have a spare copy of the book to give away to one of you Windows Home Server users/enthusiasts. All you have to do is send me your story about how you’re using one of my addins (Advanced Admin Console, Update History, FRITZ!Box Anrufliste) explaining which use you get out of them and how they make your lives with your Windows Home Server easier. The best story will be published on this blog and the author will be given the brand new (paperback) copy of the “Mommy book” (free shipping worldwide!).

The winner will be drawn on March 16th, 10:00 pm (Germany time, GMT+01:00).

Use the contact form to send me your story (don’t forget to include your full address). The lucky winner will be announced on this blog and via Twitter, so make sure to subscribe to my blog’s RSS feed and follow me on twitter so that you won’t miss it.

Good luck!

 

Update: Since I did not receive any user stories from you there’s no winner to announce.

Related Posts with Thumbnails
Categories: Windows Home Server