Introduction
The DNN Module Packager is a utility that creates a DotNetNuke manifest file and packages the module into a ZIP file for deployment to a DotNetNuke 3.x or DotNetNuke 4.x hosting site. You can edit the manifest file before packaging, and also add any other files to the package that your module needs to function properly in a DotNetNuke environment. The DNN manifest file is simply an XML file that contains information about the module, its DNN-interface controls (like View, Edit, and Settings controls), and a listing of all the folders, files, and binaries needed by the module.
Using the DNN Module Packager
The DNN Module Packager requires the basic .DNN manifest file that is automatically created by the DotNetNuke module templates in Visual Studio. If you don't have a .DNN manifest, you can always copy one from the DotNetNuke installation and modify it for your own module.
The basic steps for packaging a DNN module are:
- Select the .DNN manifest file.
- Select the root of the module directory.
- Select the target Zip output directory and filename.
- Generate the manifest (and perform edits to the manifest if needed).
- Add any other DLLs, code files, or other files needed in the package.
- Generate the package.
Another useful feature is the ability to automatically exclude any files that have particular extensions that reside in the module directory and its subdirectories that you don't want included in the manifest or the package (like VSS and other source-control files).
Below is a quick overview of the packaging process and the various screens/tabs in the DNN Module Packager:
Sample DNN Module Package with Additional Files
Sample DNN Module Package Manifest
Results of the DNN Module Packaging
How the DNN Module Packager Works
The main engine/processor of the DNN Module Packager is the DnnGenerator
class. Its primary function is to enumerate all the files under the module's root directory (and subdirectories) and add them to the DNN manifest as folder/file XML nodes. The DnnGenerator
class also maintains a list of all the files in the package, and is responsible for assembling the final 'product': the zipped DNN module package.
class DnnGenerator
{
public static string GenerateProjectDnnConfig(string sOldDnnFilePath,
string sProjectPath, string sExcludeExts, ArrayList aryOtherFiles)
{
string sNewDnnFile = string.Empty;
if (File.Exists(sOldDnnFilePath) == false)
{
throw new Exception("Specified .DNN manifest file does not exist!");
}
if (Directory.Exists(sProjectPath) == false)
{
throw new Exception("Specified DNN Module project path does not exist!");
}
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(sOldDnnFilePath);
XmlNode node = xmlDoc.SelectSingleNode("/dotnetnuke/folders/folder/files");
node.RemoveAll();
ArrayList aryFiles = FileUtilities.GetFilesInFolder(sProjectPath, true);
string[] _ExcludeExts = sExcludeExts.Split(',');
ArrayList aryExcludeExts = new ArrayList();
foreach (string sExt in _ExcludeExts)
{
aryExcludeExts.Add(sExt.Trim().ToLower());
}
foreach (string sfile in aryFiles)
{
FileInfo fi = new FileInfo(sfile);
if (aryExcludeExts.Contains(fi.Extension.Trim().ToLower()) == true)
{
continue;
}
XmlElement xnfile = xmlDoc.CreateElement("file");
node.AppendChild(xnfile);
string srelpath = FileUtilities.RelativePathTo(sProjectPath,
fi.DirectoryName);
if (srelpath.Length > 0)
{
XmlElement xnpath = xmlDoc.CreateElement("path");
xnfile.AppendChild(xnpath);
xnpath.InnerText = srelpath;
}
XmlElement xnname = xmlDoc.CreateElement("name");
xnfile.AppendChild(xnname);
xnname.InnerText = fi.Name;
}
foreach (string sotherfile in aryOtherFiles)
{
FileInfo fi = new FileInfo(sotherfile);
XmlElement xnfile = xmlDoc.CreateElement("file");
node.AppendChild(xnfile);
if (fi.FullName.ToUpper().IndexOf("\\APP_CODE\\") >= 0)
{
XmlElement xnpath = xmlDoc.CreateElement("path");
xnfile.AppendChild(xnpath);
xnpath.InnerText = "[app_code]";
}
XmlElement xnname = xmlDoc.CreateElement("name");
xnfile.AppendChild(xnname);
xnname.InnerText = fi.Name;
}
return xmlDoc.InnerXml;
}
public static void SaveNewDnnConfigFile(string sOldDnnFilePath, string sNewContents)
{
string sNewDnnFilePath = Path.GetTempFileName();
FileUtilities.WriteFileContents(sNewDnnFilePath, sNewContents, true);
File.Delete(sOldDnnFilePath);
File.Move(sNewDnnFilePath, sOldDnnFilePath);
}
public static void GenerateDnnModulePackage(string sZipDestFile,
string sProjectPath, string sExcludeExts, ArrayList aryOtherFiles)
{
ArrayList aryFiles = FileUtilities.GetFilesInFolder(sProjectPath, true);
aryFiles.AddRange(aryOtherFiles);
aryFiles = DnnGenerator.RemoveExcludedFiles(sExcludeExts, aryFiles);
FileUtilities.ZipFiles(sZipDestFile, null, aryFiles);
}
private static ArrayList RemoveExcludedFiles(string sExcludeExts,
ArrayList aryOtherFiles)
{
ArrayList aryFiles = new ArrayList();
ArrayList aryExcludeExts = new ArrayList();
string[] _ExcludeExts = sExcludeExts.Split(',');
foreach (string sExt in _ExcludeExts)
{
aryExcludeExts.Add(sExt.Trim().ToLower());
}
foreach (string sfile in aryOtherFiles)
{
FileInfo fi = new FileInfo(sfile);
if (aryExcludeExts.Contains(fi.Extension.Trim().ToLower()) == true)
{
continue;
}
aryFiles.Add(sfile);
}
return aryFiles;
}
}
Conclusion
I hope you find this article and utility useful - I've found it to make packaging and deploying DNN modules a snap!