Monday 7 December 2009

An error occurred while validating. HRESULT = '80004005'


You may have received this error when compiling a setup project within visual studio...

Roughly translated, this error message means "Cannot built setup, dependent project is missing, missing a reference or a referenced file for a project cannot be found."

For example, add a project output to the setup file, and apply one of the content files to the setup (I.e. use an icon for the add/remove programs icon). Remove the project out, then re-add it. Visual studio will then give you this error (despite the project output being in there!!)... Everytime an output is removed, you must re-reference all of the dependencies.

If it is not this specific issue, then there is something wrong with your projects. Look up the projects' references and see if they are all correct. Try to compile the projects as well, this is a good indication that you aren't adding projects with errors to your set-up!

Adding a project/installer to VSS (where you want it to go!)


If you have a solution in visual studio, its probably made up of many relationships and dependencies. If the solution isn't source controlled immediately, you might run into a couple of issues putting it in Visual Souresafe (VSS) exactly where you want it to go.
The same goes for installers, and adding new installers to an existing source controlled solution.

The key is to add it to VSS before dependencies are added... otherwise, it'll pick up the fact that its above the binding root of the solution, and put it inside the folder you want, but inside two child nodes down; or something silly like that.

So the best way is to remove dependencies, or source control it before they are added!

Friday 4 December 2009

Attach a database file to SQL Server


If you have a SQL Server Database file (.mdf) and the associated logfile (.ldf), you can attach this manually to an SQL Server database.

Here's a Microsoft link explaining the process:

BackgroundWorker - Handling Exceptions


Today i've been using Background Workers in visual studio and came to a bit of a fix when I needed to throw an expcetion within the DoWork event of the worker.

Normally, you would expect to throw exceptions as usual, but due to the nature of how the worker handles exceptions; this is done a little differently...

The worker automatically handles exceptions and passes them as an argument to the RunWorkerCompleted event. From the developers perspective, you just need to throw them within the DoWork event.
In the RunWorkerCompleted event, the RunWorkerCompletedEventArgs object contains an "Error" property. Simply test for null here to know weather an error has occurred... here you can catch your exception!

Thursday 19 November 2009

DIV Layout with CSS (Table vs. DIV Layout)


Here is a nice article explaining the differences between HTML table and DIV based layouts. It gives examples of each and how to move forward with DIV based layouts.

http://www.devarticles.com/c/a/Web-Style-Sheets/DIV-Based-Layout-with-CSS/

Add User Controls to an ASP.NET page


Heres an artircle on how to add a user control to an ASP.NET page, its quite informitive and details all of the necessary steps

http://msdn.microsoft.com/en-us/library/5d0t5fak(VS.71).aspx

Friday 13 November 2009

onclick vs. onmousedown and onmouseup


I've been trying for the last couple of hours as to why I couldn't select a row in my GridView using right click... it seemed to work fine for left click, but right click had issues (I had my attribute for the row set to 'onclick')

What I was doing so making a context menu appear, but I wanted the row to select itself before the menu appeared. After many vain attempts of simulating left click behaviour, adding pointers to the left clicks behaviour into the code... I simply changed the attribute to onmouseup, and presto! it works!

strange, but I do recall when attemping to disable right clicks on webpages, the onmousedown/up event is captured, so it must be how the browser interprets the keypresses for each.

Thursday 29 October 2009

WPF - StaticResource vs. DynamicResource


Static resources are resolved at compile time, whereas dynamic resources are resolved at runtime.

Use DynamicResources when the value of the resource could change during the lifetime of the Application.

Use StaticResources when it’s clear that you don’t need your resource re-evaluated when fetching it – static resources perform better than dynamic resources.

Monday 14 September 2009

ASP.NET - VIEWASTEXT Attribute


If you have a control on an ASP.NET page and Visual Studio is having trouble rendering it in design view, then you can add the VIEWASTEXT attribute to the tag, and visual studio will then render this as text.

Example:
<object id=factory style="display:none"
classid="clsid:1663ed61-23eb-11d2-b92f-008048fdd814"
  codebase="smsx.cab#Version=6,5,439,30 VIEWASTEXT>

    <param name="template" value="MeadCo://IE7" />
</object>

Friday 11 September 2009

Error MSB4019: The imported project "C:\Microsoft.CSharp.targets" was not found.


If you've received this error, it usually means that the targets file can not be found/identified by the current versiuon of visual studio....

I usually receive this error when attempting to import a .NET 3.5 project into a .NET 2.0 solution.

To tackle this particular scenario, you will need to open the project file (.csproj).... and if you wish to make the project .NET 2.0 ready, you will need to find the following line (specific to 3.0/3.5)...


<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

and replace with...

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

Thursday 10 September 2009

Visual Studio Debug Problem (Debugger Detaching)


During the development of an ASP.NET application, have you ever had the debugger randomly detach itself from the IE instance?

This is usually because VS gets confused regarding which isntance of IE to detach itself to... goto into Task Manager and see if there are any iexplore processes running that do not have a window handle. If so, end them and re-try...

If not, take a look at this post regarding new features introduced with IE8 that can cause this issue...

http://weblogs.asp.net/abdullaabdelhaq/archive/2009/06/01/VS-Debug-Problem-with-IE8.aspx

Friday 4 September 2009

C# Conditional Operator ( ?: ) and Null-Coalescing Operator ( ?? )


Often times in code you want to assign one variable to another, but only if the variable is not null. If it is null, you want to populate the target variable with another ( perhaps default ) value. The code normally may look like this using the C# Conditional Operator:

string fileName = tempFileName !=null ? tempFileName : "Untitled;
 

If tempFileName is not null, fileName = tempFileName, else fileName = “Untitled“.


This can now be abbreviated as follows using the Null-Coalescing Operator:

string fileName = tempFileName ??"Untitled";

The logic is the same. If tempFileName is not null, fileName = tempFileName, else fileName = “Untitled“.


The Null-Coalescing Operator comes up a lot with nullable types, particular when converting from a nullable type to its value type:

int? count = null;
 
int amount = count ?? default(int);

Since count is null, amount will now be the default value of an integer type ( zero ).

These Conditional and Null-Coalescing Operators aren't the most self-describing operators :), but I do love programming in C#!

Thursday 3 September 2009

C# - Difference between 'out' and 'ref'


When passing objects as parameters to functions, there may be a certain scenario where you wish to modify a parameter before a function call, modify its valur within the function, and retain its value after the function call... This example behaviour describes the actions of the 'ref' qualifier to a function argument. 'out' however, is quite similar...

ref qualifier
When passing an object to function, specifying it as ref requires the object to be initialised beforehand. You can then modify its value inside the function and continute to use the object once the function call has ended.

Example
        private void ModifyByFive(ref int number)
        {
            number += 5;
        }


out qualifier
When passing an object to function, specifying it as out does not require the object to be initialised beforehand. However, the object can then be modified for this purpose within the function, and can be used outside the function once the function has executed. This can be treated as an 'extra return value'. However, using too many out parameters might require an architectural re-think; as a class or struct might prove more benificial.

Example
        private void ModifyByFive(out int number)
        {
            number += 5;
        }


Tuesday 1 September 2009

Registering a DLL as an MSI Custom Action


1. In Visual Studio, open your solution and right click on the setup project. Select "View" and then select "Custom Actions".

2. Select a custom action for which you which to register the DLL, this would usually be "Install".

3. Right Click on the Install directory and select "Add Custom Action".

4. You will then need to add a script which will be run as part of the MSI installation process. For this, we will use VB Script. Paste the below code into Notepad and save it as a VB Script (.vbs) file.

REGISTER DLL VB Script
Dim WshShell
Set WshShell = CreateObject("Wscript.Shell")
WshShell.run "regsvr32 /s DLLFILENAME.dll"
Set WshShell = nothing

5. Add this to your project and reference it as a custom action for your "Install" process.

6. You may wish to unregister the DLL file during the uninstall phase. Perform the previous processes which the uninstall VB Script below...

UNREGISTER DLL VB Script
Dim WshShell
Set WshShell = CreateObject("Wscript.Shell")
WshShell.run "regsvr32 /u/s DLLFILENAME.dll
Set WshShell = nothing

Wednesday 26 August 2009

"The path is not of a legal form."


If you attempt to open your project (standard windows application) and the designer gives you a similar error to the one below....

"One or more errors encountered while loading the designer. The errors are listed below. Some errors can be fixed by rebuilding your project, while others may require code changes."


The the problem is that the form's designer is trying to locate one of the types referenced by your form and is unable.
This means that your project probably wasn't built since the reference was added or that the project file has somehow been changed.

If building the solution doesn't work, try going over the references in the project and looking at where their locations are and verifying that they all actually exist.

UML relationships


I've had this post-it note on my desk for a while now, its a nice nudge in the right direction if you havent done any UML for a while.


Stop Postback in .NET


For example, if i had an ImageButton object and I would like some Javascript to execute upon clicking this control, I would add the JS on code behind like so...


btnViewParts.Attributes.Add("OnClick","ViewParts(); return false;");

The return false; Portion of this code prevents the postback.

Tuesday 25 August 2009

T-SQL vs. PL/SQL


Here are some of the differences between Oracle's PL/SQL and SQL Server's T-SQL.

OracleSQL ServerMore Information
%TYPE data typeNo equivalent

The %TYPE data type of Oracle, lets you create a variable and have that variable's data type be defined by a table or view column or a PL/SQL package variable.

There is no equivalent for Oracle's %TYPE datatype in T-SQL, but it can be simulated (not very conveniently though) using User Defined Data types (UDT). Here is an example:

EXEC sp_addtype 'MyType', 'smallint', NULL

CREATE TABLE MyTable (i MyType)

CREATE PROC MyProc
AS
BEGIN
DECLARE @i MyType
END

BEFORE triggersINSTEAD OF triggers

Use INSTEAD OF trigger in SQL Server as an equivalent to Oracle's BEFORE trigger.

For more information on INSTEAD OF triggers, see SQL Server Books Online

DECODE() functionCASE expression

DECODE can be conveniently simulated using the T-SQL CASE expression. Here's an example:

SELECT Sport,
CASE Sport
WHEN 'Cricket' THEN 'England'
WHEN 'Hockey' THEN 'India'
WHEN 'Base Ball' THEN 'America'
ELSE NULL
END AS 'Originating Country'
FROM Sports

DESCRIBEsp_help or sp_columns

There are a lot of alternatives for Oracle's DESCRIBE, in SQL Server. You could use the system stored procedure sp_help for detailed information about a table's columns and other properties.

If sp_help is providing you with too much information, then try the ODBC catalog stored procedure, sp_columns.

There are a bunch of other useful sp_help* stored procedures available in SQL Server. You can find more information about those in SQL Server Books Online.

If none of those procedures are suitable for your requirements, then you could query the system view INFORMATION_SCHEMA.COLUMNS, to get the desired information. You could wrap your code inside a stored procedure named DESCRIBE, if you wish.

As a last resort, you could even query system tables like sysobjects and syscolumns, but this is not a recommended approach.

DUAL tableNo equivalent

There is no DUAL table in SQL Server. In fact, you don't need one in SQL Server, as you can have a SELECT statement without a FROM clause.

For example, consider the following SELECT statement in Oracle:

SELECT 'Something'
FROM DUAL

In SQL Server, the same result can be obtained by the following command:

SELECT 'Something'

If you are porting some code from Oracle into SQL Server and if you don't want to remove all references to DUAL table, then just create a DUAL table in your database using the following commands:

CREATE TABLE DUAL
(
DUMMY varchar(1)
)

INSERT INTO DUAL (DUMMY) VALUES ('X')

INTERSECT operatorNot supported

Use EXISTS clause to generate the same result.

The following example illustrates the simulation of Oracle's INTERSECT operator:

SELECT OrderID, OrderDate
FROM Orders O
WHERE EXISTS
(
SELECT 1
FROM RefundsTable R
WHERE O.OrderID = R.OrderID
)

MINUS operatorNot supported

Use NOT EXISTS clause in your SELECT statement to generate the same result.

The following example illustrates the simulation of Oracle's MINUS operator:

SELECT OrderID, OrderDate
FROM Orders O
WHERE NOT EXISTS
(
SELECT 1
FROM RefundsTable R
WHERE O.OrderID = R.OrderID
)

Nested tablesNot supported

Oracle 8i and prior versions didn't support this feature and is introduced in Oracle 9i. This feature basically enables you to store a table, within a column. It is like having an array of records in your database columns.

SQL Server has no concept of nested tables.

As a workaround, You could store your sub-tables or child tables in the form of XML inside a char, nchar, varchar, nvarchar, text or ntext type column, and parse it as needed, at runtime. See OPENXML, sp_xml_preparedocument, sp_xml_removedocument in SQL Server 2000 Books Online.

Another possible workaround would be to store comma separated values (CSV).

Note that this is against the basic rules of normalization. Columns are nomore atomic, with nested tables.

From a design point of view, best thing to do would be, to create different tables for representing different entities and link them with primary and foreign key relationships. This will also make searching easier.

OracleSQL Server

:-)

PackagesNot supported

No equivalent in SQL Server for Oracle's Packages and Package variables concept

PL/SQLT-SQL

Every database product implements and extends the standard SQL. Oracle's implementation of SQL is called PL/SQL, while Microsoft's is called T-SQL (Transact-SQL)

Row level securityNo equivalent

Though there is no inbuilt support in SQL Server for row level permissions, you can implement it using view and system functions.

For more information and a working example, read this article:

Implementing row level permissions/security in SQL Server databases

rownum pseudo columnNo equivalent

Though there is no rownum or rowid in SQL Server, there are several ways in which a row number can be generated.

For some examples, read this article:

Q186133 INF: How to Dynamically Number Rows in a Select Statement

SELECT...FOR UPDATEUPDLOCK hint

Use the locking hint UPDLOCK in your SELECT statement.

See SQL Server Books Online for more information.

SequencesIDENTITY

It is much simpler in SQL Server to generate a sequence value for a primary key or a non-key column.

You just need to turn on the IDENTITY property of column. IDENTITY property can be set to columns of the following data types: tinyint, smallint, int, bigint, decimal, numeric

Try this example to see how it works:

CREATE TABLE foo
(
i int IDENTITY(1, 1)
j int
)

INSERT INTO foo (j) VALUES (911)
INSERT INTO foo (j) VALUES (999)

SQL *PlusQuery Analyzer

For connecting to SQL Server and executing queries and modifying data, use the built-in Query Analyzer. It is much more powerful and friendlier than Oracle's SQL *Plus

START WITH...CONNECT BY clauseNo equivalent

Though there's no direct equivalent in T-SQL for Oracle's START WITH...CONNECT BY, there are several ways and efficient techniques for processing and querying hierarcical data.

For more information, read this article:

Working with hierarchical data in SQL Server databases

SynonymViews

You can simulate Oracle Synonyms in SQL Server using Views. For example, the following creates a view that returns the OrderID and OrderDate from Orders table.

CREATE VIEW vOrders
AS
SELECT OrderID, OrderDate
FROM Orders

Now you can select data from the view, using the following SELECT statement:

SELECT * FROM vOrders

The following example will create a view which is equivalent to Oracles TABS synonym or USER_TABLES data dictionary view (For simplicity, I am only including the table name in the view definition):

CREATE VIEW TABS
AS
SELECT name AS table_name
FROM sysobjects
WHERE type = 'U'

Now you can execute the following SELECT statement to return all user table names:

SELECT table_name
FROM TABS

Monday 24 August 2009

Frame Locations...


self and window
These refer to the global object of current web page.

parent
Refers to the window object of the page that is holding the current page in a frameset.

top
Refers to the window object of the page at the top of the frames hierarchy.

window.frames[nameOrNumberOfFrame]
Refers to a frame or iframe held by the current page.

Friday 17 July 2009

VSS Corrupts PDF and other Binary files...


When checking in PDF files (and other Binary files) into VSS, make sure these are noted within VSS' options as a binary type

Tools > Options > File Types > [Binary Files] add "*.pdf"

otherwise the PDFs are currupted and appear blank with errors.

Ensure VSS SP1 is installed too.

Tuesday 16 June 2009

AJAX TOOLKIT ERROR: ".... requires a ScriptManager on the page"


Add folowing section, but please keep in mind that BOTH 1.0 and 3.5 assemblies System.Web.Extensions should be in GAC, in other case it will not work.

Add this to the Web.config
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

Monday 15 June 2009

Events and Delegates for UserControls


Heres a nice article on why UserControls require events and delegates and how to implement them in C#/ASP.NET.

http://codebetter.com/blogs/brendan.tompkins/archive/2004/10/06/Easily-Raise-Events-From-ASP.NET-ASCX-User-Controls.aspx

Friday 5 June 2009

When should I use WPF vs. Silverlight?


In my role, I work with a number of large corporations, and this is a question that they ask me regularly: What is the difference between the Windows Presentation Foundation (WPF) and Silverlight, and in what scenarios does it make sense to use each?

Microsoft feels that user experience is important, and invested in multiple technologies to promote better user experience. Both WPF and Silverlight use XAML (Extensible Application Markup Language) under the covers.

Let's look at some of the different characteristics of each technology:



WPF:

* Ships as part of the .NET Framework (version 3.0 and onward)
* Runs as Windows application or as web "browser application" (called XBAP, for "XAML Browser Application"). Note that XBAPs run only in Internet Explorer with .NET 3.0 and in both Internet Explorer and Firefox with .NET 3.5.
* Runs on Windows machines only (Windows XP, Windows Server 2003, Windows Vista, and Windows Server 2008)
* Richest functionality, including 3D graphics

Silverlight:

* Ships independently
* Runs in web browsers only (Internet Explorer, Firefox, Safari)
* Runs on Windows or Mac operating systems (also on Linux via Moonlight, which is an open source implementation of Silverlight based on Mono)
* Functionality is a subset of WPF's feature set



When should you use each? The maddening answer is (of course): it depends!

WPF is a more mature technology and was designed with a richer feature set. It also has the advantage of being able to run in a browser or as an installed Windows-Form-type app.

Silverlight has a broader reach. You can access Silverlight from many operating systems and web browsers.

The most important reason to choose one over the other should be based on the intended audience for the application. For example, if a corporation is designing an application for internal use only and every employee has Windows XP as the company standard OS, then go with WPF to leverage the richer feature set. If a corporation is designing an external-facing website, then Silverlight is the better choice because potential customers can access the website from a variety of different operating systems and browsers.

Wednesday 3 June 2009

.NET WebApps Impersonation


There are many examples on why impersonation is useful... It gives you the ability to impersonate a user to access some sort of resource/utility either on the current system or a networked system.

An example might be that your attempting to retrieve a list of directories from a server in which you do not have access. Getting around this is quite simple.

Open up your web.config and enter the following...

<identity impersonate="true" username="" password="" />

Tuesday 5 May 2009

NT AUTHORITY\NETWORK SERVICE does not have write access.


You may receive this error with ASP.NET applications....
The current identity (NT AUTHORITY\NETWORK SERVICE) does not have write access to 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files'.

The Solution:

1. Goto command prompt then navigate to directory

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727


2. Now run this command

aspnet_regiis -ga "NT AUTHORITY\NETWORK SERVICE"

Tuesday 28 April 2009

Expand Size of Virtual Disk


Today I've attempted to grow the size of an existing vmware disk...

We have VMWare installed on a distribution of linux, the following commands will also work with windows. It is always a bad idea to have an auto-growing disk... there is a performance overhead associated and the disk will never shrink!

To manually grow a disk, execute the following command...

Example:
vmware-vdiskmanager -x 10GB myDisk.vmdk


This will increase "myDisk.vmdk" to 10GB.

------

You then need to log into a seperate virtual machine and add this newly extended vmdk as an extra hard disk...

Go into Disk Management (Control Panel > Adminsitrative Tools > Computer Management)... you should be able to see the newly unallocated space... Allocate this space but no not assign a drive letter to it as an Extended Partition.

Open command prompt and use the DiskPart.exe tool to extend the partition.

Usage:
DISKPART
list volume
select volume x   (where x is the drive number)
extend



IMPORTANT

If you receive the following error with DISKPART...

The volume you have selected may not be extended.
Please select another volume and try again.


See this microsoft support thread and use the Windows 2000 version of DISKPART.exe

Download: http://support.microsoft.com/kb/841650

Friday 20 March 2009

MSN Messenger API for .NET


Heres a nice library written in C# which allows you to connect to MSN Messenger and consume many of the messenger library functions

http://www.xihsolutions.net/dotmsn/

Wednesday 18 March 2009

Creating a custom CruiseControl.NET Plugin


What's great about ccnet is that you have the ability to create custom plug-in's within visual studio using reflection. You can then compile these plugins into DLLs and place them into the ..\CruiseControl.NET\server directory.

You may have used plugin's previously, many can be found at http://ccnetplugins.sourceforge.net/, to aid your continuous integration process for managing releases and controlling versioning.

Versioning is a very important aspect of release management and continuous integration as a whole. Versioning should be maintained and traceable across the whole build process.

For me, I have the following components versioned...
- All Libraries (dll files)
- Source Repository Labels (within SourceSafe, CVS, Sub Version etc.)
- CruiseControl.NET labels (within the web interface for each component)
- The Setup Project (this will also add the version info to Add/Remove Programs etc)


So, if I install a component (MSI in this case) on a clients machine, I can trace it back to the build info, the included libraries, and also, the code in the source repository!
The process of building this standard versioning system, however, isn't quite as trivial as one would hope. Alongside our build system (MSBuild, Nant etc) we can utilise CruiseControl.NET plugin's to aid our CI process.

Here is a code snippit I have used while injects version information into a Wix3 Setup Project.

namespace ThoughtWorks.CruiseControl.s34n.VersionWixFile
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Xml;
    using Exortech.NetReflector;
    using ThoughtWorks.CruiseControl.Core;
 
    [ReflectorType("VersionWixFile")]
    public class VersionWixFile: ITask
    {
        string wixproj;
 
        [ReflectorProperty("WixFile")]
        public string WixFile
        {
            get { return wixproj; }
            set { wixproj = value; }
        }
 
        #region ITask Members
 
        public void Run(IIntegrationResult result)
        {
            // Get Version Info
            string newVersion = "v" + result.Label;
            
            // Inject Into WixProj File
            if (File.Exists(wixproj))
            {
                // Get contents of file
                StreamReader sr = new StreamReader(wixproj);
                string wixProjFile = sr.ReadToEnd();
                sr.Close();
                sr.Dispose();
 
                // Replace version info
                wixProjFile = wixProjFile.Replace("[[VERSION]]", newVersion);
 
                // Write contents of file back out
                StreamWriter sw = new StreamWriter(this.wixproj);
                sw.Write(wixProjFile);
                sw.Close();
                sw.Dispose();
            }
            else
            {
                throw new Exception(string.Format("The specified .wixproj file '{0}' does not exist.", this.wixproj));
            }
        }
 
        #endregion 
    }
}



As you can see, in this example, two references are used..

  using Exortech.NetReflector;
  using ThoughtWorks.CruiseControl.Core;



These DLLs are shipped with CruiseControl.NET, and must be imported into the current solution for your plugin.

We implement the "ITask" interface and must override the "Run" method. The IIntegrationResult parameter provides us with information about the current build, including and not limited to, the version number.
This plugin does a simple replacement, where it looks for a piece of text in the Win project called: [[VERSION]]... it then replaces this with the version of the current build.

Compile the plugin within visual studio and make sure the DLL Library begins with "ccnet." and ends with ".plugin.dll". This is a known issue with CruiseControl.NET, and the plugin wont work correctly otherwise. An example might be: ccnet.s34n.VersionWixFile.plugin.dll

Place this DLL in the "..\CruiseControl.NET\server" directory alongside the ccnet.config file.

The plugin can then be called from the ccnet.config file by using the following code...

<!-- Inject ccnet version into Wix Project File -->
<VersionWixFile>
      <WixFile>[WIX PROJECT FILE PATH]\Product.wxs</WixFile>
</VersionWixFile>


Once this has been injected into the build, we can build the Wix project using MSBuild and produce a versioned MSI Setup Project! (dont forget to restart ccnet!)

View contents of MSI files with ORCA


If you require seeking the contents of an MSI file, its quite easy with the Windows Installer 4.5 Software Development Kit.

The kit includes a utility called "Orca" which gives you the ability to right-click any MSI file, and look at its contents.


1. Install the Windows Installer 4.5 Software Development Kit

2. Go to the installation location and navigate to the "TOOLS" directory.

3. Locate "orca.msi" and install this utility.

4. Right-click any msi and "Edit with Orca".!

Tuesday 17 March 2009

Insert GUID VBScript Code


I've recently been playing around with Wix and it involves a lot of GUID (Global Unique Identifier) creation. You can assign the following VBScript to a macro key press or toolbar button in visual studio (Menu: Tools > Macros).

Sub InsertGuid()
  Dim objTextSelection As TextSelection
  objTextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
  objTextSelection.Text = System.Guid.NewGuid.ToString.ToUpper(New System.Globalization.CultureInfo("en", False))
End Sub


The following link contains detail on how to assign it to a keypress or a toolbar button.

Assigning VBScript Macros to Toolbar Buttons or Key Sequences

Assigning VBScript Macros to Toolbar Buttons or Key Sequences


If you assign a macro to a toolbar button or key sequence, you can run the macro by clicking the button or pressing the assigned keys.

To assign a macro to a toolbar button

1. On the Tools menu, click Customize.

2. Click the Commands tab.

3. In the Category box, click Macros.

4. From the Commands box, drag the macro's name to the toolbar where you want a button for the macro.

5. In the Button Appearance dialog box, select an image for the toolbar button, and then click OK.



To assign a macro to a key sequence

1. On the Tools menu, click Customize.

2. Click the Keyboard tab.

3. In the Category box, click Macros.

4. In the Commands box, select the macro you want to assign.

5. Click in the Press new shortcut key box.

6. Press the key sequence you want to use for the macro.

7. Click the Assign button.

Monday 16 March 2009

Visual Studio Team System 2010 CTP


So, late last year, microsoft introduced Visual Studio 2010 CTP for a preview...

I have to say, its a really great tool! Microsoft has parnered with the guys at OMG (Object Modelling Group) to introduce full UML support! You can simply create new a "Modelling Project" and create various diagrams in the WYSIWYG editor. You can also create different diagrams based on what you have drawn, and im sure, diagrams can be created from code as before. Its a slick way to reverse engineer the development ;)


Other things of interest
- Cloud Development for Azure
- Sharepoint Development
- Full silverlight support
- and more...



Download (VHD)

http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=922b4655-93d0-4476-bda4-94cf5f8d4814&displaylang=en


Guide to extend the expiry date of the VHD (Required as of 1st Jan 2009!)
:
http://blogs.msdn.com/jeffbe/archive/2008/12/09/dealing-with-the-team-system-2010-ctp-expiration.aspx

Wednesday 11 March 2009

Adding an Installer to a windows service


So, now you may have a windows service up and running, but you need to install it... its not as hard as yout think...

1. Goto the service designer GUI, right click, and select "Add Installer", and then .NET will create a "ProjectInstaller.cs" file.

2. Goto the "ProjectInstaller.cs" design view. You will see a ServiceProcessInstaller and a ServiceInstaller.

3. In the properties for the ServiceProcessInstaller, you can configure the Account information. Here you can define whether to run the service as a user, system user or even network service.

4. In the properties for the ServiceInstaller, you can configure the start-type (Manual, Automatic, Disabled etc.) and general settings and names for your service.

5. Once the properties have been setup, these two objects have a series of events which allow any custom actions to be performed before or after setup/uninstall etc. Populate the methods with any custom actions you may require.

6. Now create a new Windows Setup project using the standard template and add it to the current solution. Add the "primary output" from the service project. Then, right click the setup project, select 'View', then 'Custom Actions'.

7. Right click the 'Custom Actions' root node in the main tree view and 'Add custom action'. Select the primary output for the service.

8. Add suitable settings for your installer project, then your done!

Adding timers in Windows Services


So if you have tried to add a standard windows timer (System.Windows.Forms.Timer)... you may notice the timer never gets executed. I think this is a poor design flaw made by Microsoft as timers are quite a fundamental part of services in the way they are architectured and constructed.

In any case, there is a workaround, we can use Threading Timers (System.Threading.Timer). These work in a similar fashion.


1. Instantiate a new System.Threading.Timer object

Timer newTimer1 = new Timer(new TimerCallback(newTimer1_Tick), null, 0, 5000);


- This requires a TimerCallback, so we will need a method called "newTimer1_Tick".
- null -> not required
- 0 -> this starts the timer immediatly (0 milliseconds)
- 5000 -> this is the interval... triggers every 5 seconds (5000 milliseconds)



2. Create the callback method...

private void newTimer1_Tick(object state)
{
            
}


- your timer logic falls within this method



3. Remember to dispose of the timers after use...


newTimer1.Dispose();

Debugging a Windows Service in Visual Studio.NET


There is an easy way to debug a windows service in .NET, without having to install it each time (then restart as its marked for deletion!!).

1. Create a new Windows Service Project using the default template.
2. Open "Program.cs"
3. In "Main()" use the following code...

Code Snippet
  1. #if (!DEBUG)
  2.     System.ServiceProcess.ServiceBase[] ServicesToRun;
  3.     ServicesToRun = new System.ServiceProcess.ServiceBase[] { new [Service Name]() };
  4.     System.ServiceProcess.ServiceBase.Run(ServicesToRun);
  5. #else
  6.     // Debug code: this allows the process to run as a non-service.
  7.     // It will kick off the service start point, but never kill it.
  8.     // Shut down the debugger to exit
  9.     [Service Name] service = new [Service Name]();
  10.     service.[Service Main Method]();
  11.  
  12.     // Put a breakpoint on the following line to always catch
  13.     // your service when it has finished its work
  14.     System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
  15. #endif
End of Code Snippet


4. Replace [Service Name] with the class name of your service.
5. Add a method to your [Service Name].cs file (which is also called from "OnStart(string[] args)". This method will contain all of the logic which is debugged. Reference this method in "Program.cs"
6. Set the compiler to DEBUG mode, and start putting some breakpoints in!!


The same applies for VB.NET users

Sorting an Array of Custom Objects in C#


This post discusses two methods of sorting custom objects within C#.
---------------------------------------------------------------------
Consider a simple case of sorting an array of strings in C#. We can simply call the Sort() method to sort the array.
Code Snippet
  1. ArrayList carArray = new ArrayList();
  2. carArray.Add("Corvette");
  3. carArray.Add("Honda");
  4. carArray.Add("BMW");
  5. carArray.Sort();
End of Code Snippet


If you observe the contents of the array after the Sort(), you will notice that the elements are sorted alphabetically ie., "BMW," "Corvette," "Honda."

However, consider a Car Class as shown in Listing 2.
Code Snippet
  1. class Car
  2. {
  3.   public string Make { set; get; }
  4.   public int Year { set; get; }
  5.   public string Location { set; get; }
  6. }
End of Code Snippet


If you create an ArrayList of car objects and try to Sort() it, it would throw an exception. You will need to have the Car class implement the IComparable interface and define the CompareTo method to be able to sort custom objects.


Method 1: Implementing the IComparable Interface

Step 1: Implement the IComparable interface
Code Snippet
  1. class Car : IComparable
End of Code Snippet


Step 2: Define the CompareTo method.

In this example we will be sorting by the Make property of the Car Class.
Code Snippet
  1. public int CompareTo(object obj)
  2. {
  3.   if (obj is Car)
  4.   {
  5.     Car c2 = (Car)obj;
  6.     return Make.CompareTo(c2.Make);
  7.   }
  8.   else
  9.     throw new ArgumentException("Object is not of type Car.");
  10. }
End of Code Snippet


That is it! We are now ready to test if our sorting works.

Step 3: Test Sorting by Make.
Code Snippet
  1. Car objCar = new Car();
  2. ArrayList carArray = new ArrayList();
  3.  
  4. objCar.Make = "BMW";
  5. objCar.Year = 2008;
  6. objCar.Location = "Florida";
  7. carArray.Add(objCar);
  8. objCar = null;
  9.  
  10. objCar = new Car();
  11. objCar.Make = "Honda";
  12. objCar.Year = 1996;
  13. objCar.Location = "Illinois";
  14. carArray.Add(objCar);
  15. objCar = null;
  16.  
  17. objCar = new Car();
  18. objCar.Make = "Corvette";
  19. objCar.Year = 2006;
  20. objCar.Location = "California";
  21. carArray.Add(objCar);
  22. objCar = null;
  23.  
  24. carArray.Sort();
End of Code Snippet


You will now observe that the carArray is sorted alphabetically by Make.

Note: Sometimes instead of using the ArrayList, it is possible that you are working with an object array. You can use the C# built in Adapter() method as shown below.

To convert from an array to ArrayList use:
Code Snippet
  1. ArrayList carArray = ArrayList.Adapter(carObjectArray);
End of Code Snippet

To convert from an ArrayList to object array use:
Code Snippet
  1. Car[] carObjectArray = (Car[])carArray.ToArray(typeof(Car));
End of Code Snippet


Method 2: Using the IComparer Interface

Sometimes, it might be necessary to have more flexibility in your sorting, for example, to provide which property you want to sort the Car array by. In situations like this, we would need to use the IComparer interface and use the overloaded Sort method that takes the comparer instance as an argument.

Step 1: Create a CarComparer class that implements the IComparer interface
Code Snippet
  1. class CarComparer: IComparer
  2. {
  3.   public enum ComparisonType
  4.   {
  5.     Make = 1, Year, Location
  6.   }
  7.  
  8.   public ComparisonType ComparisonMethod
  9.   {
  10.     set;
  11.     get;
  12.   }
  13.  
  14.   public int Compare(object x, object y)
  15.   {
  16.     Car c1;
  17.     Car c2;
  18.  
  19.     if (x is Car)
  20.       c1 = x as Car;
  21.     else
  22.       throw new ArgumentException("Object is not of type Car.");
  23.  
  24.     if (y is Car)
  25.       c2 = y as Car;
  26.     else
  27.       throw new ArgumentException("Object is not of type Car.");
  28.  
  29.     return c1.CompareTo(c2, ComparisonMethod);
  30.   }
  31. }
End of Code Snippet


The main purpose of the CarComparer is to keep track of by what property we are sorting. It has a ComparisonType enum that has the property elements and an overloaded Compare method.


Step 2

Add an overloaded CompareTo to the Car class as shown in Listing 7.

Code Snippet
  1. public int CompareTo(Car c2, CarComparer.ComparisonType comparisonType)
  2. {
  3.   switch (comparisonType)
  4.   {
  5.     case CarComparer.ComparisonType.Make:
  6.       return Make.CompareTo(c2.Make);
  7.     case CarComparer.ComparisonType.Year:
  8.       return Year.CompareTo(c2.Year);
  9.     case CarComparer.ComparisonType.Location:
  10.       return Location.CompareTo(c2.Location);
  11.     default:
  12.       return Make.CompareTo(c2.Make);
  13.   }
  14. }
End of Code Snippet


That is it, we are done. We now have added the ability to sort by Make, Year or Location. Let us test it out.

Step 3
Code Snippet
  1. Car objCar = new Car();
  2. ArrayList carArray = new ArrayList();
  3.  
  4. objCar.Make = "BMW";
  5. objCar.Year = 2008;
  6. objCar.Location = "Florida";
  7. carArray.Add(objCar);
  8. objCar = null;
  9. objCar = new Car();
  10. objCar.Make = "Honda";
  11. objCar.Year = 1996;
  12. objCar.Location = "Illinois";
  13. carArray.Add(objCar);
  14. objCar = null;
  15.  
  16. objCar = new Car();
  17. objCar.Make = "Corvette";
  18. objCar.Year = 2006;
  19. objCar.Location = "ZZ";
  20. carArray.Add(objCar);
  21. objCar = null;
  22.  
  23. CarComparer carComparer = new CarComparer();
  24. carComparer.ComparisonMethod = CarComparer.ComparisonType.Location;
  25. carArray.Sort(carComparer);
End of Code Snippet


We use the overloaded Sort method that takes an instance of the CarComparer class. To sort by other properties, change the ComparisonMethod as shown below.

Code Snippet
  1. carComparer.ComparisonMethod = CarComparer.ComparisonType.Year
End of Code Snippet



Conclusion
This article demonstrates different ways of sorting an array of custom objects. It provides a step-by-step approach in using the IComparable interface and in creating a Comparer class for sorting.

Monday 9 March 2009

Get your Business and Data Layers talking!


The following sections present the options for passing business entity data to and from your data access logic components, in addition to the advantages and disadvantages of each approach. This information will help you to make an informed choice based on your specific application scenario.


Passing Scalar Values As Inputs and Outputs


The advantages of this option are as follows:

* Abstraction. Callers must know about only the data that defines the business entity, but not a specific type or the specific structure of the business entity.
* Serialization. Scalar values natively support serialization.
* Efficient use of memory. Scalar values only convey the data that is actually needed.
* Performance. When dealing with instance data, scalar values offer better performance than the other options described in this document.


The disadvantages of this option are as follows:


* Tight coupling and maintenance. Schema changes could require method signatures to be modified, which will affect the calling code.
* Collections of entities. To save or update multiple entities to a Data Access Logic Component, you must make separate method calls. This can be a significant performance hit in distributed environments.
* Support of optimistic concurrency. To support optimistic concurrency, time stamp columns must be defined in the database and included as part of the data.



Passing XML Strings As Inputs and Outputs


The advantages of this option are as follows:


* Loose coupling. Callers must know about only the data that defines the business entity and the schema that provides metadata for the business entity.
* Integration. Accepting XML will support callers implemented in various ways—for example, .NET applications, BizTalk Orchestration rules, and third-party business rules engines.
* Collections of business entities. An XML string can contain data for multiple business entities.
* Serialization. Strings natively support serialization.

The disadvantages of this option are as follows:

* Reparsing effort for XML strings. The XML string must be reparsed at the receiving end. Very large XML strings incur a performance overhead.
* Inefficient use of memory. XML strings can be verbose, which can cause inefficient use of memory if you need to pass large amounts of data.
* Supporting optimistic concurrency. To support optimistic concurrency, time stamp columns must be defined in the database and included as part of the XML data.



Passing DataSets As Inputs and Outputs

The advantages of this option are as follows:

* Native functionality. DataSets provide built-in functionality to handle optimistic concurrency (along with data adapters) and support for complex data structures. Furthermore, typed DataSets provide support for data validation.
* Collections of business entities. DataSets are designed to handle sets and complex relationships, so you do not need to write custom code to implement this functionality.
* Maintenance. Schema changes do not affect the method signatures. However, if you are using typed DataSets and the assembly has a strong name, the Data Access Logic Component class must be recompiled against the new version, must use a publisher policy inside the global assembly cache, or must define a element in its configuration file. For information about how the runtime locates assemblies, see How the Runtime Locates Assemblies.
* Serialization. A DataSet supports XML serialization natively and can be serialized across tiers.

The disadvantages of this option are as follows:

* Performance. Instantiating and marshalling DataSets incur a runtime overhead.
* Representation of a single business entity. DataSets are designed to handle sets of data. If your application works mainly with instance data, scalar values or custom entities are a better approach as you will not incur the performance overhead.



Passing Custom Business Entity Components As Inputs and Outputs


The advantages of this option are as follows:

* Maintenance. Schema changes may not affect the Data Access Logic Component method signatures. However, the same issues arise as with typed DataSets if the Business Entity Component is held in a strong-named assembly.
* Collections of business entities. An array or a collection of custom business entity components can be passed to and from the methods.

The disadvantages of this option are as follows:

* Supporting optimistic concurrency. To support optimistic concurrency easily, time stamp columns must be defined in the database and included as part of the instance data.
* Limited integration. When using custom business entity components as inputs to the Data Access Logic Component, the caller must know the type of business entity; this can limit integration for callers that are not using .NET. However, this issue does not necessarily limit integration if the caller uses custom business entity components as output from the Data Access Logic Component. For example, a Web method can return the custom Business Entity Component that was returned from a Data Access Logic Component, and the Business Entity Component will be serialized to XML automatically using XML serialization.

Thursday 26 February 2009

"Cannot load mysql extension. Please check your PHP configuration" Error with XAMPP


so, if your like me, you've downloaded XAMPP... managed to get apache to start, but having trouble with MYSQL integration, then read on....
If you are simply trying to integrat php and mysql, then you may still find this useful.

You may receive this warning when attempting to access the local MYSQL instance packaged with XAMPP. Usually, this is noticed by clicking on the phpmyadmin on the XAMPP control panel.

1. For me: the problem was because i already had PHP installed on my PC. Therefore, the old installation was being used and it was conflicting!!

2. For others: The problem was due to the "php_mysql.dll" extension being excluded from the php.ini file.

- open php.ini located within the main php dir. For me, this is .\xampp\php\.
- Find "extension=php_mysql.dll" and ensure the semicolon is removed from the start of the string. This will then include the mysql extension.
- Now find the "extension_dir" string, and ensure it points to the 'ext' dir within the php dir. For me, this value is: extension_dir = "\xampp\php\ext\"

3. Lastly: Others find the problem is with a currupted mysql configuration file. This is located within the 'mysql\bin' dir. For me, this is ".\xampp\mysql\bin".
This is a cnf file, and for Windows users, this is the same extension as a SpeedDial file, so it will just be called "my". The best way to edit this, is to use the 'winmysqladmin.exe' tool located in the same directory, or drag the file onto Notepad.exe. Ensure the port is setup to a free port on your system... Mine is the default: 'port= 3306'.

If this is still not working, open "winmysqladmin.exe". (this is now an unsupported application, use phpmyadmin for anything else! You may receive DLL errors when using, but just ignore them.). Execute the 'my.ini setup' tab and a new configuration file can be saved out from here.

Wednesday 25 February 2009

Starting Apache 2.2 on Windows (applies to *nix also)


I recently downloaded XAMPP the other day, and had a little trouble starting the inbuilt Apache 2.2 web server. Here is what i did to resolve these issues.
(This also applies to NIX systems).

I attempted to start the the apache service [apache_installservice.bat], but I received a strange error. So i decided to open the Apache Monitor manually and start the webserver.

Monitor Location: .\apache\bin\ApacheMonitor.exe

I executed the start button and the server failed to start with an ambiguous error message. I opened the event log and found the following error...

The Apache service named reported the following error:
>>> (OS 10048)Only one usage of each socket address (protocol/network address/port) is normally permitted. : make_sock: could not bind to address 0.0.0.0:80


It seemed i already had programs/services running on port 80, so i opened up the Apache config file and altered the port.

Config Location: .\apache\conf\httpd.conf

Change: Listen 80 ---> to: Listen 8080

This will run the server on 8080 rather than 80. (assuming 8080 is free!)... you can check "netstat" on "Start>Run>cmd" to check this.



I then attempted to fire up the web server again, but the same error occured (but with a different port!) This time the port being 443...

The Apache service named reported the following error:
>>> (OS 10048)Only one usage of each socket address (protocol/network address/port) is normally permitted. : make_sock: could not bind to address 0.0.0.0:443 .


This port tells Apache which port SSL associated with. This can also be modified using the SSL config file.

SSL Config file location: .\apache\conf\extra\httpd-ssl.conf

Change: Listen 443 ---> to: Listen 444

(Providing nothing is running on 444)


I then attemted to start the Apache Server, and everything ran smoothly!

Tuesday 3 February 2009

Increase File Size limits on .NET Web Services.


Add this to the Web.config file.

Code Snippet
  1. <httpRuntime executionTimeout="3600" maxRequestLength="80960"></httpRuntime>
End of Code Snippet
- executionTimeout is given in seconds.
- maxRequestLength is given in KB.

This will increase the accepted file size over SOAP to 80MB with a timeout of 1 hour.