Thursday, July 29, 2010
 Now reading ...
Dec
5
Sat
Posted By Subodh on Saturday, December 05, 2009
1328 Views


Packaging multiple DNN Modules in DotnetNuke 5.0+

How does somebody package a DNN module? Login as host, go to Module Definitions, hit Edit on the module you want to package and voila, there’s a Create Package button!

 

How do you create a package from command line? Or, how do you create a package that contains multiple packages? I have to admit, I couldn’t Google enough to find a solution. having spent a fair part of my Saturday looking for a solution, I just ended up experimenting. And writing my own solution.

The Oracles of DNN, the keepers of all knowledge, please tell me if I recreated something already available out there? No, I’m not talking about NANT. All I wanted was an easy way to package a few modules as one! For DNN 5.0 (since you changed the Package Installer). There are a lot of sites out there that claim that having multiple package nodes inside of <packages> node would create a package that can install multiple modules. I tried editing the .dnn file. But the installer just won’t create a package. So, here it goes; a down and dirty 30 minute C# code that can create a package straight via command line. And now I don’t need NANT, I don’t need the UI way of packaging. Just  simple port build command line would do.

 

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Diagnostics;
   6: using System.IO;
   7: using System.Xml;
   8: using ICSharpCode.SharpZipLib.Zip;
   9: namespace Subodh.Modules.DNNPackager
  10: {
  11:     class Program
  12:     {
  13:         static void Main(string[] args)
  14:         {
  15:             if (args.Length < 3) PrintUsage();
  16:             if (args.Length >= 3)
  17:             {
  18:                 string sSourceDirectory = args[0];
  19:                 string sManifestFileName = args[1];
  20:                 string sManifestFilePathFull = sSourceDirectory + "\\" + sManifestFileName;
  21:                 string sTargetPath= args[2];
  22:                 string sPackageName = "";
  23:                 XmlDocument xManifest = new XmlDocument();
  24:                 xManifest.Load(sManifestFilePathFull);
  25:                 string sManifestRootNode = xManifest.DocumentElement.Name;
  26:                 if (sManifestRootNode == "dotnetnuke")
  27:                 {
  28:                     XmlNodeList xPackages= xManifest.SelectNodes("//packages/package[@type='Module']");
  29:                     if (xPackages.Count > 0)
  30:                     {
  31:                         XmlElement xFirstPackageNode = (XmlElement)xPackages[0];
  32:                         string sPkg1Name = xFirstPackageNode.GetAttribute ("name");
  33:                         string sPkg1Version= xFirstPackageNode.GetAttribute ("version");
  34:                         if (sPkg1Name != "" && sPkg1Version != "")
  35:                         {
  36:                             sPackageName = sPkg1Name + "_" + sPkg1Version;
  37:                         }
  38:                         else ExitWith(2, "Cant find name and version");
  39:                         string sWorkingDirectory = System.IO.Directory.GetCurrentDirectory() +"\\Temp";
  40:                         if (Directory.Exists(sWorkingDirectory)) Directory.Delete(sWorkingDirectory, true);
  41:                         DirectoryInfo di = Directory.CreateDirectory(sWorkingDirectory);
  42:                         foreach (XmlElement xPackage in xPackages)
  43:                         {
  44:                             CopyFiles(sSourceDirectory, di.FullName, xPackage);
  45:                         }
  46:                         CopyFile(sSourceDirectory, di.FullName, sManifestFileName);
  47:                         BuildCompressedPackage(di.FullName, System.IO.Directory.GetCurrentDirectory(), sPackageName + ".zip");
  48:                         
  49:                     }
  50:                     else ExitWith(1, "Unable to find any module package declarations");
  51:  
  52:                 }
  53:                 else ExitWith(1, "Not a DNN package type");
  54:             }
  55:             ;
  56:  
  57:         }
  58:  
  59:         private static void CopyFiles(string sSourceDir, string sTargetDir, XmlNode xPackage)
  60:         {
  61:             XmlElement xLicense = (XmlElement)xPackage.SelectSingleNode("license");
  62:             XmlElement xReleaseNotes = (XmlElement)xPackage.SelectSingleNode("releaseNotes");
  63:             if (xLicense != null)
  64:             {
  65:                 if (xLicense.HasAttribute("src")) CopyFile(sSourceDir, sTargetDir, xLicense.GetAttribute("src"));
  66:             }
  67:             if (xReleaseNotes != null)
  68:             {
  69:                 if (xReleaseNotes.HasAttribute("src")) CopyFile(sSourceDir, sTargetDir, xReleaseNotes.GetAttribute("src"));
  70:             }
  71:  
  72:             XmlNode xScriptComponent = xPackage.SelectSingleNode("components/component[@type='Script']");
  73:             XmlNode xModuleComponent = xPackage.SelectSingleNode("components/component[@type='Module']");
  74:             XmlNode xAssemblyComponent = xPackage.SelectSingleNode("components/component[@type='Assembly']");
  75:             XmlNode xFileComponent = xPackage.SelectSingleNode("components/component[@type='File']");
  76:             if (xScriptComponent!=null) CopyFilesFromScriptComponents(sSourceDir, sTargetDir, xScriptComponent);
  77:             if (xModuleComponent!=null) CopyFilesFromModuleComponents(sSourceDir, sTargetDir, xModuleComponent);
  78:             if (xAssemblyComponent!=null) CopyFilesFromAssemblyComponents(sSourceDir, sTargetDir, xAssemblyComponent);
  79:             if (xFileComponent!=null) CopyFilesFromFileComponents(sSourceDir, sTargetDir, xFileComponent);
  80:  
  81:         }
  82:         private static void CopyFilesFromFileComponents(string sSourceDir, string sTargetDir, XmlNode xFileComponent)
  83:         {
  84:             string sbasePath = "";
  85:             XmlElement xBasePath = (XmlElement)xFileComponent.SelectSingleNode("files/basePath");
  86:             if (xBasePath != null) sbasePath = xBasePath.InnerText.Trim();
  87:             if (sSourceDir.EndsWith(sbasePath)) sbasePath = "";
  88:             XmlNodeList xFiles = xFileComponent.SelectNodes("files/file");
  89:             foreach (XmlNode xFile in xFiles)
  90:             {
  91:                 XmlNode xPath = xFile.SelectSingleNode("path");
  92:                 XmlNode xName = xFile.SelectSingleNode("name");
  93:                 string sFileName = xName.InnerText.Trim();
  94:                 string sSourceDir2 = sSourceDir + "\\" + sbasePath + "\\";
  95:                 string sTargetDir2 = sTargetDir + "\\" + sbasePath + "\\";
  96:                 if (xPath != null && xPath.InnerText != "")
  97:                 {
  98:                     sSourceDir2 += xPath.InnerText.Trim();
  99:                     sTargetDir2 += xPath.InnerText.Trim();
 100:                 }
 101:                 CopyFile(sSourceDir2, sTargetDir2, sFileName);
 102:             }
 103:         }
 104:         private static void CopyFilesFromAssemblyComponents(string sSourceDir, string sTargetDir, XmlNode xAssemblyComponent)
 105:         {
 106:             string sbasePath = "";
 107:             XmlElement xBasePath = (XmlElement)xAssemblyComponent.SelectSingleNode("assemblies/basePath");
 108:             if (xBasePath != null) sbasePath = xBasePath.InnerText.Trim();
 109:             if (sSourceDir.EndsWith(sbasePath)) sbasePath = "";
 110:             XmlNodeList xAssemblies = xAssemblyComponent.SelectNodes("assemblies/assembly");
 111:             foreach (XmlNode xAssembly in xAssemblies)
 112:             {
 113:                 XmlNode xName = xAssembly.SelectSingleNode("name");
 114:                 string sFileName = xName.InnerText.Trim();
 115:                 string sReplPath = "";
 116:                 if (sSourceDir.ToLower().IndexOf("\\desktopmodules") > 0)
 117:                 {
 118:                     sReplPath = sSourceDir.Substring(sSourceDir.ToLower().IndexOf("\\desktopmodules"));
 119:                 }
 120:                 string sSourceDir2 = sSourceDir.Replace (sReplPath,"") + "\\"+sbasePath;
 121:                 string sTargetDir2 = sTargetDir + "\\" + sbasePath + "\\";
 122:                 CopyFile(sSourceDir2, sTargetDir2, sFileName);
 123:             }
 124:         }
 125:         private static void CopyFilesFromScriptComponents(string sSourceDir, string sTargetDir, XmlNode xScriptComponent)
 126:         {
 127:             string sbasePath = "";
 128:             XmlElement xBasePath = (XmlElement )xScriptComponent.SelectSingleNode("scripts/basePath");
 129:             if (xBasePath != null) sbasePath = xBasePath.InnerText.Trim();
 130:             if (sSourceDir.EndsWith(sbasePath)) sbasePath = "";
 131:             XmlNodeList xInstallScripts = xScriptComponent.SelectNodes("scripts/script[@type='Install' or @type='UnInstall']");
 132:             foreach (XmlNode xScript in xInstallScripts)
 133:             {
 134:                 XmlNode xPath = xScript.SelectSingleNode("path");
 135:                 XmlNode xName = xScript.SelectSingleNode("name");
 136:                 string sFileName = xName.InnerText.Trim();
 137:                 string sSourceDir2 = sSourceDir + "\\" + sbasePath + "\\";
 138:                 string sTargetDir2 = sTargetDir  + "\\" + sbasePath + "\\";
 139:                 if (xPath != null && xPath.InnerText != "")
 140:                 {
 141:                     sSourceDir2 += xPath.InnerText.Trim();
 142:                     sTargetDir2 += xPath.InnerText.Trim();
 143:                 }
 144:                 CopyFile(sSourceDir2, sTargetDir2, sFileName);
 145:             }
 146:         }
 147:         private static void CopyFilesFromModuleComponents(string sSourceDir, string sTargetDir, XmlNode xModuleComponent)
 148:         {
 149:             XmlNodeList xControlSrcs = xModuleComponent.SelectNodes("desktopModule/moduleDefinitions/moduleDefinition/moduleControls/moduleControl/controlSrc");
 150:             foreach (XmlNode xControlSrc in xControlSrcs)
 151:             {
 152:                 string sControlPath = ((XmlElement) xControlSrc).InnerText.Trim();
 153:                 string sReplPath="";
 154:                 if (sSourceDir.ToLower().IndexOf("\\desktopmodules") > 0)
 155:                 {
 156:                     sReplPath = sSourceDir.Substring(sSourceDir.ToLower().IndexOf("\\desktopmodules"));
 157:                 }
 158:                 sControlPath = sControlPath.Replace("/", "\\");
 159:                 //string sTargetDir2 = sTargetDir + sReplPath;
 160:                 if (sReplPath.StartsWith("\\")) sReplPath = sReplPath.Substring(1);
 161:                 sControlPath = sControlPath.Replace(sReplPath+"\\", "");
 162:                 CopyFile(sSourceDir, sTargetDir, sControlPath);
 163:             }
 164:         }
 165:         private static void CopyFile(string sSourceDir, string sTargetDir, string sFileName)
 166:         {
 167:             try
 168:             {
 169:                 string sSourcePath = sSourceDir + "\\" + sFileName;
 170:                 string sTargetPath = sTargetDir + "\\" + sFileName;
 171:                 sSourcePath = sSourcePath.Replace("\\\\", "\\");
 172:                 sTargetPath = sTargetPath.Replace("\\\\", "\\");
 173:                 sSourcePath = sSourcePath.Replace("\\\\", "\\");
 174:                 sTargetPath = sTargetPath.Replace("\\\\", "\\");
 175:                 if (!Directory.Exists(sTargetPath.Replace("\\" + sFileName,""))) Directory.CreateDirectory(sTargetPath.Replace("\\" + sFileName,""));
 176:                 File.Copy(sSourcePath, sTargetPath,true);
 177:             }
 178:             catch (Exception exp)
 179:             {
 180:                 ExitWith(5, "Could not find File " + exp.Message);
 181:             }
 182:         }
 183:  
 184:  
 185:         private static void BuildCompressedPackage(string SourceDirectory, string PackagePath, string PackageName)
 186:         {
 187:             try
 188:             {
 189:                 
 190:                 using (ZipOutputStream s = new ZipOutputStream(File.Create(PackagePath + "\\" + PackageName + ".zip")))
 191:                 {
 192:                     s.SetLevel(9); // 0-9, 9 being the highest compression
 193:                     CompressDir(SourceDirectory, SourceDirectory, s);
 194:                     s.Finish();
 195:                     s.Close();
 196:                 }
 197:             }
 198:             catch (Exception exp)
 199:             {
 200:                 Console.WriteLine(exp);
 201:             }
 202:         }
 203:  
 204:         private static void CompressDir(string ParentPath, string SourceDirectory, ZipOutputStream s)
 205:         {
 206:             string[] filenames = Directory.GetFiles(SourceDirectory);
 207:             byte[] buffer = new byte[4096];
 208:             foreach (string file in filenames)
 209:             {
 210:                 string sFilePath = SourceDirectory.Replace(ParentPath, "");
 211:                 if (sFilePath.Trim() != "")
 212:                 {
 213:                     if (sFilePath.StartsWith("\\")) sFilePath = sFilePath.Substring(1);
 214:                     if (!sFilePath.EndsWith("\\")) sFilePath += "\\";
 215:                 }
 216:                 ZipEntry entry = new ZipEntry(sFilePath + Path.GetFileName(file));
 217:                 entry.DateTime = DateTime.Now;
 218:                 s.PutNextEntry(entry);
 219:                 using (FileStream fs = File.OpenRead(file))
 220:                 {
 221:                     int sourceBytes;
 222:                     do
 223:                     {
 224:                         sourceBytes = fs.Read(buffer, 0, buffer.Length);
 225:                         s.Write(buffer, 0, sourceBytes);
 226:                     }
 227:                     while (sourceBytes > 0);
 228:                 }
 229:             }
 230:             string[] directories = Directory.GetDirectories(SourceDirectory);
 231:             foreach (string directroy in directories)
 232:             {
 233:                 CompressDir(ParentPath , directroy, s);
 234:             }
 235:  
 236:         }
 237:  
 238:         private static void PrintUsage()
 239:         {
 240:             Console.WriteLine("\t DNNPackager Usage: ");
 241:             Console.WriteLine("\t\t DNNPackager.exe <source-dir> <manifest-file> <target-path>");
 242:         }
 243:         private static void ExitWith(int errorCode, string errorMessage)
 244:         {
 245:             Console.WriteLine("Error Encountered");
 246:             Console.WriteLine(errorMessage);
 247:             System.Environment.Exit(errorCode);
 248:         }
 249:     }
 250: }

 

There you go with the entire source code. I don’t think I’d need to explain the code, its too simple for me to bother (I think). The usage is pretty simple

   1: private static void PrintUsage()
   2:        {
   3:            Console.WriteLine("\t DNNPackager Usage: ");
   4:            Console.WriteLine("\t\t DNNPackager.exe <source-dir> <manifest-file> <target-path>");
   5:        }

 

As an example: DNNPackager.exe "C:\inetpub\DNN5.2\DesktopModules\SpeedBlog" SpeedBlog.dnn "C:\Builds\SpeedBlog\TEMPBUILD" would create a SpeedBlog_<version>.zip installer file from the SpeedBlog.dnn manifest into the current directory.  A word for the reference. SharpZipLib is in DNN bin directory.

Let me know in comments if this helps anyone out there. Or if I missed anything. Even if I did something entirely unnecessary. And yeah, I need some kind of DNN documentation.

  
 You may also be interested in
  
 Comments & Discussions

  
Locations of visitors to this page Clicky Web Analytics 

Subodh's Blog Rating

 

DISCLAIMER

The opinion expressed
on this page 
is strictly that
of the page author
who has a
habit of animating
day-dreaming
and
fictionalizing
out of thin air.
 

The contents of this page
have not been
reviewed 
nor
approved
by 
Yahoo!

 Follow this blog
  
 Tag Cloud
  
Archives
 

Top 5 Posts of Last year
Copyright © 1995-2009 Subodh Shakya. All rights reserved.