Automated Publishing of InfoPath Forms (Part 2 of 2)


2008 at 04:31 PM


We’ve now surpassed 50 InfoPath forms on the InfoPath 2007 / SharePoint 2007 project I’m currently engaged on. If you’ve done InfoPath/SharePoint development before, you’ll know that it can be really painful to publish forms and then deploy them to SharePoint.

In Part 1 of this 2 blog series, I showed you how to automate the deployment of InfoPath forms to SharePoint using NAnt. This time around I’ll show you how to automate the publishing of an InfoPath form.

If you’ve published an InfoPath form to an Administrator-approved form template before, you’ll be all too familiar with the process of clicking next a whole bunch of times in order to publish the form. Why should you have to go through all these manual steps every time you make a change to a form?

To automate this, I first found some VB code on this blog article to publish a form. I then converted it to C#, and built it as a custom NAnt task. So now I can publish a form by simply calling a custom NAnt task like this:

<publishform outputfolder="c:\mypublishedforms" formname="MyFormName.xsn" cabsdkpath="..\tools\CabSDK\BIN" xsffilename="manifest.xsf" formsourcepath="..\trunk\src\SourceForms\MyFormName\InfoPath Form Template\" />

In order to use this approach, you’ll need to either build your InfoPath form using the Visual Studio template, or you’ll need to extract the form source files from the XSN. To extract the source files from the XSN, choose “File” -> “Save As Source Files”. Then you can work with your form template by right clicking on “manifest.xsf” and choosing “Design”.

Here is the code to build the custom NAnt task:

using System;

using System.Diagnostics;

using System.IO;

using System.Xml;

using NAnt.Core;

using NAnt.Core.Attributes;

 

namespace My.Build.Tasks

{

    [TaskName("publishform")]

    public class PublishFormTask : Task

    {

        [TaskAttribute("outputfolder", Required = true)]

        public string OutputFolder { get; set; }

 

        [TaskAttribute("formname", Required = true)]

        public string FormName { get; set; }

 

        [TaskAttribute("cabsdkpath", Required = true)]

        public string CabSdkPath { get; set; }

 

        [TaskAttribute("xsffilename", Required = true)]

        public string XsfFileName { get; set; }

 

        [TaskAttribute("formsourcepath", Required = true)]

        public string FormSourcePath { get; set; }

 

        protected override void ExecuteTask()

        {

            string makeCabPath = CabSdkPath + "\\MAKECAB.EXE";

            BuildCabFile(makeCabPath);

        }

 

        private void BuildCabFile(string makeCabExe)

        {

            try

            {

                if (!File.Exists(makeCabExe))

                {

                    throw new Exception(string.Format("CABSDK not found. Please check your CABSDK property value. Couldn't find makecab.exe @ '{0}'", makeCabExe));

                }

 

                var tempName = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                //var tempName = Path.GetTempFileName();

                var tempFolder = Path.GetTempPath();

                var tempPath = PathCombine(tempFolder, tempName);

 

                var ddfString = string.Empty;

                ddfString += ".Set DiskDirectoryTemplate='" + tempFolder + "'" + Environment.NewLine;

                ddfString += ".Set CabinetNameTemplate='" + tempName + "'" + Environment.NewLine;

 

                var xsfDom = new XmlDocument();

                xsfDom.Load(PathCombine(FormSourcePath, XsfFileName));

                var nm = InitNamespaceManager(xsfDom);

 

                ddfString += QuoteString(PathCombine(FormSourcePath, XsfFileName)) + Environment.NewLine;

                var fileNodes = xsfDom.SelectNodes("/xsf:xDocumentClass/xsf:package/xsf:files/xsf:file/@name", nm);

 

                for (int i = 0; i <= fileNodes.Count - 1; i++)

                {

                    ddfString += QuoteString(PathCombine(FormSourcePath, fileNodes[i].InnerText)) + Environment.NewLine;

                }

 

                var ddfPath = PathCombine(tempFolder, "makecab.ddf");

                SaveToFile(ddfString, ddfPath);

                ShellExecute(QuoteString(makeCabExe), "/V1 /F " + QuoteString(ddfPath));

                File.Delete(ddfPath);

 

                if (File.Exists(PathCombine(OutputFolder, FormName)))

                {

                    File.Delete(PathCombine(OutputFolder, FormName));

                }

 

                File.Move(tempPath, PathCombine(OutputFolder, FormName));

 

                string[] oScratchFiles = new string[] { "setup.inf", "setup.rpt" };

                foreach (string strScratchFile in oScratchFiles)

                {

                    if (File.Exists(strScratchFile))

                    {

                        File.Delete(strScratchFile);

                    }

                }

            }

            catch (Exception ex)

            {

                throw new Exception("Could not create XSN file from files.", ex);

            }

        }

 

        private static void SaveToFile(string data, string filePath)

        {

            var fs = File.Create(filePath);

            fs.Close();

            var TextStream = new StreamWriter(filePath);

            TextStream.Write(data);

            TextStream.Flush();

            TextStream.Close();

        }

 

        private static void ShellExecute(string command, string args)

        {

            var info = new ProcessStartInfo(command, args);

            info.UseShellExecute = false;

            var process = Process.Start(info);

            process.WaitForExit(60000);

        }

 

        private static string QuoteString(string s)

        {

            return "\"" + s + "\"";

        }

 

        private static string PathCombine(string folder, string fileName)

        {

            return Path.Combine(folder, fileName);

        }

 

        public static XmlNamespaceManager InitNamespaceManager(XmlDocument xmlDOMDoc)

        {

            XmlNamespaceManager xnmMan;

            xnmMan = new XmlNamespaceManager(xmlDOMDoc.NameTable);

 

            foreach (XmlAttribute nsAttr in xmlDOMDoc.DocumentElement.Attributes)

            {

                if (nsAttr.Prefix == "xmlns")

                    xnmMan.AddNamespace(nsAttr.LocalName, nsAttr.Value);

            }

 

            return xnmMan;

        }

 

        public void RunTask()

        {

            ExecuteTask();

        }

    }

}

 

 

Comments

# uuzxjy said on Wednesday, November 05, 2008 11:55 AM

KqUr6V  <a href="uxphvcyvinha.com/.../a>, [url=http://bmuutarvawev.com/]bmuutarvawev[/url], [link=http://fctemftqouxg.com/]fctemftqouxg[/link], http://uuuspukcxxwf.com/

Leave a Comment

(required) 
(required) 
(optional)
(required)