Hello Gents,
While we were migrating from VS2008 to VS201x I found a problem with
harvesting projects containing links to external filesandmore precisely
if the link is not in the root level of the project but in a sub-folder.
Following is an example of such project:
<Project ...>
...
<ItemGroup>
<Content Include="..\..\FolderOutsideProject\SubFolder\File.ext">
<Link>Subfolder1\SubFolder2\File.ext</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
...
</Project>
If project is created in VS2008 and uses tools version 3.5 then link's
sub-folder is properly recognized and heat generates sub-folders
accordinglywhen creating corresponding Component entries. After
migration to V201x and tools version 4.0 sub-folders are not taken into
account and corresponding Component entries are placed in the root
directory.
I tracked the problem down to VSProjectHarvester.cs file and more
precisely to VSProjectHarvester.MSBuild40Project.Build() method which
does not populate the dictionary of targetOutputs.
I also studied the new approach used when building projects against
tools 4.0 inside harvester and found a way to populatetargetOutputs so
it contains the same data as returned by the old approach used when
building against 3.5 target.
Following URL is a pull request with the changes made in 3.8 branch:
https://wix.codeplex.com/SourceControl/network/forks/bdachev/ProjectHarverster/contribution/4702
Please find attached the fix as a patch file if you prefer it that way.
The code below (written in C# and without using reflection) illustrates
how to populate targetOutputs:
IDictionary<string, TargetResult> resultsByTarget =
buildResult.ResultsByTarget;
if (resultsByTarget != null)
{
foreach (string itemName in targetNames)
{
TargetResult result;
bool hasKey = resultsByTarget.TryGetValue(itemName,
out result);
if (hasKey)
{
if (result != null)
{
ITaskItem[] items = result.Items;
targetOutputs.Add(itemName, items);
}
}
if (!targetOutputs.Contains(itemName))
{
targetOutputs.Add(itemName, new List<object>());
}
}
}
The patch itself is written using reflection as the rest of the code in
VSProjectHarverster.cs to avoid references to MSBuild related assemblies.
Hope it will be of some help!
Best regards,
Boris.
PS: The patch also includes a fix for another problem of project
harverster related to winforms .resx files
From 9102beadec38ae81873783a637ef1053dfabe9d4 Mon Sep 17 00:00:00 2001
From: Boris Dachev <[email protected]>
Date: Sat, 11 May 2013 22:32:22 +0300
Subject: [PATCH] Fixes in project harvester:
- fix for .resx files problem
- fix for file links
---
src/ext/VSExtension/wixext/VSProjectHarvester.cs | 48 ++++++++++++++++++++++--
1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/src/ext/VSExtension/wixext/VSProjectHarvester.cs
b/src/ext/VSExtension/wixext/VSProjectHarvester.cs
index 1130f40..c983c49 100644
--- a/src/ext/VSExtension/wixext/VSProjectHarvester.cs
+++ b/src/ext/VSExtension/wixext/VSProjectHarvester.cs
@@ -236,7 +236,17 @@ namespace Microsoft.Tools.WindowsInstallerXml.Extensions
IDictionary buildOutputs = new Hashtable();
- bool buildSuccess = project.Build(projectFile, buildOutputGroups,
buildOutputs);
+ string pwd = Directory.GetCurrentDirectory();
+ Directory.SetCurrentDirectory(Path.GetDirectoryName(projectFile));
+ bool buildSuccess = false;
+ try
+ {
+ buildSuccess = project.Build(projectFile, buildOutputGroups,
buildOutputs);
+ }
+ finally
+ {
+ Directory.SetCurrentDirectory(pwd);
+ }
if (!buildSuccess)
{
@@ -1282,10 +1292,40 @@ namespace Microsoft.Tools.WindowsInstallerXml.Extensions
// this.buildManager.EndBuild();
this.types.buildManagerType.GetMethod("EndBuild", new
Type[] { }).Invoke(this.buildManager, null);
- // fill in empty lists for each target so that heat will
look at the item group later
- foreach (string target in targetNames)
+ // IDictionary<string, TargetResult> resultsByTarget =
buildResult.ResultsByTarget;
+ object resultsByTarget =
buildResult.GetType().GetProperty("ResultsByTarget").GetValue(buildResult,
null);
+ if (resultsByTarget != null)
{
- targetOutputs.Add(target, new List<object>());
+ // cache MethodInfo of TryGetValue
+ var tryGetValue =
resultsByTarget.GetType().GetMethod("TryGetValue");
+ object[] prms = new object[2];
+ // enumerate target names and for each try to get
items from results of the build
+ foreach (string itemName in targetNames)
+ {
+ // TryGetValue's first parameter is the key set to
itemName
+ prms[0] = itemName;
+ prms[1] = null;
+ // TargetResult result;
+ // bool hasKey =
resultsByTarget.TryGetValue(itemName, out result);
+ bool hasKey =
(bool)tryGetValue.Invoke(resultsByTarget, prms);
+ if (hasKey)
+ {
+ // if dictionary has the key then the the
value should be of TargetResult type
+ object result = prms[1];
+ if (result != null)
+ {
+ // ITaskItem[] items = result.Items;
+ object items =
result.GetType().GetProperty("Items").GetValue(result, null);
+ targetOutputs.Add(itemName, items);
+ }
+ }
+
+ // fill in empty lists for each target so that
heat will look at the item group later
+ if (!targetOutputs.Contains(itemName))
+ {
+ targetOutputs.Add(itemName, new
List<object>());
+ }
+ }
}
return buildSucceeded;
--
1.8.1.msysgit.1
------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and
their applications. This 200-page book is written by three acclaimed
leaders in the field. The early access version is available now.
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may
_______________________________________________
WiX-devs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/wix-devs