Archive

Archive for October, 2015

Adding multiple versions of the same assembly to the same single SharePoint WSP

This discovery came about when we wanted to simply deploying NLog with our Visual Studio 2013 SharePoint project components, but didn’t want to bundle it with any particular component, since removing that component would remove NLog from the GAC for all of them, even if they had each placed it there because its shared.  So, like lots of people we made up a SharePoint project to contain this dependency, among others, which was fine until we upgraded NLog versions.

In doing so we started to break older components that were looking for NLog 2.0 after we swapped out for NLog 3.2, and although we could have used assembly remapping or upgraded all of the components, neither modifying all the config files (web apps, and timer service, and tools, etc) or redeploying all the components was considered a nice transitional solution.

So, simply adding both DLLs into the SharePoint Package > under Advanced > additional assemblies looks straight forward.  A dependency folder was added to the solution, with a sub folder for each version, and both of those versions were added as additional assemblies to be deployed to the GAC.  Both were added, from different ‘Source Paths’ (“..\Dependencies\NLog_2.0\NLog.dll” and “..\Dependencies\NLog_3.2\NLog.dll”), both deployed to the GAC, and both with the same default ‘Location’ value of “NLog.dll”.

Publish… and Fail…

Package.package : error SPT16: Both “MySharePointWSP.Logging” and “MySharePointWSP.Logging” contain a file that deploys to the same Package location: NLog.dll

HUH????

So I search online for that type of error, and found little, apart a hint about making the Location of each match the Source Path… well the VS SharePoint dialog didn’t like that at all… but after some experimenting I noticed something… it was ok with partial paths, and that these paths were used for the GAC sub paths under the assembly folder.  Well, with a bit more mucking about, and individually deploying each I copied the GAC paths, trimmed them down to just the assembly specific portion and placed them in the ‘Location’, and to my delight, it worked.  Even though they were both going to a different GAC (C:\Windows\assembly\GAC_MSIL\NLog and C:\Windows\Microsoft.NET\assembly\GAC_MSIL\NLog), both deployed to the right place when I explicitly provided the location with include the version/public key info.

The NLog 2.0 assembly reference in the SharePoint Package > Advanced > Additional assemblies had “NLog\2.0.0.0__5120e14c03d0593c\NLog.dll” as its location, and the NLog 3.2 assembly reference had “NLog\v4.0_3.2.0.0__5120e14c03d0593c\NLog.dll” as its location.

The Package.package file contents looked like this…

<assemblies>

    <customAssembly location=”NLog\2.0.0.0__5120e14c03d0593c\NLog.dll” deploymentTarget=”GlobalAssemblyCache” sourcePath=”..\Dependencies\NLog_2.0\NLog.dll” />

    <customAssembly location=”NLog\v4.0_3.2.0.0__5120e14c03d0593c\NLog.dll” deploymentTarget=”GlobalAssemblyCache” sourcePath=”..\Dependencies\NLog_3.2\NLog.dll” />

</assemblies>

So its odd, but what I took away from this is that it looks like the packaging process tries to validate the Locations, looking for possible conflicts, not taking into account that the fully qualified paths when they go into the GAC (regardless of the old or new GAC) will be different by version and key.  Manually putting the versioned/keyed path, makes them unique and deploy as normal, and once the next version of NLog comes out, I expect to see it in the new GAC along side the NLog 3.2 version, and the NLog 2.0 version still in the old GAC, all deployed from one WSP.


Update…

Adding the latest NLog 4.0 to by package also worked with the addition of the additional assembly.  The default location also worked, as it didn’t conflict since the other two were explicit, but I expanded it myself as well and so the Package,package file also contained this line:

<customAssembly location=”NLog\v4.0_4.0.0.0__5120e14c03d0593c\NLog.dll” deploymentTarget=”GlobalAssemblyCache” sourcePath=”..\Dependencies\NLog_4.1.2\NLog.dll” />

And I now have all three NLog assemblies deploying, one to the old GAC and two to the new GAC all from a single WSP.

Importing PowerShell Modules from GAC DLLS in order to use their CmdLets

What I am writing here is nothing new, just a consolidation of attempted answers I found when trying to do as the title of this post describes.  Now to set the stage, this is a DLL deployed as part of a SharePoint solution which is why it gets dropped to the GAC and then the CmdLets are used to configure the solution once the SharePoint WSPs are deployed.

Import-Module will take a full path to a DLL in the GAC or anywhere in order to use the CmdLets within it, but I didn’t want to be mucking with resolving the GAC path for a DLL, I just wanted to give it the assembly name without version and what not.  In looking at other people comments to loading DLLs with partial name, the obvious “LoadWithPartialName” was mentioned, however that will load the DLL into memory, but doesn’t load them as modules for CmdLet use…

Chaining the two commands together does work nicely though:

$assembly = [System.Reflection.Assembly]::LoadWithPartialName(‘MyProject.PowerShell’)

Import-Module -Assembly $assembly

New-ObjectToPerformTask -Url $url

It’s nothing special, but a nice complete way to load PowerShell cmdlets using partial names from the GAC, so its great for SharePoint deployed DLLs.