16 December, 2011

Using ILMerge and Eazfuscator.NET

I ran into some new requirements on my last project.
I've made an autoupdate system which will be used for an upcoming project, and i wanted to merge all the dll's into the autoupdate executable.
Just to minimize trouble and communication when downloading the autoupdater.
I also wanted to obfuscate my executable.

Merge Assemblies:

Now first i stumbled upon ILMerge, which is used to merge assemblies.
This is a tool release by Microsoft so it should be safe to use, you can read more about it here:
http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx

It's pretty simple to use:

ILMerge.exe /out:MyMergedExe.exe MyOriginalExe.exe Myfirst.dll MySecond.dll
First, all my projects use framework version 4, so we need to add some parameters so that ILMerge will be able
to merge a framework version 4.0 project.

ILMerge.exe /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:MyMergedExe.exe MyOriginalExe.exe Myfirst.dll MySecond.dll
In the ILMerge folder (C:\Program Files (x86)\Microsoft\ILMerge\), create a file named ILMerge.exe.config:
<?xml version ="1.0"?>
<configuration>
 <startup useLegacyV2RuntimeActivationPolicy="true">
  <requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>
 </startup>
</configuration>
Great, now everything runs and works with .NET Framework v4.0.

Then i wanted a more dynamic way to include the DLL's without editing the ILMerge command line every time.
Luckily there is a parameter named /wildcards


ILMerge.exe /wildcards /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:MyMergedExe.exe MyOriginalExe.exe *.dll
And to get some more information about the merge process, add the /log parameter.

That's basically everything you need to know about merging assemblies into a single executable.

Obfuscate Executable:

So let's see how we can obfuscate the executable.
There is a lot of obfuscators out there.
I tried 3-4 variants, and found a lot of buggy obfuscators out there. Some crashed, some did not work, some costs a lot of $.
Anyway i ended up with the free EazFuscator.NET. It works, and has a nice commandline interface.
You can read more about it here:
http://www.eazfuscator.net


Eazfuscator.NET.exe -s -o MyObfuscatedExe.exe MyMergedExe.exe

I also added -s to get some statistics about the merge process.
You dont need to use the GUI application that comes with Eazfuscator.NET.
We will use the commandline interface only.


Automate, using PostBuild event:

Now, let's automate all this information into a complete build:

In your project, add this to the postbuild event:

if $(ConfigurationName) == Release $(ProjectDir)\Build\PostBuild.cmd "$(TargetDir)", "$(TargetName)"

Create a folder in your project and name it Build.
Inside the build folder, create a file named Postbuild.cmd with this content:


REM Add this to the project Postbuild event: 
REM if $(ConfigurationName) == Release $(ProjectDir)\Build\PostBuild.cmd "$(TargetDir)", "$(TargetName)"
ECHO --------------------------------------------------------------------------------------------------------------------------
ECHO Executing PostBuild.cmd with parameters: TargetDir=%1, TargetName=%2
CD %1
ECHO Merging Assemblies Into Executable: %2
IF NOT EXIST %1MergedRelease mkdir %1MergedRelease
"C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" /wildcards /log /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:MergedRelease/%2.exe %2.exe *.dll
ECHO Obfuscating Executable: %2
IF NOT EXIST %1MergedRelease\ObfuscatedRelease mkdir %1MergedRelease\ObfuscatedRelease
"C:\Program Files (x86)\Eazfuscator.NET\Eazfuscator.NET.exe" -s -o MergedRelease/ObfuscatedRelease/%2.exe MergedRelease/%2.exe
ECHO --------------------------------------------------------------------------------------------------------------------------


Now when building a release build:
The normal exe with separate dll's will be created under

$(ProjectDir)\Bin\Release\
Under this folder there will be a subfolder named MergedRelease:

$(ProjectDir)\Bin\Release\MergedRelease\
In this folder our merged exe with the pdb file will be created.

Under this folder there will be a subfolder named ObfuscatedRelease:

$(ProjectDir)\Bin\Release\MergedRelease\ObfuscatedRelease\
In this folder our merged and obfuscated exe will be created.

Now thats all, a merged and obfuscated exe everytime you do a release build.

07 March, 2011

More readable exception messages in Sharepoint 2010

I have the same trouble everytime i upgrade to a newer sharepoint version,
exception messages that doesn't tell me anything.
And everytime i search the net i find a lot of answers that is not working.

So after investigating this, i found the correct way to turn off custom error
message in sharepoint (This means enabling the display of the actual error message).

This picture shows default error meassages in sharepoint, not
very helpful when developing webparts:

Now to enable more useful error messages, which means turning OFF custom error messages:

Navigate and edit the web.config file located here:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\web.config

Change this line:
From:
<customErrors mode="On" />
To:
<customErrors mode="Off" />
Now when an exception occurs in any sharepoint site, it will look like this:

Much better, but if you are developing web parts you might want to turn on the call stack too.
To do this, navigate to the web.config file located under your web site, like:
C:\inetpub\wwwroot\wss\VirtualDirectories\MyTestSite80\web.config

Change callstack in this line:
From:
<SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">
To:
<SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">

Now when an exception occurs in any sharepoint site, it will look like this:

So just to clarify:
There is NO need to enable debug in any web.config files (debug=true).
There is NO need to change customerrors mode inside the web.config under the site, this can be left On.
There is NO need to change this file: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG\web.config.

04 March, 2011

Custom web part pages with navigation, Sharepoint 2010

So even in sharepoint 2010, microsoft has still not added an option to add custom web part pages, just unbelievable :)
So we are still stuck with editing system files manually to get the look that we want.
Another thing that really annoys me is that a web part page has no navigation on the left side , i really can't see
any use of a sharepoint page without navigation.

Anyway let's see how we can make this work a little better.

When creating a web part page in sharepoint there are 8 available types which can be selected:
Web Part PageIndexContentPageImage
Header, Footer, 3 Columns2spstd2.aspxspstd2.gif
Full Page, Vertical1spstd1.aspxspstd1.gif
Header, Left Column, Body3spstd3.aspxspstd3.gif
Header, Right Column, Body4spstd4.aspxspstd4.gif
Header, Footer, 2 Columns, 4 Rows5spstd5.aspxspstd5.gif
Header, Footer, 4 Columns, Top Row6spstd6.aspxspstd6.gif
Left Column, Header, Footer, Top Row, 3 Columns7spstd7.aspxspstd7.gif
Right Column, Header, Footer, Top Row, 3 Columns8spstd8.aspxspstd8.gif

The system content pages can be found here:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\1033\STS\DOCTEMP\SMARTPGS\spstd?.aspx
Graphical view of the types can be found here:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\IMAGES\spstd?.gif
This file links to spcf.aspx
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\1033\STS\DOCTEMP\SMARTPGS\_webpartpage.htm
This is the actual web part page creation form, which will list the 8 different options.
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\spcf.aspx

Which contains:
<select id="onetidWebPartPageTemplate" name="WebPartPageTemplate" size="8" onchange="DoTemplateOptionChange()"> 
   <option value="2" selected="true"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option2%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="1"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option1%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="3"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option3%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="4"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option4%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="5"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option5%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="6"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option6%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="7"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option7%>" EncodeMethod='HtmlEncode'/></option> 
   <option value="8"><SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,webpagecreation_layout_option8%>" EncodeMethod='HtmlEncode'/></option> 
 </select>   
For some reason the different types are listed not in sequence, 1 and 2 are switched, sloppy  :)

Soulution 1:
If you want to include the left navigation bar in web part pages, then remove these lines from all of the spstd?.aspx files
...
<style type="text/css">
body #s4-leftpanel {
display:none;
}
.s4-ca {
margin-left:0px;
}
</style>
...
<asp:Content ContentPlaceHolderId="PlaceHolderLeftNavBar" runat="server"></asp:Content>
...
This will enable navigation, removing the style element is something new in sharepoint 2010.

If you want to customize a web part page like adding more web part zones etc you need to edit one of the spstd?.aspx pages.

The part which you need to change is this (located at the bottom in the file):

<table cellpadding="4" cellspacing="0" border="0" width="100%">
        <tr>
            <td id="_invisibleIfEmpty" name="_invisibleIfEmpty" colspan="3" valign="top" width="100%">
                <webpartpages:webpartzone runat="server" title="loc:Header" id="Header" frametype="TitleBarOnly" />
            </td>
        </tr>
        <tr>
            <td id="_invisibleIfEmpty" name="_invisibleIfEmpty" valign="top" height="100%">
                <webpartpages:webpartzone runat="server" title="loc:LeftColumn" id="LeftColumn" frametype="TitleBarOnly" />
            </td>
            <td id="_invisibleIfEmpty" name="_invisibleIfEmpty" valign="top" height="100%">
                <webpartpages:webpartzone runat="server" title="loc:MiddleColumn" id="MiddleColumn"
                    frametype="TitleBarOnly" />
            </td>
            <td id="_invisibleIfEmpty" name="_invisibleIfEmpty" valign="top" height="100%">
                <webpartpages:webpartzone runat="server" title="loc:RightColumn" id="RightColumn"
                    frametype="TitleBarOnly" />
            </td>
        </tr>
        <tr>
            <td id="_invisibleIfEmpty" name="_invisibleIfEmpty" colspan="3" valign="top" width="100%">
                <webpartpages:webpartzone runat="server" title="loc:Footer" id="Footer" frametype="TitleBarOnly" />
            </td>
        </tr>
        <script type="text/javascript" language="javascript">            if (typeof (MSOLayout_MakeInvisibleIfEmpty) == "function") { MSOLayout_MakeInvisibleIfEmpty(); }</script>
    </table>
This is the default layout for spstd2.aspx.
Now you can change the table, adding more webpart zones etc. Just remember to name the zones properly.

If you change the layout it's a good idea to change the spstd?.gif image too so that it will reflect the layout.

When you change the content page and save it, it will immediatly change in sharepoint for all of the pages that are based on the modified page.


Soulution 2:
There is also another option which kinda works but will require sharepoint designer everytime you create a new page.
It's not as smooth and integrated as editing the system files.

In sharepoint desinger 2010:
  • Open the site.
  • Select site pages, select file then new page from master.
  • Inside PlaceHolderMain, add a table, inside the cells add web part zones.
  • Save it as MyTemplate.aspx
  • Close sharepoint designer.
  • Open the site, then site actions, site settings.
  • Under galleries, site content types, Create.
  • Name: SpecialWebPartPage.
  • Select Parent content type from: Document Content Types
  • Parent Content Type: Web Part Page
  • Then press ok to save.
  • Select the SpecialWebPartPage.
  • Advanced settings.
  • Change document Template to: /Sites/YourSite/SitePages/MyTemplate.aspx
  • Save.
  • Create a document library with document template: Web Part Page
  • Go into library settings for the document library.
  • Advanced settings.
  • Enable allow management of content types.
  • Save.
  • Select Add from existing site content types.
  • Select the SpecialWebPartPage.
  • Save.
  • Select  new button order and default content type.
  • Select the new content type to visible position from top = 1 (which makes it default).
  • Select the old document type to visible = false.
  • Now view the document library, select documents, click new document.
  • Sharepoint designer will be started.
  • Now save the file in the appropriate folder in the document library.
  • View the page in the document library, select edit page, now you will see the web part zones as defined in your template.
And this page has the left navigation menu intact.

Works well except that you need sharepoint designer to save the new page.

It's probably possible to make it smoother if the template is located inside the TEMPLATE\LAYOUTS folder like the basic page template bpcf.aspx.
I did a couple of tests, and it certainly treats this template in the same way as basic page template,
but ran into several problems with the masterpage and includes which required a lot of modifications of the template.
Seems like there is a lot of logic in the basic page template that needs to be adopted.
But i haven't investigated this any further.

If anyone has a better solution for this let me know :)

26 January, 2011

Static code analysis and CA2000 warning

After upgrading to visual studio 2010, i started to get a lot of CA2000 warnings when running static code analysis.

Let's look at this example function:
public static void PopulateMyTable1(HtmlTable table)
{
    table.Rows.Clear();
    HtmlTableRow row = new HtmlTableRow();
    row.ID = "MyRow";
    row.Visible = false;
    HtmlTableCell cell = new HtmlTableCell();
    cell.Attributes.Add("class", "MyClass");
    cell.Height = "20px";
    row.Cells.Add(cell);
    table.Rows.Add(row);
}

Generates these warnings:
CA2000 : Microsoft.Reliability : In method 'TestClass.PopulateMyTable1(HtmlTable)', object 'cell' is not disposed along all exception paths.
Call System.IDisposable.Dispose on object 'cell' before all references to it are out of scope.
CA2000 : Microsoft.Reliability : In method 'TestClass.PopulateMyTable1(HtmlTable)', object 'row' is not disposed along all exception paths.
Call System.IDisposable.Dispose on object 'row' before all references to it are out of scope.


The warnings are generated because we are calling properties that can cause an exception, which will cause the object not beeing disposed properly.
So how can we fix this ?

public static void PopulateMyTable2(HtmlTable table)
{
    table.Rows.Clear();
    HtmlTableRow row = null;
    try
    {
        row = new HtmlTableRow();
        row.ID = "MyRow";
        row.Visible = false;
    }
    catch (Exception)
    {
        row.Dispose();
        throw;
    }
 
    table.Rows.Add(row);
 
    HtmlTableCell cell = null;
    try
    {
        cell = new HtmlTableCell();
        cell.Attributes.Add("class", "MyClass");
        cell.Height = "20px";
    }
    catch (Exception)
    {
        cell.Dispose();
        throw;
    }
 
    row.Cells.Add(cell);            
}

This generates no CA2000 warnings, but talk about code cluttering.
Let's try something else:

public static void PopulateMyTable3(HtmlTable table)
{
    table.Rows.Clear();
    HtmlTableRow row = new HtmlTableRow();
    table.Rows.Add(row);
    row.ID = "MyRow";
    row.Visible = false;
    HtmlTableCell cell = new HtmlTableCell();
    row.Cells.Add(cell);
    cell.Attributes.Add("class", "MyClass");
    cell.Height = "20px";
}

Since we always add the new objects to the collection before calling any properties/methods then there will be no CA2000 warnings.

A much safer approach, because if an exception is thrown by calling a property then it will be taken care of when disposing the collection.

24 January, 2011

Annoying static code analysis errors in visual studio 2010

I have just upgraded to VisualStudio 2010, and ran into these annoying warnings.

CA0503 : The CodeAnalysisRules property is deprecated. Use the CodeAnalysisRuleSet property instead.
CA0505 : The CodeAnalysisRules property will be ignored because the CodeAnalysisRuleSet property is defined.

In visual studio 2008 the only way of using a centralized rules file was to add the following line to the end of
our project file:

<Import Project="C:\Projects\Applications\Common\Rules\MyCompany.CodeAnalysis.Rules.targets"/>

In 2010 you can browse for an existing rules file from within the project options.
And it will store the rules file like this:

<CodeAnalysisRuleSet>..\..\Common\Rules\MyCompany.CodeAnalysis.ruleset</CodeAnalysisRuleSet>

If you have defined both, then you will get the CA503 and CA505 errors.
So in visual studio 2010, just remove the old style import tag.