Skip to content

Instantly share code, notes, and snippets.

@GilesBathgate
Last active February 21, 2021 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GilesBathgate/02ec989cec836c097f35ea3517b5c31c to your computer and use it in GitHub Desktop.
Save GilesBathgate/02ec989cec836c097f35ea3517b5c31c to your computer and use it in GitHub Desktop.
Harvester implementation
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using WixSharp;
using WixSharp.CommonTasks;
namespace WixSharp
{
class Harvester
{
private static readonly string _heat = Path.Combine(Compiler.WixLocation, "heat.exe");
private readonly Project _project;
private readonly string _sourceDir;
private readonly string _targetDir;
private readonly IList<ProjectReference> _components;
public Harvester(Project project, string sourceDir, string targetDir)
{
_project = project;
_sourceDir = sourceDir;
_targetDir = targetDir;
_components = new List<ProjectReference>();
_project.WixSourceGenerated += WixSourceGenerated;
}
private void WixSourceGenerated(XDocument document)
{
var ns = XNamespace.Get("http://schemas.microsoft.com/wix/2006/wi");
var defaultFeature = document.Descendants(ns + "Feature")
.FirstOrDefault(x => x.Attribute("Id")?.Value == _project.DefaultFeature.Id);
foreach (var project in _components)
{
if (project.Binaries)
defaultFeature.AddElement(
new XElement("ComponentGroupRef",
new XAttribute("Id", $"{project.Name}.Binaries")));
if (project.Content)
defaultFeature.AddElement(
new XElement("ComponentGroupRef",
new XAttribute("Id", $"{project.Name}.Content")));
if (project.Satellites)
defaultFeature.AddElement(
new XElement("ComponentGroupRef",
new XAttribute("Id", $"{project.Name}.Satellites")));
}
}
public void AddProjects(IEnumerable<ProjectReference> projects)
{
foreach (ProjectReference p in projects)
AddProject(p);
}
public void AddProject(ProjectReference project)
{
var sourceDir = project.SourceDir ?? _sourceDir;
var targetDir = project.TargetDir ?? _targetDir;
if (!System.IO.File.Exists(project.ProjectPath))
throw new Exception($"Project '{project.ProjectPath}' not found.");
var output = Path.Combine(_project.OutDir, Path.ChangeExtension(Path.GetFileName(project.ProjectPath), "wxs"));
var projectDir = Path.GetDirectoryName(project.ProjectPath);
var args = new[] {
$"project {project.ProjectPath}",
project.Binaries ? "-pog Binaries" : "",
project.Content ? "-pog Content" : "",
project.Satellites ? "-pog Satellites" : "",
"-ag","-sfrag",
$"-directoryid {targetDir}",
"-template fragment",
$"-platform AnyCPU",
$"-projectname {project.Name}",
$"-out {output}" };
var pi = new ProcessStartInfo
{
FileName = _heat,
Arguments = string.Join(" ", args),
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
using (var p = Process.Start(pi))
{
p.WaitForExit();
if (p.ExitCode != 0)
throw new Exception(p.StandardOutput.ReadToEnd());
}
var xml = XDocument.Load(output);
foreach (var fragment in xml.Root.Elements())
_project.AddXml("Wix", fragment.ToString());
_project.CandleOptions +=
$" -d\"{project.Name}.TargetDir\"={sourceDir} " + //As intended the TargetDir for candle is the sourceDir
$" -d\"{project.Name}.ProjectDir\"={projectDir} ";
_components.Add(project);
if (!Compiler.PreserveTempFiles)
System.IO.File.Delete(output);
}
}
}
var project = new ManagedProject(...);
var projectRefs = new[] {
new ProjectReference(@"path\to\project1.csproj"),
new ProjectReference(@"path\to\project2.csproj") };
var harvester = new Harvester(project, @"..\bin", "INSTALLDIR");
harvester.AddProjects(projectRefs);
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace WixSharp
{
public class ProjectReference
{
public string Name { get; }
public string SourceDir { get; set; }
public string TargetDir { get; set; }
public string ProjectPath { get; }
public bool Binaries { get; set; } = true;
public bool Content { get; set; } = true;
public bool Satellites { get; set; } = true;
public ProjectReference(string projectPath)
{
ProjectPath = projectPath;
Name = Path.GetFileNameWithoutExtension(projectPath);
}
}
}
@johnou
Copy link

johnou commented Feb 17, 2021

@GilesBathgate have you managed to run Harvester with project.InstallScope = InstallScope.perUser; and installing to %LocalAppData%? on our project wxs validation fails with ICE38 and ICE64 errors for every file..

@GilesBathgate
Copy link
Author

I believe something similar to this Harvester was added to wix# 1.12.0 I think the method is project.AddVsProjectOutput

@johnou
Copy link

johnou commented Feb 21, 2021

@GilesBathgate thanks, got it all sorted!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment