Merging .NET assemblies using ILMerge

Today I had a problem about multiple dll registration plugin for MSCRM. This plugin was registered on Database and I could not update this one because I needed the others libraries. I had two soltions: First, I could register it on GAC. I don’t like because I had problem on production during the installation of the new solution. The second one was to use ILMERGE to merge all dll and create an unique dll to register. I choose the second solution. ILMerge is useful tool on Microsoft. This little gem makes it possible to link multiple assemblies to a single one.

First, you would compile your libraries to DLLs and your program to an EXE referencing the DLLs. This is exactly what Visual Studio would do if you had multiple libraries and a program referencing these libraries, so there is no need to do this on the command line.

Later you can link these parts to a single self-contained EXE, DLL, using ILMerge:

echo %1
%1Build\ILMerge.exe /keyfile:%1Properties\keys.snk /target:library /copyattrs /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:%1Build\final\namedll %1Build\library.dll %1Build\Castle.Core.dll %1Build\Castle.Windsor.dll %1Build\Microsoft.WITDataStore.dll %1Build\Newtonsoft.Json.dll %1Build\Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll

The nice thing about this is that you can also merge third party assemblies like commercial class libraries into your program. And you do not have to modify your build process.

I found ILMerge tremendously useful, and I think that something like this should be a part of the .NET framework SDK. Maybe just enhance al.exe so that it can also link DLLs.

I have only scratched the surface of the .NET build process and the capabilities of ILMerge, and this article might contain many inaccuracies or even errors. But I found ilmerge.exe so useful that I just had to write about it.

I found a GUID for MERGE,

image_thumb_681250B1

but I prefer the line command. I insert on build process this rows:

copy /Y "$(TargetDir)" "$(ProjectDir)Build"
call "$(ProjectDir)Build\Merge.bat" $(ProjectDir)
cd "$(ProjectDir)Build"
del *.dll *.pdb Winvs*

In this way, after the build, all dlls are copied on Build folder and the Merge command is called. The merge.bat is the following:

echo %1
%1Build\ILMerge.exe /keyfile:%1Properties\keys.snk /target:library /copyattrs /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:%1Build\final\namedll %1Build\library.dll %1Build\Castle.Core.dll %1Build\Castle.Windsor.dll %1Build\Microsoft.WITDataStore.dll %1Build\Newtonsoft.Json.dll %1Build\Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll

Changing local path in team foundation server

application-lifecycle-managementIf you want to change the local path for the working directory of the Team Foundation Server (TFS), you need to go to File -> Source Control -> Workspaces, then select your workspace (it should match your computer name) and click Edit.

In the next dialog change the mapping for the root TFS node to the new location on your hard drive.

Important! You need to perform a “Get” on the whole TFS tree to update project associations.

Lync commands in powershell

imagesEd ecco a grande richiesta come gestire Lync con powershell. Ho notato che e’ veramente difficile trovare informazioni ed esempi relativi al’utilizzo dei comandi Lync in poweshell.Prima di tutto ecco il link per partire: La guida technet ai comandi Lync. Adesso possiamo iniziare a vedere un po’ di codice:

Ricordiamoci di importare il modulo di lync per poter utilizzare i suoi comandi:

Import-Module 'C:\Program Files\Common Files\Microsoft Lync Server 2013\Modules\Lync\Lync.psd1'

Se volessimo avere la lista di tutti gli utenti ecco il codice:

$users = Get-CsUser -Filter {RegistrarPool -eq "lync.server"} | select sipaddress
foreach ($user in $users)
{
$usermail = $user.Split(":")
Write-Host $usermail
}

In questo modo abbiamo chiesto di avere una lista di tutte le mail registrate su lync e di stamparle a video. Per avere tutti i dati dell’utente bastera’
eliminare la select finale.

Un’altro comando inderessante e’ Export-CsUserData: la sua descrizione e’:
“Exports user data in a format that can be imported into Microsoft Exchange Server 2013. The data will be exported as a .ZIP file containing a pair of XML documents. This cmdlet was introduced in Lync Server 2013.”

Ed ecco il codice:

Export-CsUserData -FileName $zipfile –UserFilter $ExportEmail -PoolFqdn "lync.server"

L’ultimo comando che ho utilizzato e’ Update-CsUserData. Questo serve per aggiornare i contatti di ogni user:

Update-CsUserData -FileName $zipFile -Confirm:$False

Notare l’uso dell’attributo -Confirm:$False: Questo mi forza la conferma del comando senza visualizzazione di un messaggio di conferma. E’ molto utile
vogliamo inserire il comando in uno script automatico.

E finalmente ecco il codice completo, naturalmente sempre nel mio repository GitHub: Le funzionalita’ di questo script sono le seguenti:

  • Esportazione della lista contatti
  • Unzip dell’esportazione
  • Modifica del file xml generato da Lync
  • Check e validazione delle mail
  • Zip delle modifiche
  • Update lista contatti

Questo viene eseguito per ogni utente di Lync, E’ molto utile durante la migrazione di Lync 2010 a Lync 2013. Di seguito il suo utilizzo:

LyncContacts.ps1 –UserEmail all –ExportEmail email@email.it In questo modo migriamo tutti gli utenti e per ogni utente usiamo la lista contatti ExportEmail come default

LyncContacts.ps1 –UserEmail email@email.com –ExportEmail email@email.it In questo caso migriamo solo un user e utilizziamo la ExportMail come default dei contatti

Spero di essere stato utile a qualcuno.

PowerShell

imagesSono due giorni che sto “smanettando” con powershell: Sto creando una poweshell per importare i contatti Lync (Migrazione da Lync 2010 a Lync2013). Per risolvere il problema ho dovuto crearmi una lista di utenti lync e ciclare su ogni utente. Per ognuno ho dovuto creare un file zip, modificare un file xml e poi eseguire un altro comando della powershell di lync.

Dato che non sono molto pratico di powershell ho cercato un po’ su internet e alla fine sono riuscito a creare tutto quello che mi serviva, senza importare nessuna libreria esterna ma utilizzando la potenza di powershell. Vediamo come ho risolto il tutto:
Per iniziare mi sono creato dei metodi base per la gestione degli zip, delle cartelle e del file xml:
In questo post vedremo questo. Magari in futuro vi faro’ vedere i comandi lync… 🙂

Prima di tutto ho creato delle cartelle temporanee per poter lavorare in tranquillita’:

#Tmp dir
$folderTmp = "C:\TmpLync\"
$folderTmpContact = "C:\TmpLync\Contacts"
#********************************************************************************************************************************************
#Start TMP FOLDER
#********************************************************************************************************************************************
#Clean and create all tmp dir
if (!(Test-Path $folderTmp)) {
# create it
[void](new-item $folderTmp -itemType directory)
}
if (!(Test-Path $folderTmpContact)) {
# create it
[void](new-item $folderTmpContact -itemType directory)
}

Poi ho creato le funzioni per zippare ed unzippare cartelle

function UnZipMe($zipfilename,$destination)
{
   $shellApplication = new-object -com shell.application
   $zipPackage = $shellApplication.NameSpace($zipfilename)
   $destinationFolder = $shellApplication.NameSpace($destination)
	# CopyHere vOptions Flag # 4 - Do not display a progress dialog box.
	# 16 - Respond with "Yes to All" for any dialog box that is displayed.
	$destinationFolder.CopyHere($zipPackage.Items(),20)
}

function ZipMe($srcdir,$ZipFileName,$zipFilepath )
{
		$zipFile = "$zipFilepath$zipFilename"
		#Prepare zip file
		if(-not (test-path($zipFile))) {
		    set-content $zipFile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
		    (dir $zipFile).IsReadOnly = $false
		}

		$shellApplication = new-object -com shell.application
		$zipPackage = $shellApplication.NameSpace($zipFile)
		$files = Get-ChildItem -Path $srcdir | where{! $_.PSIsContainer}

		foreach($file in $files) {
		    $zipPackage.CopyHere($file.FullName)
			#using this method, sometimes files can be 'skipped'
			#this 'while' loop checks each file is added before moving to the next
		    while($zipPackage.Items().Item($file.name) -eq $null){
		        Start-sleep -seconds 1
		    }
		}
}

L’utilizzo di queste due funzioni e’ semplicissimo:
Per unzippare:

$zipFilename = "contacts.zip"
$a = gci -Path $folderTmpContact -Filter $zipFilename
foreach($file in $a)
{
    Write-Host "Processing - $file" UnZipMe –zipfilename
    UnZipMe –zipfilename $file.FullName -destination $file.DirectoryName
}

Per zippare:

$srcdir = $folderTmpContact
$zipFilepath = $folderTmp
ZipMe -srcdir $srcdir -zipFileName $ZipFileName -zipFilePath $zipFilepath

La parte piu’ complessa e’ stata la gestione e la modifica del file XML: Ho provato ad utilizzare i comandi standard per leggere un file xml:

$xml = New-Object XML
$xml = [xml](get-content "c:\test\DocItemSet.xml")
$email = $xml.DocItemSet.DocItem[0].name

Ma la stringa da ricercare non aveva logica e il file xml poteva cambiare. Alla fine ho deciso di utilizzare una semplice ricerca e modifica:

$original_file = "c:\test\DocItemSet.xml"
$destination_file =  "c:\test\DocItemSet.xml.new"
(Get-Content $original_file) | Foreach-Object {
    $_ -replace $email, 'something1aa'
    } | Set-Content $destination_file

In questo modo ricerco, modifico e faccio anche un backup del file.
Per lavorare e per debuggare poweshell ho utilizzato PowerGUI mentre per un ottimo punto di partenza per powershell consiglio questi link:

http://powershell.com/
http://powershell.it/Comandi/v1.0/Get-Content.aspx
http://powershell.it/Tutorial/Introduzione-a-PowerShell.aspx

NB: Se abbiamo il seguente errore File xyz.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see “get-help about_signing” for more details. Esesguiamo la console powershell ed eseguiamo il seguente comando:
Set-ExecutionPolicy Unrestricted -Force
Set-ExecutionPolicy RemoteSigned -Force

Spero di essere stato utile…
Buon divertimento a tutti!!!

Utilizzare WordPress con C#

imagesFinalmente ho deciso (e trovato il tempo) di creare il mio sito personale (ormai tutti hanno un sito personale 🙂 ).

In home page voglio dare la possibilita’ di visualizzare i post principali che scrivo su wordpress; per fare questo ho pensato a diverse soluzioni:

  • converto tutto in .NEt sbarazzandomi di WordPress
  • decido di utilizzare wordpress sui miei server e quindi avere controllo anche del database (in questo modo posso fare le query direttamente sul db)
  • cerco su internet qualche plugin o framework che mi possa aiutare ad integrare wordpress nel mio sito.
  • utilizzare webhooks per pushare le informazioni direttamente dal blog di WordPress
  • dato che voglio solo visualizzare i miei posts e non voglio inserire post direttamente da .net, si puo’ leggere direttamente rss feed che rendo disponibile da mio sito.

Per adesso ho deciso di utilizzare l’ultima possibilita’: meno costosa (gratis)… piu’ semplice da utilizzare e piu’ veloce da fare.

Prima di tutto creiamo il modello di oggetto che identifica il  POST:

public class Post
{
   public string Title { get; set; }
   public string Url { get; set; }
   public string Author {get; set;}
   public DateTime PublishedDate { get; set; }
}

Adesso andiamo a leggere i post dal link del mio rss feed di wordpress. Ho creato un semplice parser per leggere queste informazioni:

public static IList GetBlogPosts(string postUrl, int postCount)
{

string xml;

using (WebClient downloader = new WebClient())
{
   using (TextReader reader =
      new StreamReader(downloader.OpenRead(postUrl)))
{
xml = reader.ReadToEnd();
}
}
// Sanitize the XML
xml = XmlCommon.SanitizeXmlString(xml);
XmlDocument xmlDoc = new XmlDocument();
//Load feed via a feedUrl.
TextReader tr = new StringReader(xml);
var doc = XDocument.Load(tr);

XNamespace dc= "http://purl.org/dc/elements/1.1/";

//Get all the "items" in the feed.
var feeds = doc.Descendants("item").Select(x =>
new Post
{
//Get title, pubished date, and link elements.
Title = x.Element("title").Value, //3
PublishedDate = DateTime.Parse(x.Element("pubDate").Value),
Author = x.Element(dc + "creator").Value,
Url = x.Element("link").Value
} //  Put them into an object (Post)
)
// Order them by the pubDate (Post.PublishedDate).
.OrderByDescending(x=> x.PublishedDate)
//Only get the amount specified, the top (1, 2, 3, etc.) via postCount.
.Take(postCount);

//Convert the feeds to a List and return them.
return feeds.ToList();
}

Volevo farvi notare la seguente riga di codice:

xml = XmlCommon.SanitizeXmlString(xml);

In questo modo andremo a ripulire il nostro XML. Il file rss di wordpress viene creato con dei caratteri non validi per le specifiche XML.Qui trovate un articolo che spiega meglio il pattern utilizzato.

Infine se potremmo anche creare una cache per non rallentare il caricamento. Ecco qualche lineea di codice:

//Check if feed exists
if (HttpRuntime.Cache["WordPressPost"] == null)
				{
					//If it is, insert it into the cache, cache for 10 minutes
					HttpRuntime.Cache.Insert("WordPressPost",
						FeedReader.GetBlogFeed("url", 5), null, SystemTime.Now().AddMinutes(10), Cache.NoSlidingExpiration);
				}

//retrieve cached feeds
var cachedFeeds = (List) HttpRuntime.Cache["WordPressPost"]

Ora possiamo avere i nostri post di worpress nella nostra homepage. Ho creato un piccolo progetto di esempio in Github

Cercando su google ho trovato WP.NET e un ottimo articolo sol suo utilizzo : Extending-WordPress-with-Csharp-Plugins. Con WP.Net e’ possibile utilizzare wordpress con .net.

Snoop WPF un aiuto prezioso!!!

Molte volte, a me capita spesso con wpf, un layout a runtime ha un funzionamento differente da quello aspettato. Potrebbe essere difficile visualizzare a codice alcuni oggetti ( magari vengono creati automaticamente: pensate ad una treeview). Un mio collega qualche tempo fa mi ha suggerito un tools chiamato Snoop: Da quel giorno non ne posso fare a meno!!!!!!!!!

Con snoop potrai spiare a runtime tutto il tuo codice, visualizzare il layout in 3D per capire come i content panel funzionano e modificare a runtime le proprieta’ degli elementi sul tuo progetto!!!

Il suo utilizzo e’ sempliccissimo: Eseguiamo la nostra applicazione e poi eseguiamo snoop. Dal menu (vedi immagine seguente) selezionare il mirino vicino al cannocchiale e trascinarlo sulla nostra applicazione.

Adesso e’ possibile navigare il nostro albero e modificare le proprieta’ oppure visualiizare il layout in 3d…. Lo reputo un aiuto prezioso per debuggare il nostro WPF!!!

Per una documentazione approfondita ecco il link: http://blois.us/Snoop/

Fatemi sapere cosa ne pensate. Io lo trovo eccezionale.

Layout 3D e Proprieta’ Layout

Visual Studio 11 – Prime impressioni

Oggi ho iniziato ad utilizzare e muovere i primi passi con Visual Studio 2011. Abbiamo decisio di inizare ad utilizzare VS2011 e MV4 per sviluppare un nostro nuovo progetto anche se ancora in versione developer e non in versione definitiva. Questo perche’ lo sviluppo durera’ circa 15 mesi e per allora ci saranno le versioni definitive.

La prima cosa che si puo’ notare e’ la sinergia tra la nuova versione di Microsof Windows, Windows 8, e Visual Studio 11. L’interfaccia visuale, molto semplice ed intuita e diciamo anche essenziale, mostra i seguenti punti di forza:
Continua a leggere