Ejemplo n.º 1
0
        protected override void CompilationAndBuild(IBuildContext context, CancellationTokenSource cts)
        {
            if (context.OnlyCheck)
            return;

              List<string> msiFiles = new List<string>();

              foreach (string wxsFile in wxsFiles)
              {
            msiFiles.Add(InternalCompilationAndBuild(context, cts, wxsFile));
              }

              string outDir = string.Format("{0} v{1}.{2}.{3}.{4} Patches v{5}.{6}.{7}.{8}",
            product.BaseName,
            product.BaseVersion.Major,
            product.BaseVersion.Minor,
            product.BaseVersion.Build,
            product.BaseVersion.Revision,
            product.TargetVersion.Major,
            product.TargetVersion.Minor,
            product.TargetVersion.Build,
            product.TargetVersion.Revision);

              outDir = Path.Combine(Path.GetDirectoryName(context.ProjectFileName), outDir);

              if (Directory.Exists(outDir))
            Directory.Delete(outDir, true);
              Directory.CreateDirectory(outDir);

              context.BuildMessageWriteLine("Построенные MSP-файлы:", BuildMessageTypes.Information);

              foreach (string msiFile in msiFiles)
              {
            string outFile = Path.Combine(outDir, Path.GetFileName(msiFile));
            File.Copy(msiFile, outFile);
            context.BuildMessageWriteLine(outFile, BuildMessageTypes.Information);
              }
        }
Ejemplo n.º 2
0
        public void Build(IBuildContext context)
        {
            string prefix = context.OnlyCheck ? "Проверка" : "Сборка";

              context.ClearBuildMessage();
              context.BuildMessageWriteLine(prefix + " начата.", BuildMessageTypes.Notification);

              // Общее действие для вызова методов с отменой выполнения задач.
              // Параметры:
              // a - метод для вызова;
              // c - токен для отмены и других операций;
              // m - сообщение о начале действия.
              Action<Action<IBuildContext, CancellationTokenSource>, IBuildContext, CancellationTokenSource, string> actionWithErrorHandling =
            (Action<IBuildContext, CancellationTokenSource> a, IBuildContext ctx, CancellationTokenSource c, string m) =>
            {
              // Не будем выводить названия действия при проверке, так как некоторые могут не выполнятся.
              if (!context.OnlyCheck)
            context.BuildMessageWriteLine(m, BuildMessageTypes.Notification);
              try
              {
            a(ctx, c);
              }
              catch (Exception e)
              {
            context.BuildMessageWriteLine(e.Message, BuildMessageTypes.Error);
            c.Cancel();
            c.Token.ThrowIfCancellationRequested();
              }
            };

              Stopwatch stopwatch = Stopwatch.StartNew();
              CancellationTokenSource cts = new CancellationTokenSource();
              Task.Factory.
            StartNew(delegate
            {
              actionWithErrorHandling(CheckProduct, context, cts, "");
            }, cts.Token).
            ContinueWith(delegate
            {
              // Загружаем шаблоны во временную папку.
              actionWithErrorHandling(LoadingTemplates, context, cts, "Загрузка шаблонов.");
            }, cts.Token).
            ContinueWith(delegate
            {
              actionWithErrorHandling(ProcessingTemplates, context, cts, "Обработка шаблонов.");
            }, cts.Token).
            ContinueWith(delegate
            {
              actionWithErrorHandling(CompilationAndBuild, context, cts, "Компиляция и сборка.");
            }, cts.Token).
            ContinueWith(delegate
            {
              stopwatch.Stop();
              // Сюда токен не передаем.
              // Здесь должен быть код, выполняющийся в любом случае, завершились задачи или нет.
              context.BuildMessageWriteLine(
            string.Format(prefix + " завершена {0} за {1}.", cts.IsCancellationRequested ? "с ошибками" : "успешно",
            stopwatch.Elapsed.ToString("mm\\:ss")),
            cts.IsCancellationRequested ? BuildMessageTypes.Error : BuildMessageTypes.Information);
              if (context.BuildIsFinished != null)
            context.BuildIsFinished();
            });
        }
Ejemplo n.º 3
0
 protected void RunCommand(IBuildContext context, string fileName, string command)
 {
     context.BuildMessageWriteLine(">" + fileName + " " + command, BuildMessageTypes.ConsoleSend);
       IProcessRunner runner = CreateProcessRunner();
       runner.OutputMessageReceived += (s, e) =>
       {
     context.BuildMessageWriteLine(e.Message, BuildMessageTypes.ConsoleReceive);
       };
       runner.Start(fileName, command);
       if (runner.HasError)
     throw new Exception(string.Format("Запуск {0} завершился с ошибкой.", Path.GetFileName(fileName)));
 }
Ejemplo n.º 4
0
        private void RunningLight(IBuildContext context, CancellationTokenSource cts)
        {
            context.BuildMessageWriteLine(LightDescription, BuildMessageTypes.Notification);

              // Путь к light.
              string lightFileName = Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.LightFileName);

              // Конечное имя. Меняем пробелы на подчеркивание.
              string outFileName = string.Format("{0}_v{1}.{2}",
            product.Name.Replace(' ', '_'),
            product.Version.Major, product.Version.Minor);
              // Добавим к имени файла директорию.
              string outDirectory = string.Format("{0} v{1}", product.Name, product.Version);
              outFileName = Path.Combine(Path.GetDirectoryName(context.ProjectFileName), outDirectory, outFileName);

              // Выполняем два раза.
              // Первый раз строим wixout, второй msi и wixpdb.
              for (int mode = 0; mode < 2; mode++)
              {
            // Команда для выполнения.
            StringBuilder command = new StringBuilder();
            string targetFileName;
            if (mode == 0)
            {
              targetFileName = string.Format("{0}.{1}", outFileName, "wixout");
              command.Append(string.Format("-bf -xo -out \"{0}\"", targetFileName));
            }
            else
            {
              targetFileName = string.Format("{0}.{1}", outFileName, "msi");
              command.Append(string.Format("-out \"{0}\"", targetFileName));
              command.Append(string.Format(" -pdbout \"{0}.{1}\"", outFileName, "wixpdb"));
            }
            command.Append(" -cultures:null");

            // Подавление ICE:
            //   warning LGHT1076 : ICE17: ListView: 'SELECTEDDATABASE' for Control: 'DatabasesListView' of Dialog: 'DatabasesListDlg' not found in ListView table.
            //   error LGHT0204 : ICE38: Component ... installs to user profile. It's KeyPath registry key must fall under HKCU.
            //   error LGHT0204 : ICE43: Component ... has non-advertised shortcuts. It's KeyPath registry key should fall under HKCU.
            //   error LGHT0204 : ICE57: Component ... has both per-user and per-machine data with a per-machine KeyPath.
            string[] ices = context.ApplicationSettings.SuppressIce.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string ice in ices)
              command.Append(" -sice:" + ice);

            command.Append(string.Format(" -ext \"{0}\"", Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.UIExtensionFileName)));
            command.Append(string.Format(" -ext \"{0}\"", Path.Combine(context.ApplicationInfo.ApplicationDirectory, "WixSTExtension.dll")));
            command.Append(" -cultures:ru-RU;en-US");
            // Берем файлы с расширением .wxs и меняем на .wixobj.
            foreach (var name in templates.Where(v => v.Value.EndsWith(".wxs")).Select(v => Path.ChangeExtension(v.Value, ".wixobj")))
            {
              command.Append(@" " + Path.Combine(StoreDirectory, name));
            }

            RunCommand(context, lightFileName, command.ToString());

            context.BuildMessageWriteLine(string.Format("Создан файл: {0}", targetFileName), BuildMessageTypes.Information);

            // Если создаем wixout, то зархивируем его вместе с дополнительной информацией.
            if (mode == 0)
            {
              WixProductUpdateInfo updateInfo = WixProductUpdateInfo.Create(product, targetFileName, context.SourceStoreDirectory);
              updateInfo.Save(string.Format("{0}.{1}", outFileName, WixProductUpdateInfo.FilenameExtension), true);
            }
              }
        }
Ejemplo n.º 5
0
        private void RunningCandle(IBuildContext context, CancellationTokenSource cts)
        {
            context.BuildMessageWriteLine(CandleDescription, BuildMessageTypes.Notification);

              // Путь к candle.
              string candleFileName = Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.CandleFileName);

              // Команда для выполнения.
              StringBuilder command = new StringBuilder();
              // Если указываем путь в кавычках, то надо указать дополнительно обратный слеш,
              // это требование WIX.
              command.Append(string.Format("-out \"{0}\\\"", StoreDirectory.IncludeTrailingPathDelimiter()));
              command.Append(" -arch x86");
              command.Append(string.Format(" -ext \"{0}\"", Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.UIExtensionFileName)));
              command.Append(string.Format(" -ext \"{0}\"", Path.Combine(context.ApplicationInfo.ApplicationDirectory, "WixSTExtension.dll")));

              // Берем файлы с расширением .wxs.
              foreach (var name in templates.Where(v => v.Value.EndsWith(".wxs")))
              {
            command.Append(string.Format(" \"{0}\"", Path.Combine(StoreDirectory, name.Value)));
              }

              RunCommand(context, candleFileName, command.ToString());
        }
Ejemplo n.º 6
0
        protected override void ProcessingTemplates(IBuildContext context, CancellationTokenSource cts)
        {
            if (context.OnlyCheck)
            return;

              wxsFiles.Clear();

              string pathToTemplate = Path.Combine(StoreDirectory, mspTemplate);
              DeleteDevelopmentInfo(pathToTemplate);

              foreach (IWixElement element in product.RootElement.Items)
              {
            // Создадим имя файла: Имя_Продукта_v1.2.3.4_Имя_Патча_v1.2.3.5.wxs.
            string name = string.Format("{0}_v{1}.{2}.{3}.{4}_{5}_v{6}.{7}.{8}.{9}.wxs",
              product.TargetName.Replace(' ', '_'),
              product.BaseVersion.Major,
              product.BaseVersion.Minor,
              product.BaseVersion.Build,
              product.BaseVersion.Revision,
              element.Id,
              product.TargetVersion.Major,
              product.TargetVersion.Minor,
              product.TargetVersion.Build,
              product.TargetVersion.Revision);

            // Создаем в отдельной директории файл wxs для каждого Patch.
            string path = Path.Combine(StoreDirectory, element.Id);
            Directory.CreateDirectory(path);
            path = Path.Combine(path, name);
            File.Copy(pathToTemplate, path);

            // Дочерние элементы WixPatchComponentElement;
            var children = element.Items.OfType<WixPatchComponentElement>();

            // Заполним содержимым.
            XElement xmlWix = XElement.Load(path);
            XElement xmlPatch = xmlWix.GetXElement("Patch");
            // Сформируем список компонент.
            string componentsDesc = "";
            foreach (WixPatchComponentElement c in children)
              componentsDesc += (componentsDesc == "" ? "" : ", ") + c.Id;
            string description = string.Format(@"Патч ""{0}"" версии {1}. Обновление до версии {2} компонент: {3}",
              product.BaseName, product.BaseVersion, product.TargetVersion, componentsDesc);
            xmlPatch.Attribute("Comments").Value = description;
            xmlPatch.Attribute("Description").Value = description;
            xmlPatch.Attribute("DisplayName").Value = string.Format(@"Патч ""{0}""", product.TargetName);
            xmlPatch.Attribute("Manufacturer").Value = product.TargetManufacturer;
            xmlPatch.Attribute("TargetProductName").Value = product.TargetName;

            XElement xmlPatchFamily = xmlPatch.GetXElement("PatchFamily");
            // Важно, указываем новую версию. Эта версия ни как не связана с версией MSI,
            // только для msp. Но она должна быть больше чем у ранних MSP. Будем использовать
            // версию нового продукта.
            xmlPatchFamily.Attribute("Version").Value = product.TargetVersion;
            xmlPatchFamily.Attribute("ProductCode").Value = product.TargetId.ToString();

            // Добавляем компоненты.
            // Если указаны все компоненты, то ничего не добавляем. Патч сформируется полным.
            // Если компоненты указаны не все, то добавим их.
            bool isFull = children.Select(v => v.Id).OrderBy(v => v).
              SequenceEqual(product.UpdateComponents.Select(v => v.Id).OrderBy(v => v));
            if (!isFull)
            {
              foreach (WixPatchComponentElement component in children)
              {
            XElement xmlComponentRef = new XElement(XmlNameSpaceWIX + "ComponentRef",
              new XAttribute("Id", component.Id));
            xmlPatchFamily.Add(xmlComponentRef);
              }
            }

            xmlWix.Save(path);

            // Добавим в список
            wxsFiles.Add(path);
            context.BuildMessageWriteLine(string.Format("Сформирован {0}.", path), BuildMessageTypes.Notification);
              }
        }
Ejemplo n.º 7
0
        private string InternalCompilationAndBuild(IBuildContext context, CancellationTokenSource cts, string wxsFile)
        {
            // Команда для выполнения.
              StringBuilder command = new StringBuilder();

              context.BuildMessageWriteLine("Компиляция и сборка файла: " + wxsFile, BuildMessageTypes.Notification);

              context.BuildMessageWriteLine(TorchDescription, BuildMessageTypes.Notification);
              // torch -p -xi "Сервер АСПО 1.0.1\Сервер АСПО.wixout" "Сервер АСПО 1.0.2\Сервер АСПО.wixout" -out Patch\Differences.wixmst
              string wixmstFileName = Path.ChangeExtension(wxsFile, ".wixmst");
              command.Append("-p -xi");
              command.Append(string.Format(" \"{0}\"", Path.Combine(context.SourceStoreDirectory, product.BasePath)));
              command.Append(string.Format(" \"{0}\"", Path.Combine(context.SourceStoreDirectory, product.TargetPath)));
              command.Append(string.Format(" -out \"{0}\"", wixmstFileName));
              string torchFileName = Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.TorchFileName);
              RunCommand(context, torchFileName, command.ToString());

              command.Clear();
              context.BuildMessageWriteLine(CandleDescription, BuildMessageTypes.Notification);
              // candle Patch\Patch.wxs -out Patch\
              command.Append(string.Format("\"{0}\"", wxsFile));
              command.Append(string.Format(" -out \"{0}\\\"", Path.GetDirectoryName(wxsFile).IncludeTrailingPathDelimiter()));
              string candleFileName = Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.CandleFileName);
              RunCommand(context, candleFileName, command.ToString());

              string wixmspFileName;
              command.Clear();
              context.BuildMessageWriteLine(LightDescription, BuildMessageTypes.Notification);
              // light Patch\Patch.wixobj -out Patch\Patch.wixmsp
              command.Append(string.Format("\"{0}\"", Path.ChangeExtension(wxsFile, ".wixobj")));
              command.Append(string.Format(" -out \"{0}\"", wixmspFileName = Path.ChangeExtension(wxsFile, ".wixmsp")));
              string lightFileName = Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.LightFileName);
              RunCommand(context, lightFileName, command.ToString());

              string mspFileName;
              command.Clear();
              context.BuildMessageWriteLine(PyroDescription, BuildMessageTypes.Notification);
              // pyro Patch\Patch.wixmsp -t MyPatch Patch\Differences.wixmst -out Patch\Patch.msp
              command.Append(string.Format("\"{0}\"", wixmspFileName));
            #warning AspoPatch Вставить в продукт.
              command.Append(string.Format(" -t AspoPatch \"{0}\"", wixmstFileName));
              command.Append(string.Format(" -out \"{0}\"", mspFileName = Path.ChangeExtension(wxsFile, ".msp")));
              string pyroFileName = Path.Combine(context.ApplicationSettings.WixToolsetPath, context.ApplicationSettings.PyroFileName);
              RunCommand(context, pyroFileName, command.ToString());

              context.BuildMessageWriteLine("Файл " + mspFileName + " построен.", BuildMessageTypes.Notification);
              return mspFileName;
        }