Codoxide Library | Updates and New Home
 

by Sameera on November 15, 2008 21:08

I have made several updates to the Codoxide.Common Library and moved the project over to SourceForge.net.

The project's new home is codoxidelib.sourceforge.net and the new SVN repository is https://codoxidelib.svn.sourceforge.net/svnroot/codoxidelib/trunk

Codoxide.Common Library Version 0.0.1 (Concept Phase): Database Wrapper, Basic Design Patterns, Configuration Handlers
 

by Sameera on October 20, 2008 11:18

Today I'm so excited to announce the first release of the Codoxide.Common Library. High Five! I haven't been over ambitious about the version numbering as I want you to treat this library to still be in concept stage.   Codoxide.Common Library Released

Unfortunately, this release had taken longer than expected cos of my newly cramped up schedule. Worst part of that is I'm posting this code without proper documentation (yep, excuses!). Nevertheless, there's plenty of code in here to prove useful to many. So here goes!

Features/Components

Patterns

  • SharedInstance<T>
  • Singleton<T>
  • Factory e.g. Factory.Build<T>()

Configuration

  • ConfigurationManager<T>
  • ConfigurationSectionBase

Data

  • Database<CONNECTION_TYPE, COMMAND_TYPE, ADAPTER_TYPE>
  • Map<T>

 

SharedInstance<T>

SharedInstance is actually the most basic type of generic Singleton implementation that's been around in the C# community. This implementation was both simple and efficient. But, it violated the definition of a Singleton by depending on the presence of a public constructor and thereby allowing additional instances to be created. Therefore, I have refrained from calling this a Singleton resorted to the term SharedInstance.

E.g:

[code:c#]
SharedInstance<User>.Instance.Login("admin", "password");

User employee1 = new User();
employee1.Username = "emp001";
employee1.Password = "pass001";
employee1.Save();
[/code]

Singleton<T>

More advanced implementation of the generic Singleton implementation. Uses reflection, custom attributes and "lazy initialization" to provide a powerful way to create and initialize your singletons.

E.g:

[code:c#]
public class UserPreferences : IXmlSerializable, ISupportLazyInitialization
{
    ..

    public virtual void Initialize()
    {
        try
        {
            string location = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Codoxide\\preference.xml";
            if (File.Exists(location))
                using (XmlReader reader = XmlReader.Create(location))
                {
                    reader.ReadToFollowing("Preferences");
                    this.ReadXml(reader);
                    reader.ReadEndElement();
                }
        }
        catch (Exception ex)
        {
            throw new InvalidConfigurationException("Exception occurred while loading the preferences from disk", ex);
        }
    }
    ..
}

...

Console.WriteLine(Singleton<UserPreferences>.Instance.BackgroundColor);
[/code]

Factory.Build<T>

This one's another powerful and unique implementation. Coolest feature of this class is that you can do something like the following:

[code:c#]
using (IDatabase db = Factory.Build<IDatabase>())
{
    ..
}
[/code]

This allows developers of class libraries to write their code using interfaces or abstract classes, leaving the library users to specify the concrete classes via configuration files.

Grab the Code

There's of course, plenty more to be documented regarding the library. And you can expect the project space to be updated in coming (err..) weeks Wink.

Until then, you can:

Check out the code (using SVN): https://codoxidelib.svn.sourceforge.net/svnroot/codoxidelib/trunk

Browse the project space: http://codoxidelib.sourceforge.net/

VSTO App Deployment using NSIS - Part 2
 

by Sameera on May 21, 2008 02:28

Detecting and Deploying Prerequisites

This is the 2nd of a multi-part series on deploying VSTO Applications using NSIS. Part 1 of the series can be found here.

Step 4: Ensuring MSI 3.1 is available

Before proceeding you need to make sure the client computer has MSI 3.1 installed. Click here to find out how.

Step 5: Checking whether Excel is Installed

Being an Excel Worksheet-Level Customization, it makes no sense for this app to be deployed on a computer that doesn't have MSO Excel 2003 Professional installed. Lets see how we can achieve this. If you do a bit of research you can find out that with VS Deployment Projects, this is achieved by doing a Windows Installer search for the component ID {A2B280D4-20FB-4720-99F7-40C09FBCE10A}.

Since performing a Windows Installer Search is a common and desirable feature, I came up with the following macro:

!macro GenerateMsiSearch functionName componentId
    Function ${functionName}
        Push $0
        Push $1
        StrCpy $0 ""
        StrCpy $1 ""
        System::Call "msi::MsiLocateComponent(t '${componentId}', t, *i) i .r1"
        DetailPrint "Component ID: ${componentId} Install State: $1"
        ${If} $1 == '3' ; installed on local drive
            StrCpy $0 '1'
        ${ElseIf} $1 == '4' ; run from source, CD or net
            StrCpy $0 '1'
        ${ElseIf} $1 == '-3' ; Path  to the component returned more data than our buffer can handle. Which means we do have this installed.
        ${Else}
            StrCpy $0 '0'
        ${EndIf}
        Pop $1
        Exch $0
    FunctionEnd
!macroend

When invoked, this macro will generate a function, with the give name that will search for the specified Component ID. So the code to detect Excel 2003 becomes:

!insertmacro GenerateMsiSearch "IsExcelInstalled" "{A2B280D4-20FB-4720-99F7-40C09FBCE10A}" ; Version 2003

Section "MainSection" SEC01
    ; Determine whether the user has the required version of Excel installed
    Call IsExcelInstalled
    Pop $0
    ${If} $0 == '0'
        MessageBox MB_OK "A compatible version of Microsoft Office Excel was not found. Setup cannot continue."
        Abort
    ${EndIf}

[/code]

So, why did I make this a macro that generates a function, and not just a function that accepts the component ID as a parameter? Well, parameter passing is not that straight forward with NSIS, and I believe this leads to much cleaner code at the end.

Step 6: Ensuring .NET 2.0 Runtime is Present

You can find plenty of ways to do this on NSIS web site. Here's one of them.

Step 7: Ensuring VSTO is Present

!insertmacro GenerateMsiSearch "IsVstoInstalled" "{D2AC2FF1-6F93-40D1-8C0F-0E135956A2DA}"

Function InstallVSTOSE
    ; ${DirState} '$COMMONFILES\Microsoft Shared\VSTO\8.0' $1
    Call IsVstoInstalled
    Pop $0
    ${If} $0 == '0'
        SetOutPath '$TEMP'
        SetOverwrite on
        Banner::show /NOUNLOAD "Microsoft VSTO SE..."
        File 'C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\vstor\vstor.exe'
        ExecWait '$TEMP\vstor.exe /q:a /c:"install"' $1 ; '$TEMP\vstor.exe /q:a /c:"install /q"' $1
        Delete '$TEMP\vstor.exe'
        Banner::destroy
        ${If} $1 == '0'
            DetailPrint "VSTO 2005 SE was installed successfully."
        ${ElseIf} $0 == '3010'
            SetRebootFlag true
        ${Else}
            DetailPrint 'VSTO 2005 SE Installation failed with error $1'
            Abort
        ${EndIf}
    ${Else}
        DetailPrint 'VSTO 2005 SE already installed.'
    ${EndIf}
FunctionEnd

We now have the scripts in place to deploy the application components as well as the to determine all prerequisites are available. All that is left is to add the boiler place Update Manifest and Set Security code. Easiest way to do this is to bring the code over a new .NET EXE project and pass the installation-dependent (e.g. Installation Path etc.) parameters as command line arguments. You can then execute the EXE as the last step of the installation.

Tags: , , ,

Filed Under: Code Snippets | Projects

VSTO App Deployment using NSIS - Part 1
 

by Sameera on May 20, 2008 06:49

For a little over a year, we’ve been working on a very sophisticated Microsoft Excel 2003 Document Level Customization project. We have nothing but pride towards the ingenuity of this application. But, there was one aspect that consistently overshadowed its success: Deployment.

Visual Studio Deployment Projects help you generate a setup app quickly and easily. It has the ability to look up source projects and determine all the components that need to be deployed. This makes things remarkably easy when you want a rudimentary installation. But, for anything out of the ordinary,  you will find that this offers you very limited help. To workaround these limitations you have to pick up a tool called Orca. Now, here’s where things get really dirty.

To use Orca, you have to have some semblance of the MSI database format. That isn’t actually so bad. A simple search on the Internet will fetch you loads of information regarding the subject. But, figuring out the format is just the beginning. You then have to weed your way using some ugly hacks. That's not all; you have to reapply those hacks with each build. If you are willing to live with the inconveniences, there's still a lot you can achieve using Orca. Musical Nerdery has a neat example on the subject.

Anyway, the point is we got sick and tired of working within these constraints and started looking for alternatives. After some serious considerations we opt to go with NSIS (Nullsoft Scriptable Installer Suite). We were mostly excited about its low footprint and its powerful scripting language.

This post is the first of a series in which I'm going to guide you through the steps involved in migrating your existing VSTO deployment package to NSIS. Before we begin, I should point out a few of the downsides to using NSIS.

  1. NSIS doesn't understand VS Projects. It cannot scan through your projects and determine which components are relevant. You have to figure out all the files/dependencies you must deploy on to the client PC. Easiest way to do this is by creating a VS Deployment Project and let it tell you which files you need.
  2. It cannot perform automatic rollbacks. If you want the user to be able to cancel the installation midway (after some files have already been deployed), you have to roll back the installation yourself using scripts. I'd argue that this is only a minor concern.

Since basic tutorials on NSIS scripting are widely available, I'm going to skip over the basics. You can learn about them here if you need to.

Step 1: Add a Visual Studio Deployment Project to your VSTO Solution

For the purpose of this tutorial I'll be using a really simple Excel 2003 Document Level Customization project called NsisDemo. All it does is display a message box saying "NSIS Rocks!!!" You can download it here or use your own VSTO project and include a VS Deployment Project as I have done.

Step 2: Begin your NSIS Script

Now, fire up your favorite text editor. I tend to prefer Notepad++ which offers syntax highlighting for NSIS scripts. Create the basic skeleton of a NSIS script in a sub folder of your main solution folder. If you need help getting started check out HM Nis Edit to generate a script for you, or use this one: Sample NSIS Start Script (2.4KB).

Step 3: Include Files that will be Copied to Client Machine

Open your VS Deployment Project. Go to the File System Editor and take a look at the file list under Application Folder.

VSDeploymentPrj_FSE_AppFolder

Lets go ahead and add these files to our script. You'd need to modify the main installer section as well as the uninstaller section.

[code:c#]

Section "MainSection" SEC01
    File "..\NsisDemo\bin\Debug\NsisDemo.xls"
    File "..\NsisDemo\bin\Debug\NsisDemo.dll"

    ; Following lines are shortened for better display
    File "C:\WINDOWS\assembly\GAC\..\Microsoft.Office.Interop.Excel.dll"
    File "C:\WINDOWS\assembly\GAC\..\Microsoft.Office.Interop.SmartTag.dll"
    File "C:\WINDOWS\assembly\GAC_MSIL\..\Microsoft.Office.Tools.Common.dll"
    File "C:\WINDOWS\assembly\GAC_MSIL\..\Microsoft.Office.Tools.Excel.dll"
    File "C:\WINDOWS\assembly\GAC\..\Microsoft.Vbe.Interop.dll"
    File "C:\..\Microsoft.VisualStudio.OfficeTools.Controls.ManagedWrapper.dll"
    File "C:\..\Microsoft.VisualStudio.Tools.Applications.Runtime.dll"
    File "C:\..\Microsoft.VisualStudio.Tools.Applications.Runtime.tlb"
    File "C:\WINDOWS\assembly\GAC\..\office.dll"
    File "C:\WINDOWS\assembly\GAC_MSIL\..\VSTOStorageWrapper.Interop.dll"
SectionEnd

Section Uninstall
    Delete "$INSTDIR\NsisDemo.xls"
    Delete "$INSTDIR\NsisDemo.dll"
    Delete "$INSTDIR\uninst.exe"
    Delete "$INSTDIR\VSTOStorageWrapper.Interop.dll"
    Delete "$INSTDIR\office.dll"
    Delete "$INSTDIR\Microsoft.VisualStudio.Tools.Applications.Runtime.tlb"
    Delete "$INSTDIR\Microsoft.VisualStudio.Tools.Applications.Runtime.dll"
    Delete "$INSTDIR\Microsoft.VisualStudio.OfficeTools.Controls.ManagedWrapper.dll"
    Delete "$INSTDIR\Microsoft.Vbe.Interop.dll"
    Delete "$INSTDIR\Microsoft.Office.Tools.Excel.dll"
    Delete "$INSTDIR\Microsoft.Office.Tools.Common.dll"
    Delete "$INSTDIR\Microsoft.Office.Interop.SmartTag.dll"
    Delete "$INSTDIR\Microsoft.Office.Interop.Excel.dll"
    RMDir "$INSTDIR"

    DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
    SetAutoClose true
SectionEnd

[/code]

Note that all the non-user files (files other than NsisDemo.xls and NsisDemo.dll) are part of the Office 2003 PIAs. You might chose to deploy these files properly using the PIA installer. But, for now lets keep things simple and stick to copying them to the install directory.

At this point you may compile the script to generate an executable installer file. However, the VSTO application deployed through it will fail at run time as there are lot more missing pieces we need to stitch in to it.

Up next: Part 2

Tags: , , ,

Filed Under: Code Snippets | Projects

BreadCrumbs Control: Final Touches and Demo Project
 

by Sameera on February 15, 2008 21:08

After weeks of inactivity, I finally managed to get a demo project in place for the BreadCrumbs controls. You can download it here. The code includes few updates I have made since the last version. For the sake of flexibility, I have kept the basic control as simple as possible. In the demo, I have added few additional helper classes to provide the full functionality desired.

Extending the control is pretty simple too. For instance, to display the menus for each of the sub items in a list item, you handle the SubItemClicked event. The SubItemClickedEventArgs passed to you along with this event provides you with the row index, column index and the bottom-left corner pixel coordinates of the sub item. In the demo app, this event handled as;

[code:c#]
void ListBox_SubItemClicked(object sender, BreadCrumbsListBox.SubItemClickedEventArgs e)
{
    ContextMenuStrip menu = null;
    if (e.ColumnIndex == 1 && breadCrumbsList.ListBox.SelectedItem != null)
        menu = GetTemplateMenu(breadCrumbsList.ListBox.SelectedIndex);
    else
        menu = _entityMenu;
    menu.Show(breadCrumbsList, breadCrumbsList.PointToClient(e.BottomLeftCorner));
}
[/code]

Here, the _entityMenu is a pre-constructed menu while as the "Template Menu" is reconstructed every time based on the selection.

About Me

Sameera Perera

Sameera Perera

Log in

RecentComments

Comment RSS

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

Archive

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

All forms of source code published on Codoxide.com are distributed under the Apache License, Version 2.0 unless otherwise stated.
The rest of the content are published under a Creative Commons Attribution 3.0 License.
Creative Commons License

CodoxideTM

Copyright © 2010  codoxide.com. All rights reserved. Designed by Sameera Perera