• Wix 安装部署教程(十二) -- 自动更新WXS文件


            上一篇分享了一个QuickWIX,用来对比两个工程前后的差异,但是这样还是很繁琐,而且昨天发现有Bug,目录对比有问题。这次改变做法,完全让程序自动去更新WXS文件,然后再用CCNet去自动编译,这样的话,工程师更新文件,再也不用我去编译,发布了。

             思路:在原来的基础上,传入工程路径和目标文件夹,用模板的方式,更新变动的部分生成新的WXS文件覆盖原来的文件,一开始我思路搞错了,想在比较的基础上去更新变动的部分,比如一个文件删除了,就把这个File移除掉,同理对于组件和目录,但是这样比较费事,容易出Bug。

             工程目录,在原来的基础上没有增加对象。多了一个Templet文件,用于放模板文件。

             

         界面:

         

              如果改成控制台程序,就三句:     

     static void Main(string[] args)
            {
                if (args.Length < 2)
                    return;
                Console.WriteLine(args[0]);
                Console.WriteLine(args[1]);
                var wiXml = new GenerateWiXml(args[0], "$(var.Dev)", args[1]);
                wiXml.Generate();
                wiXml.WixComparator.AfterWixProj.SaveAsLast();
                Console.WriteLine("替换完成");
            }

    先创建GenrateWiXml对象,调用Generate方法来根据目录来生成WIX元素。每个元素都有ToWixString方法。  主要是SaveAsLast方法,更换了两个WXS文件。Product.wxs和DevComponents.wxs。前者找Feature 和 Directory 标签,后者分两种情况,根目录和其他目录,因为我根目录文件夹写了些其他的元素,不能全部替换Files,另外其他的DirectoryRef 就直接添加了。

     public void SaveAsLast()
            {
                #region DirAndCompDocument
                if (DirAndCompDocument == null)
                {
                    DirAndCompDocument = XDocument.Load(GetWxsProductPath());
                }
    
                var rawpath1 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"....Templet", WixConfig.WxsProductPath);
                var productTemp = XDocument.Load(rawpath1);
                // 组件
                var comelement = WixFeature.NewXElement();
                var feature = productTemp.Descendants()
                                .First()
                                .Elements()
                                .First()
                                .Elements()
                                .FirstOrDefault(n => n.Name == WixConfig.Np + "Feature" && n.Attribute("Id").Value == "ProductFeature");
    
                if (feature != null)
                {
                    feature.Elements().Remove();
                
                    feature.Add(comelement.Elements());
                }
                // 目录
                var direlement = WixDirectory.NewXElement();
    
                var element = productTemp.Descendants()
                      .First()
                      .Elements()
                      .First()
                      .Elements()
                      .FirstOrDefault(n => n.Name == WixConfig.Np + "Directory");
                if (element != null)
                {
                    var dir = element.Elements().First();
                    dir.Elements().Remove();
                    dir.Add(direlement.Elements());
                }
    
    
                productTemp.Save(GetWxsProductPath());
    
                #endregion 
    
                #region files
                var rawpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"....Templet", WixConfig.WxsFilePath);
                var dirTemp = XDocument.Load(rawpath);
                var fragment = dirTemp.Descendants().First().Elements().First();
                var installfolder = WixFragment.DirectoryRefs;
                //根目录下面的dir 都要递归处理 要全部加到DirTemp中去
                foreach (var wd in installfolder)
                {
                    //最特别的一个
                    if (wd.Id == "INSTALLFOLDER")
                    {
                        //找到Install下面的comp 全部加进来
                        var firstcop = fragment.Elements().First().Elements().First();
                        foreach (var file in wd.Component.Files)
                        {
                            firstcop.Add(file.XElement);
                        }
                    }
                    else
                    {
                        //全部添加   
                        fragment.Add(wd.XElement);
                    }
    
                }
                dirTemp.Save(GetWxsFilePath());
    
    
                #endregion
    
    
            }

     这个WXS模板,需要自己调整了。而每个元素的XElement基本上是这样生成的(WIXDirectoryRef):

                  if (_xElement == null)
                    {
                        XNamespace np = "http://schemas.microsoft.com/wix/2006/wi";
                        var str = ToWixString();
                        _xElement = XElement.Parse(str);
                        _xElement.Name = np + "DirectoryRef";
                        // 确保后代的命名空间都对
                        var cops = _xElement.Elements();
                        foreach (var xe in cops)
                        {
                            xe.Name = np + "Component";
    
                            foreach (var x in xe.Elements())
                            {
                                x.Name = np + "File";
                            }
                        }
                    }

    调用XElement的Parse方法后,需要修改元素的命名空间,不然每个元素都会出现一个xmlns=“”的标签。

         小结:将上面的工程改成控制台配合自己的WIX的SetUp工程,然后部署到CCNET就可以自动打包了。以下是源码,比较部分替换元素的代码没有删除,先留着。希望对你有帮助。 

     http://pan.baidu.com/s/1hUtki

  • 相关阅读:
    Encountered a section with no Package: header
    java的System.getProperty()方法能够获取的值
    谷歌技术&quot;三宝&quot;之MapReduce
    surfaceDestroyed什么时候被调用
    调用CachedRowSetImpl类时,为什么会出现这样的错误
    正則表達式举例(下)
    java中接口的定义与实现
    UVA 538
    编程算法
    3D空间包围球(Bounding Sphere)的求法
  • 原文地址:https://www.cnblogs.com/stoneniqiu/p/4707329.html
Copyright © 2020-2023  润新知