Tuesday 21 December 2010

Server.MapPath when HttpContext is null

I've been writing some code that is fired from a scheduled task and need to access the root of a website. The usual method of Server.MapPath() returns an error as the HttpContext is null due to running under another thread.
To work around this problem you can use the method:
System.Web.Hosting.HostingEnvironment.MapPath()

Monday 20 December 2010

Images showing in Firefox but not IE

I've worked on a site recently when images would show up in Firefox but not IE. This is an issue with IE not being able to show images that have the colour mode set to CMYK.

To solve, change all the image colour modes to RGB.

  1. Open the image in Photoshop
  2. Select the Image menu
  3. Select the Mode menu
  4. Select the mode you want
  5. Save image

Wednesday 1 December 2010

Run program as Administrator from search box

If you type in the search box, you can find and run an application you are after, example notepad. If you click enter once the application is highlighted, this will run the application as a normal user.

To get the program to open as an administrator user, use the following short cut:

Ctrl + Shift + Enter

Tuesday 30 November 2010

MSBuild and recursive copying

If you require to copy files and folder recursively, you'll need to use the following code.

First declare the list of files to copy in an ItemGroup

<ItemGroup>
  <Files Include=".\**\*.cs" />
</ItemGroup>

Then use the files metadata to perform the copy.

<copy DestinationFiles="@(Files)->'location\%(RecursiveDir)%(Filename)%(Extension)')" SourceFiles="@(Files)" />

More information available at MSBuild Team Blog article

MSBuild updating TeamCity build status

If you are using TeamCity and MSBuild to provide Continuous Integration and are using custom build tasks, you can get MSBuild to update the status of the build in TeamCity.

You need to add the following line:

<Message Importance="high" Text="##teamcity[progressMessage 'Packaging media files ...']" />

MSBuild calling same target multiple times

If you are doing similar tasks within a build, you can set-up a target and call it multiple times, like copying files between directories. You can pass in parameters like variables, to keep the methods as generic as possible.

An example:
<MsBuild Projects="$(MSBuildProjectFile)" Targets="MethodName" Properties="Param1=Value" />

<Target Name="MethodName">
<ItemGroup>
<Path Include="Source\$(Value)"/>
</ItemGroup>
...
</Target>

Friday 19 November 2010

Sitecore Treelist filtering

We have a treelist for selecting content to display as lists. The editor only needs to select the parent and not any of the children. Using the default source for a treelist to point to the containing folder you allow the editors to see all the children.

You could write a query like below to exclude or include the templates you require:
/sitecore/content/DisplayItems/descendant-or-self::*[@@templatename!='Template1' and @@templatename!='Template2' and @@templatename!='Template3']

This can be changed to use the following format which is easier to read and has more options.
Datasource=/sitecore/content/DisplayItems&ExcludeTemplatesForDisplay=Template1,Template2,Template3

Using this approach, there are several other parameters that you can set like:
  • IncludeTemplatesForSelection
  • ExcludeTemplatesForSelection
  • IncludeTemplatesForDisplay
  • ExcludeTemplatesForDisplay
There is more reading and options on this at LearnSitecore

Wednesday 10 November 2010

key not valid for use in specified state

Something that a colleague recently found out that may be useful if you ever need to use the RSA Encryption provider in the .Net Framework.

If you try to encrypt data that exceeds 245 bytes you get an error "key not valid for use in specified state". This is a little misleading considering the cause, which I found here in the end: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/4e3ada0a-bcaf-4c67-bdef-a6b15f5bfdce/

For those of you interested you can re-create with the following (this is a modification to the RSA Example from http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx).

If you uncomment the second 'Append' line and re-run it the provider fails with the "key not valid" exception.
using System;
using System.Security.Cryptography;
using System.Text;

class RSACSPSample
{

static void Main()
{
StringBuilder sb = new StringBuilder();
sb.Append("The quick brown fox jumped over the lazy dogs.");
//sb.Append("The quick brown fox jumped over the lazy dogs.");

Console.WriteLine(sb.Length.ToString());

try
{
//Create a UnicodeEncoder to convert between byte array and string.
UnicodeEncoding ByteConverter = new UnicodeEncoding();

//Create byte arrays to hold original, encrypted, and decrypted data.
byte[] dataToEncrypt = ByteConverter.GetBytes(sb.ToString());
byte[] encryptedData;
byte[] decryptedData;

//Create a new instance of RSACryptoServiceProvider to generate
//public and private key data.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{

//Pass the data to ENCRYPT, the public key information
//(using RSACryptoServiceProvider.ExportParameters(false),
//and a boolean flag specifying no OAEP padding.
encryptedData = RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false), false);

//Pass the data to DECRYPT, the private key information
//(using RSACryptoServiceProvider.ExportParameters(true),
//and a boolean flag specifying no OAEP padding.
decryptedData = RSADecrypt(encryptedData, RSA.ExportParameters(true), false);

//Display the decrypted plaintext to the console.
Console.WriteLine("Decrypted plaintext: {0}", ByteConverter.GetString(decryptedData));
}
}
catch (ArgumentNullException)
{
//Catch this exception in case the encryption did
//not succeed.
Console.WriteLine("Encryption failed.");

}

Console.ReadKey();
}

static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
try
{
byte[] encryptedData;
//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{

//Import the RSA Key information. This only needs
//toinclude the public key information.
RSA.ImportParameters(RSAKeyInfo);

//Encrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
}
return encryptedData;
}
//Catch and display a CryptographicException
//to the console.
catch (CryptographicException e)
{
Console.WriteLine(e.Message);

return null;
}

}

static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
try
{
byte[] decryptedData;
//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Import the RSA Key information. This needs
//to include the private key information.
RSA.ImportParameters(RSAKeyInfo);

//Decrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
return decryptedData;
}
//Catch and display a CryptographicException
//to the console.
catch (CryptographicException e)
{
Console.WriteLine(e.ToString());

return null;
}

}
}
You can force a key size in the constructor for the provider to allow more data, but this slows the algorithm down considerably.

Hopefully this may be useful to someone at some point :

Tuesday 10 August 2010

Change database owner

We need to install all databases with the owner as sa. Our security policy stops developers been able to log on to the SQL servers with the sa account (which I agree with). For some of our custom maintenance plans to run we need the owner ot be sa.

So, to change the database owner do the following:
USE database_name
EXEC sp_changedbowner 'sa'

Friday 28 May 2010

Local development SMTP server

If you are writing an application or website function that sends out emails you may want to use a local SMTP that doesn't actually forward on the email. This is useful when testing bulk mail, as you wouldn't want to send out actual emails to multiple test addresses. There are many apps out there that perfrom this function. The one that I use is SMTP4dev which is available from CodePlex.

Wednesday 12 May 2010

Dual screen wallpaper on Windows 7

If you have a dual, triple or quad screen setup, you can have a desktop wallper span all of them. I am using a free piece of software to do this called DisplayFusion, you can download this from http://www.binaryfortress.com/displayfusion/

Friday 7 May 2010

Aborting a Sitecore event

So you've managed to intercept a Sitecore event, but you now need to stop all other events from occurring. I've had to do this when creating an alias to make sure it doesn't effect any other item. So we check all the possible clashes in the item:creating event, if one is found we won't to stop all further processing.

To stop the further processing all you need to do is call the following:

SitecoreEventArgs.Cancel(args);

You may also want to pass a message to the user, so just add a call to SheerResponse.

SheerResponse.ShowError(shortDescription, longDescription);

Wednesday 5 May 2010

Update AssemblyInfo as part of the build process

I use TeamCity to build by code as part of continuous integration. One of the tasks I tend to do is to update the AssemblyInfo file with the current build number.

First you need to ensure you have installed the open source project MSBuild Community Tasks, downloadable from here.

Then the code to do this is:
<Target Name="PreBuildTasks">
<PropertyGroup>
<Version>$(BUILD_NUMBER)</Version>
</PropertyGroup>
<MSBuild.Community.Tasks.AssemblyInfo
CodeLanguage="CS"
AssemblyCompany="CompanyName"
AssemblyCopyright="Copyright (c) CompanyName2009"
AssemblyDescription="Description"
AssemblyFileVersion="$(Version)"
AssemblyVersion="$(Version)"
AssemblyTitle="Titlek"
Guid="1938930d-a5f3-4045-a5f3-f5b930d70ade"
AssemblyProduct="Product name"
OutputFile="$(MSBuildProjectDirectory)\ProjectName\Properties\AssemblyInfo.cs" />
</Target>

Please note this has only be tested to work on TeamCity.

Create build file from solution file

You can create a build file from your solution for use with MSBuild. Useful if you are using any automated build tools like TeamCity.

To do this, open up the "Visual Studio 2008 Command Prompt"
Navigate to the folder containing your solution file
Enter the following:

Set MSBuildEmitSolution = 1
msbuild solutionname.sln


Once complete you should see a file in the folder called solutionname.sln.proj which is now your build file. You can edit this build file as required. I tend to add pre build code to update AssemblyInfo.cs and post build code to fire off unit tests and to package up the final output.

Thursday 25 February 2010

Changing default editor for batch scripts.

Right clicking on a .bat or .cmd file and select edit will open the file in the default program, Notepad. I prefer to use a different editor. To change the default for these files requires a registry change:
  1. Open the registry editor (regedit.exe)
  2. Browse to HKEY_CLASSES_ROOT\batfile\shell\edit\command
  3. Edit the default value and change to the executable you want to use to edit the batch files,
    e.g. "C:\Program Files\Programmer's Notepad\pn.exe" "%1"
  4. Click OK
  5. Browse to HKEY_CLASSES_ROOT\cmdfile\shell\edit\command
  6. Edit the default value and change to the executable you want to use to edit the command files.
  7. Click OK
No restart required.

Wednesday 24 February 2010

IIS 7.0 not serving CSS files

After a rebuild of IIS 7, I couldn't get any CSS files to return. If I browsed to the path http://localhost/styles.css, I would a blank page (even when I view source). The problem was that during the reinstall of IIS I forgot to add the Static Content Component.

For Vista and Windows 7:
Control Panel -> Programs -> Turn Windows features on or off

Then navigate to: Internet Information Services -> World Wide Web Services -> Common HTTP Features
Enable the Static Content option

Friday 19 February 2010

Cannot load macro project error

After moving 'My Documents' folder to a different drive, I started getting an error when loading the macro's explorer window. The error was:

Cannot load macro project '' for the following reason:

'C:\Users\\Documents\Visual Studio 2008\Projects\VSMacros80\Samples\Samples.vsmacros' is an invalid or inaccessible macro project file

The problem is when you move your documents folder, this updates the environment variable %USERPROFILE%, but the macro's path for Visual Studio are stored in the registry.

Searching the registry I found the following two keys which had a 'path' value, referencing the C:\.

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\vsmacros\OtherProjects7\0
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\vsmacros\RecordingProject7


To solve, change the 'path' values in the above keys to your new location and restart Visual Studio.

Attach to multiple w3wp processes

This is an update to a previous post as I am now working on a project that can have up to 3 w3wp processes running.

I've changed the following lines:

Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, compName).Item("w3wp.exe")
proc2.Attach2(dbgeng)


with:
For Each proc2 As EnvDTE80.Process2 In dbg2.GetProcesses(trans, compName)
If proc2.Name.Contains("w3wp.exe") Then
proc2.Attach2(dbgeng)
End If
Next

Wednesday 3 February 2010

Visual Studio and Spark

There is a great post about setting up file icons, Templates and syntax highlighting in Visual Studio for spark templates here:

3 Useful Visual Studio Tricks for Spark Templates

Thursday 28 January 2010

IIS7 and basic authentication

I needed to use basic HTTP authentication to secure a site instance as it required pulic access for a demo.

However, in IIS7, the only authentication modes listed are the default Forms, Anonymous and ASP.NET Impersonation.

To solve this, I had to install the basic authentication module for IIS.

For Server 2008:
  • Server Manager -> Roles -> Web Server -> Add Role Services

For Vista and Windows 7:
  • Control Panel -> Programs -> Turn Windows features on or off

Then navigate to: Internet Information Services -> World Wide Web Services -> Security
Enable the Basic Authentication option

Thursday 7 January 2010

Debug prompt in VS 2008

When trying to debug an application using VS2008 on Windows 7 64 bit, I keep getting the following prompt, which is quite annoying.

debug prompt
To disable the prompt, you need to edit the following registry key. Ensure that Visual Studio is not running whilst you change the registry.

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Debugger
Set DisableAttachSecurityWarning attribute value to 1.

Monday 4 January 2010

Open command window here...

Windows XP came with a nice little powertoy “Open Command Prompt Here”, which enabled you to use the navigate around the file system and then were able to open a command prompt at the current location.

In Windows 7, you can now simply hold the Shift key down while right clicking on a folder and you'll see the option to "Open command window here".