@joebigelow / wix / commits / 5c851a84

WIXFEAT:4009 - Add support for outbound firewall rule

adnan shaheen committed Feb 5, 2018 at 14:01 UTC 5c851a848a6eeb86472e8a1cca814dd0cb1b0483
15 files changed +142 -20
src/ca/firewall.cpp
+32 -14
@@ -3,7 +3,7 @@
3 #include "precomp.h"
4
5 LPCWSTR vcsFirewallExceptionQuery =
6 - L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description` FROM `WixFirewallException`";
6 + L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `WixFirewallException`";
7 enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription };
8 enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown };
9 enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
@@ -36,6 +36,7 @@ static UINT SchedFirewallExceptions(
36 LPWSTR pwzComponent = NULL;
37 LPWSTR pwzFormattedFile = NULL;
38 LPWSTR pwzDescription = NULL;
39 + int iDirection = 0;
40
41 // initialize
42 hr = WcaInitialize(hInstall, "SchedFirewallExceptions");
@@ -130,6 +131,9 @@ static UINT SchedFirewallExceptions(
131
132 hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData);
133 ExitOnFailure(hr, "failed to write firewall rule description to custom action data");
134 +
135 + hr = WcaWriteIntegerToCaData(iDirection, &pwzCustomActionData);
136 + ExitOnFailure(hr, "failed to write firewall rule direction to custom action data");
137 }
138
139 // reaching the end of the list is actually a good thing, not an error
@@ -270,6 +274,7 @@ static HRESULT CreateFwRuleObject(
274 __in LPCWSTR wzPort,
275 __in int iProtocol,
276 __in LPCWSTR wzDescription,
277 + __in int iDirection,
278 __out INetFwRule** ppNetFwRule
279 )
280 {
@@ -321,6 +326,12 @@ static HRESULT CreateFwRuleObject(
326 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription);
327 }
328
329 + if (MSI_NULL_INTEGER != iDirection)
330 + {
331 + hr = pNetFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION> (iDirection));
332 + ExitOnFailure(hr, "failed to set exception direction");
333 + }
334 +
335 *ppNetFwRule = pNetFwRule;
336 pNetFwRule = NULL;
337
@@ -429,7 +440,8 @@ static HRESULT AddApplicationException(
440 __in BOOL fIgnoreFailures,
441 __in LPCWSTR wzPort,
442 __in int iProtocol,
432 - __in LPCWSTR wzDescription
443 + __in LPCWSTR wzDescription,
444 + __in int iDirection
445 )
446 {
447 HRESULT hr = S_OK;
@@ -456,7 +468,7 @@ static HRESULT AddApplicationException(
468 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
469 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
470 {
459 - hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, &pNetFwRule);
471 + hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule);
472 ExitOnFailure(hr, "failed to create FwRule object");
473
474 // set edge traversal to true
@@ -590,8 +602,9 @@ static HRESULT AddPortException(
602 __in BOOL fIgnoreFailures,
603 __in LPCWSTR wzPort,
604 __in int iProtocol,
593 - __in LPCWSTR wzDescription
594 - )
605 + __in LPCWSTR wzDescription,
606 + __in int iDirection
607 +)
608 {
609 HRESULT hr = S_OK;
610 BSTR bstrName = NULL;
@@ -614,7 +627,7 @@ static HRESULT AddPortException(
627 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
628 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
629 {
617 - hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, &pNetFwRule);
630 + hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule);
631 ExitOnFailure(hr, "failed to create FwRule object");
632
633 // enable it
@@ -825,14 +838,15 @@ static HRESULT AddApplicationException(
838 __in BOOL fIgnoreFailures,
839 __in LPCWSTR wzPort,
840 __in int iProtocol,
828 - __in LPCWSTR wzDescription
829 - )
841 + __in LPCWSTR wzDescription,
842 + __in int iDirection
843 +)
844 {
845 HRESULT hr = S_OK;
846
847 if (fSupportProfiles)
848 {
835 - hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription);
849 + hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection);
850 }
851 else
852 {
@@ -860,14 +874,15 @@ static HRESULT AddPortException(
874 __in BOOL fIgnoreFailures,
875 __in LPCWSTR wzPort,
876 __in int iProtocol,
863 - __in LPCWSTR wzDescription
864 - )
877 + __in LPCWSTR wzDescription,
878 + __in int iDirection
879 +)
880 {
881 HRESULT hr = S_OK;
882
883 if (fSupportProfiles)
884 {
870 - hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription);
885 + hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection);
886 }
887 else
888 {
@@ -951,6 +966,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
966 LPWSTR pwzDescription = NULL;
967 int iProtocol = 0;
968 int iProfile = 0;
969 + int iDirection = 0;
970
971 // initialize
972 hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
@@ -1013,6 +1029,8 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1029 ExitOnFailure(hr, "failed to read protocol from custom action data");
1030 hr = WcaReadStringFromCaData(&pwz, &pwzDescription);
1031 ExitOnFailure(hr, "failed to read protocol from custom action data");
1032 + hr = WcaReadIntegerFromCaData(&pwz, &iDirection);
1033 + ExitOnFailure(hr, "failed to read direction from custom action data");
1034
1035 switch (iTarget)
1036 {
@@ -1022,7 +1040,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1040 case WCA_TODO_INSTALL:
1041 case WCA_TODO_REINSTALL:
1042 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1025 - hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription);
1043 + hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection);
1044 ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1045 break;
1046
@@ -1040,7 +1058,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1058 case WCA_TODO_INSTALL:
1059 case WCA_TODO_REINSTALL:
1060 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile);
1043 - hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription);
1061 + hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection);
1062 ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile);
1063 break;
1064
src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+15 -2
@@ -25,7 +25,7 @@ namespace WixToolsetTest.Firewall
25 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t",
26 "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t",
27 "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t",
28 - "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall",
28 + "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1",
29 }, results);
30 }
31
@@ -44,7 +44,20 @@ namespace WixToolsetTest.Firewall
44 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t",
45 "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t",
46 "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t",
47 - "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall",
47 + "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1",
48 + }, results);
49 + }
50 +
51 + [Fact]
52 + public void CanBuildUsingOutboundFirewall()
53 + {
54 + var folder = TestData.Get(@"TestData\UsingOutboundFirewall");
55 + var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
56 +
57 + var results = build.BuildAndQuery(Build, "WixFirewallException");
58 + Assert.Equal(new[]
59 + {
60 + "WixFirewallException:fexPv9RR1kBvP6gMgWyXMVQkVbopOA\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example outbound firewall\t2",
61 }, results);
62 }
63
src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl new
+11
@@ -0,0 +1,11 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +
3 +<!--
4 +This file contains the declaration of all the localizable strings.
5 +-->
6 +<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
7 +
8 + <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
9 + <String Id="FeatureTitle">MsiPackage</String>
10 +
11 +</WixLocalization>
src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs new
+22
@@ -0,0 +1,22 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 + <Product Id="*" Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
4 + <Package InstallerVersion="200" Compressed="no" InstallScope="perMachine" />
5 +
6 + <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
7 + <MediaTemplate />
8 +
9 + <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
10 + <ComponentGroupRef Id="ProductComponents" />
11 + </Feature>
12 +
13 + </Product>
14 +
15 + <Fragment>
16 + <Directory Id="TARGETDIR" Name="SourceDir">
17 + <Directory Id="ProgramFilesFolder">
18 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
19 + </Directory>
20 + </Directory>
21 + </Fragment>
22 +</Wix>
src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs new
+14
@@ -0,0 +1,14 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3 + xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
4 + <Fragment>
5 + <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
6 + <Component>
7 + <File Source="example.txt" />
8 + <fw:FirewallException Description="An example outbound firewall" Name="example" Port="42" Outbound="yes">
9 + <fw:RemoteAddress>*</fw:RemoteAddress>
10 + </fw:FirewallException>
11 + </Component>
12 + </ComponentGroup>
13 + </Fragment>
14 +</Wix>
src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt new
+1
@@ -0,0 +1 @@
1 +This is example.txt.
\ No newline at end of file
src/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
+4
@@ -16,6 +16,10 @@
16 <Content Include="TestData\UsingFirewall\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
17 <Content Include="TestData\UsingFirewall\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
18 <Content Include="TestData\UsingFirewall\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
19 + <Content Include="TestData\UsingOutboundFirewall\example.txt" CopyToOutputDirectory="PreserveNewest" />
20 + <Content Include="TestData\UsingOutboundFirewall\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
21 + <Content Include="TestData\UsingOutboundFirewall\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
22 + <Content Include="TestData\UsingOutboundFirewall\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
23 </ItemGroup>
24
25 <ItemGroup>
src/wixext/FirewallCompiler.cs
+7
@@ -81,6 +81,7 @@ namespace WixToolset.Firewall
81 string scope = null;
82 string remoteAddresses = null;
83 string description = null;
84 + int? direction = null;
85
86 foreach (var attrib in element.Attributes())
87 {
@@ -177,6 +178,11 @@ namespace WixToolset.Firewall
178 case "Description":
179 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
180 break;
181 + case "Outbound":
182 + direction = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes
183 + ? FirewallConstants.NET_FW_RULE_DIR_OUT
184 + : FirewallConstants.NET_FW_RULE_DIR_IN;
185 + break;
186 default:
187 this.ParseHelper.UnexpectedAttribute(element, attrib);
188 break;
@@ -260,6 +266,7 @@ namespace WixToolset.Firewall
266 Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
267 ComponentRef = componentId,
268 Description = description,
269 + Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN,
270 });
271
272 if (!String.IsNullOrEmpty(port))
src/wixext/FirewallConstants.cs
+2
@@ -9,6 +9,8 @@ namespace WixToolset.Firewall
9 static class FirewallConstants
10 {
11 // from icftypes.h
12 + public const int NET_FW_RULE_DIR_IN = 1;
13 + public const int NET_FW_RULE_DIR_OUT = 2;
14 public const int NET_FW_IP_PROTOCOL_TCP = 6;
15 public const int NET_FW_IP_PROTOCOL_UDP = 17;
16
src/wixext/FirewallDecompiler.cs
+13
@@ -146,6 +146,19 @@ namespace WixToolset.Firewall
146 fire.Description = (string)row[9];
147 }
148
149 + if (!row.IsColumnEmpty(10))
150 + {
151 + switch (Convert.ToInt32(row[10]))
152 + {
153 + case FirewallConstants.NET_FW_RULE_DIR_IN:
154 + fire.Direction = Firewall.FirewallException.DirectionType.@in;
155 + break;
156 + case FirewallConstants.NET_FW_RULE_DIR_OUT:
157 + fire.Direction = Firewall.FirewallException.DirectionType.@out;
158 + break;
159 + }
160 + }
161 +
162 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]);
163 if (null != component)
164 {
src/wixext/FirewallTableDefinitions.cs
+1
@@ -21,6 +21,7 @@ namespace WixToolset.Firewall
21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."),
22 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the firewall configuration.", modularizeType: ColumnModularizeType.Column),
23 new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in Windows Firewall manager for this firewall rule."),
24 + new ColumnDefinition("Direction", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 1, maxValue: 2, description: "Direction (1=in; 2=out)"),
25 },
26 tupleIdIsPrimaryKey: true
27 );
src/wixext/Tuples/WixFirewallExceptionTuple.cs
+8
@@ -20,6 +20,7 @@ namespace WixToolset.Firewall
20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Profile), IntermediateFieldType.Number),
21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.ComponentRef), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Description), IntermediateFieldType.String),
23 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Direction), IntermediateFieldType.Number),
24 },
25 typeof(WixFirewallExceptionTuple));
26 }
@@ -40,6 +41,7 @@ namespace WixToolset.Firewall.Tuples
41 Profile,
42 ComponentRef,
43 Description,
44 + Direction,
45 }
46
47 public class WixFirewallExceptionTuple : IntermediateTuple
@@ -107,5 +109,11 @@ namespace WixToolset.Firewall.Tuples
109 get => this.Fields[(int)WixFirewallExceptionTupleFields.Description].AsString();
110 set => this.Set((int)WixFirewallExceptionTupleFields.Description, value);
111 }
112 +
113 + public int Direction
114 + {
115 + get => this.Fields[(int)WixFirewallExceptionTupleFields.Direction].AsNumber();
116 + set => this.Set((int)WixFirewallExceptionTupleFields.Direction, value);
117 + }
118 }
119 }
\ No newline at end of file
src/wixext/firewall.xsd
+9 -1
@@ -141,7 +141,7 @@
141 <xs:attribute name="IgnoreFailure" type="YesNoType">
142 <xs:annotation>
143 <xs:documentation>
144 - If "yes," failures to register this firewall exception will be silently
144 + If "yes", failures to register this firewall exception will be silently
145 ignored. If "no" (the default), failures will cause rollback.
146 </xs:documentation>
147 </xs:annotation>
@@ -170,6 +170,14 @@
170 </xs:documentation>
171 </xs:annotation>
172 </xs:attribute>
173 +
174 + <xs:attribute name="Outbound" type="YesNoType">
175 + <xs:annotation>
176 + <xs:documentation>
177 + If "yes", registers an outbound firewall rule.
178 + </xs:documentation>
179 + </xs:annotation>
180 + </xs:attribute>
181 </xs:complexType>
182 </xs:element>
183
src/wixlib/firewall.wixproj
+2 -2
@@ -1,7 +1,7 @@
1 <?xml version="1.0" encoding="utf-8"?>
2 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 <Project DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
4 - <Import Project="..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props" Condition="Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props')" />
4 + <Import Project="..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props" Condition="Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props')" />
5 <Import Project="..\FindLocalWix.props" />
6 <PropertyGroup>
7 <ProjectGuid>{1acffefd-505a-41a5-acbf-a02b7b473aa2}</ProjectGuid>
@@ -73,7 +73,7 @@
73 <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
74 </PropertyGroup>
75 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets'))" />
76 - <Error Condition="!Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props'))" />
76 + <Error Condition="!Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props'))" />
77 </Target>
78 <Import Project="..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" />
79 </Project>
\ No newline at end of file
src/wixlib/packages.config
+1 -1
@@ -1,5 +1,5 @@
1 <?xml version="1.0" encoding="utf-8"?>
2 <packages>
3 <package id="Nerdbank.GitVersioning" version="2.1.65" developmentDependency="true" targetFramework="net40" />
4 - <package id="WixToolset.MSBuild" version="4.0.0-build-0093" developmentDependency="true" targetFramework="net40" />
4 + <package id="WixToolset.MSBuild" version="4.0.0-build-0102" developmentDependency="true" targetFramework="net40" />
5 </packages>
\ No newline at end of file