Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

The New Extension Installer Manifest – Part 4, The Assembly Component

This article is cross-posted from my personal blog.

In DotNetNuke v 4.6 a new installer system was introduced to handle the new Authentication Systems.  In DotNetNuke 5.0 we have extended the use of the Installer to all extensions, including Modules, Language Packs and Skins. 

In previous blogs in this series I introduced the new Extension Installer Manifest, and the 3 components that most developers would be fairly familiar with – Module, Assembly, File, as they are similar to the legacy module manifest, and I began to detail the individual component manifests by describing the Cleanup Component.

In this article I will dive deeper into the Assembly Component (see Listing 1).

Listing 1 - The Assembly Component manifest fragment from the FileBasedCachingProvider

   1:  <component type="Assembly">
   2:    <assemblies>
   3:      <assembly>
   4:        <path>bin\Providerspath>
   5:        <name>DotNetNuke.Caching.FileBasedCachingProvider.dllname>
   6:        <version>05.00.01version>
   7:      assembly>
   8:    assemblies>
   9:  component>

Most of the components which handle files inherit from the base File Component, and so the Assembly Component has a element and a element.  The element name for the collection is rather than and the element name for a single assembly is rather than ,  but in code the actual copying of the file is handled by the base FileInstaller.

While the element is defined for the File Component it is not really used for standard files.  However the version element is important for assemblies.

Registering Assemblies

One of the problems with earlier versions of DotNetNuke is in handling assembly versioning.  Each module, when installed just extracts its assemblies and copies them to the /bin folder, regardless of whether an existing version of the assembly is already in use. 

This makes life difficult, if module developers use 3rd party libraries of any kind – either their own shared code or controls from commercial vendors.  For example, if Module A uses Assembly A version 1 (Assembly A1) and Module B uses Assembly A version 2 (Assembly A2), then if Module A is installed after Module B it could break Module B as the older version (A1) is installed over the version Module B expects (A2).

Conversely, on uninstall, Module A will remove the associated assembly, which will again break Module B.

This situation is solved in the new Installer, by using the element and by using assembly referencing.

Listing 2 – The InstallFile method of the AssemblyInstaller

   1:  Protected Overrides Function InstallFile(ByVal file As InstallFile) As Boolean
   2:      Dim bSuccess As Boolean = True
   4:      If file.Action = "UnRegister" Then
   5:          DeleteFile(file)
   6:      Else
   7:          'Attempt to register assembly this will return False if the assembly exists
   8:          'and true if it does not or is older
   9:          Dim returnCode As Integer = DataProvider.Instance.RegisterAssembly(Me.Package.PackageID, 
  10:                                                           file.Name, file.Version.ToString(3))
  11:          Select Case returnCode
  12:              Case 0
  13:                  'Assembly Does Not Exist
  14:                  Log.AddInfo(Util.ASSEMBLY_Added + " - " + file.FullName)
  15:              Case 1
  16:                  'Older version of Assembly Exists
  17:                  Log.AddInfo(Util.ASSEMBLY_Updated + " - " + file.FullName)
  18:              Case 2, 3
  19:                  'Assembly already Registered
  20:                  Log.AddInfo(Util.ASSEMBLY_Registered + " - " + file.FullName)
  21:          End Select
  23:          'If assembly not registered, is newer (or is the same version and we are in repair mode)
  24:          If returnCode < 2 OrElse (returnCode = 2 AndAlso file.InstallerInfo.RepairInstall) Then
  25:              'Call base class version to copy file to \bin
  26:              bSuccess = MyBase.InstallFile(file)
  27:          End If
  28:      End If
  29:      Return bSuccess
  30:  End Function

The AssemblyInstaller overrides the InstallFile method of the base FileComponent (it also overrides the DeleteFile method – see later), and before copying the file into the /bin folder, it registers the assembly in the database (see Listing 2).  The RegisterAssembly method checks if the assembly is already registered by another extension and returns one of 4 return Codes.

  • 0 – Assembly does not exist
  • 1 – An older version of the assembly exists
  • 2 – The same version of the assembly exists
  • 3 – A newer version of the assembly exists

If the return code is 0 or 1 then the file is copied (as the assembly does not exist or is older than the current version) by calling the base FileInstaller class’s InstallFile method.  If the return code is 2 the assembly is only copied if we are repairing the install, and if the return code is 3 the assembly is not copied as it could potentially break another extension that is already installed.

The RegisterAssemby method adds an entry into the Assemblies table, recording the PackageID of the Extension which registered the assembly.

Figure 1 – The Assemblies Table



UnRegistering Assemblies

On uninstall the reverse process happens.  As mentioned above, the AssemblyInstaller also overrides the base FileInstaller’s DeleteFile method.

Listing 3 – The DeleteFile method of the AssemblyInstaller

   1:  Protected Overrides Sub DeleteFile(ByVal file As InstallFile)
   2:      'Attempt to unregister assembly this will return False if the 
   3:      'assembly is used by another package and cannot be delete and
   4:      'true if it is not being used and can be deleted
   5:      If DataProvider.Instance.UnRegisterAssembly(Me.Package.PackageID, file.Name) Then
   6:          Log.AddInfo(Util.ASSEMBLY_UnRegistered + " - " + file.FullName)
   7:          'Call base class version to deleteFile file from \bin
   8:          MyBase.DeleteFile(file)
   9:      Else
  10:          Log.AddInfo(Util.ASSEMBLY_InUse + " - " + file.FullName)
  11:      End If
  12:  End Sub

In the DeleteFile method (see Listing 3), the UnRegisterAssembly method is called.  This method removes the record from the assemblies table and returns a boolean value:

  • true – the registration was the only registration for this assembly and the assembly can be safely deleted
  • false – there are other extensions which still require the assembly and the assembly should not be deleted

So the result of this is that, by using assembly counting, we can improve the situation where shared assemblies are being used.  The only remaining case which could break Extensions is if a shared assembly does not retain binary compatibility in newer versions.


There are currently no comments, be the first to post one.

Comment Form

Only registered users may post comments.


2sic Daniel Mettler (124)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (21)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (269)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?