Support using response file for long command-lines in MakeSfxCA
Fixes wixtoolset/issues#4688
Rob Mensching committed
Mar 31, 2022 at 16:50 UTC
88b472e81aae5bcd68255469c5f54e9e35a41ec3
2 files changed
+81
-21
src/dtf/WixToolset.Dtf.CustomAction/WixToolset.Dtf.CustomAction.targets
+16
-6
@@ -29,7 +29,7 @@
29
@(IntermediateAssembly) - Managed custom action assembly.
30
@(Content) - Project items of type Content will be included in the package.
31
$(CustomActionContents) - Optional space-delimited list of additional files to include.
32
-
32
+
33
[OUT]
34
$(IntermediateOutputPath)$(TargetCAFileName) - Managed custom action package with unmanaged stub.
35
==================================================================================================
@@ -44,7 +44,7 @@
44
Condition=" '%(Extension)' == '.dll' or '%(Extension)' == '.exe' " />
45
<CustomActionReferenceContents Include="@(ReferenceComWrappersToCopyLocal)"
46
Condition=" '%(Extension)' == '.dll' or '%(Extension)' == '.exe' " />
47
-
47
+
48
<!-- include PDBs for Debug only -->
49
<CustomActionReferenceContents Include="@(IntermediateAssembly->'%(RootDir)%(Directory)%(Filename).pdb')"
50
Condition=" Exists('%(RootDir)%(Directory)%(Filename).pdb') and '$(Configuration)' == 'Debug' " />
@@ -60,17 +60,27 @@
60
- Project items of type Content
61
- Additional items in the CustomActionContents property
62
-->
63
+ <ItemGroup>
64
+ <CustomActionContents Include="@(CustomActionReferenceContents);@(Content->'%(FullPath)');$(CustomActionContents)" />
65
+
66
+ <IntermediateCAResponseFile TaskParameter="Value" PropertyName="IntermediateCAResponseFile" />
67
+ <IntermediateCAAssembly Include="@(IntermediateAssembly->'%(FullPath)')" />
68
+ <IntermediateCAPackage Include="@(IntermediateAssembly->'%(RootDir)%(Directory)$(TargetCAFileName)')" />
69
+ </ItemGroup>
70
+
71
+ <!-- Use a response file to pass the potentially very long contents to MakeSfxCA.exe -->
72
<PropertyGroup>
64
- <CustomActionContents>@(CustomActionReferenceContents);@(Content->'%(FullPath)');$(CustomActionContents)</CustomActionContents>
73
+ <IntermediateCAResponseFile>@(IntermediateCAPackage->'%(RootDir)%(Directory)%(Filename).rsp')</IntermediateCAResponseFile>
74
</PropertyGroup>
75
76
+ <WriteLinesToFile File="$(IntermediateCAResponseFile)" Lines="@(CustomActionContents->'"%(Identity)"')" Overwrite="true" />
77
+
78
<ItemGroup>
68
- <IntermediateCAAssembly Include="@(IntermediateAssembly->'%(FullPath)')" />
69
- <IntermediateCAPackage Include="@(IntermediateAssembly->'%(RootDir)%(Directory)$(TargetCAFileName)')" />
79
+ <FileWrites Include="$(IntermediateCAResponseFile)" />
80
</ItemGroup>
81
82
<!-- Run the MakeSfxCA.exe CA packaging tool. -->
73
- <Exec Command='"$(MakeSfxCA)" "@(IntermediateCAPackage)" "$(SfxCADll)" "@(IntermediateCAAssembly)" "$(CustomActionContents)"'
83
+ <Exec Command='"$(MakeSfxCA)" "@(IntermediateCAPackage)" "$(SfxCADll)" "@(IntermediateCAAssembly)" "@$(IntermediateCAResponseFile)"'
84
WorkingDirectory="$(ProjectDir)" />
85
86
<!-- Add modules to be copied to output dir. -->
src/dtf/WixToolset.Dtf.MakeSfxCA/MakeSfxCA.cs
+65
-15
@@ -3,11 +3,12 @@
3
namespace WixToolset.Dtf.MakeSfxCA
4
{
5
using System;
6
- using System.IO;
6
using System.Collections.Generic;
7
+ using System.IO;
8
+ using System.Linq;
9
+ using System.Reflection;
10
using System.Security;
11
using System.Text;
10
- using System.Reflection;
12
using WixToolset.Dtf.Compression;
13
using WixToolset.Dtf.Compression.Cab;
14
using WixToolset.Dtf.Resources;
@@ -28,12 +29,12 @@ namespace WixToolset.Dtf.MakeSfxCA
29
/// Prints usage text for the tool.
30
/// </summary>
31
/// <param name="w">Console text writer.</param>
31
- public static void Usage(TextWriter w)
32
+ private static void Usage(TextWriter w)
33
{
34
w.WriteLine("WiX Toolset custom action packager version {0}", Assembly.GetExecutingAssembly().GetName().Version);
35
w.WriteLine("Copyright (C) .NET Foundation and contributors. All rights reserved.");
36
w.WriteLine();
36
- w.WriteLine("Usage: WixToolset.Dtf.MakeSfxCA <outputca.dll> SfxCA.dll <inputca.dll> [support files ...]");
37
+ w.WriteLine("Usage: WixToolset.Dtf.MakeSfxCA [-v] <outputca.dll> SfxCA.dll <inputca.dll> [support files ...]");
38
w.WriteLine();
39
w.WriteLine("Makes a self-extracting managed MSI CA or UI DLL package.");
40
w.WriteLine("Support files must include " + MakeSfxCA.REQUIRED_WI_ASSEMBLY);
@@ -47,20 +48,42 @@ namespace WixToolset.Dtf.MakeSfxCA
48
/// <returns>0 on success, nonzero on failure.</returns>
49
public static int Main(string[] args)
50
{
50
- if (args.Length < 3)
51
+ var logger = TextWriter.Null;
52
+ var output = String.Empty;
53
+ var sfxDll = String.Empty;
54
+ var inputs = new List<string>();
55
+
56
+ var expandedArgs = ExpandArguments(args);
57
+
58
+ foreach (var arg in expandedArgs)
59
+ {
60
+ if (arg == "-v")
61
+ {
62
+ logger = Console.Out;
63
+ }
64
+ else if (String.IsNullOrEmpty(output))
65
+ {
66
+ output = arg;
67
+ }
68
+ else if (String.IsNullOrEmpty(sfxDll))
69
+ {
70
+ sfxDll = arg;
71
+ }
72
+ else
73
+ {
74
+ inputs.Add(arg);
75
+ }
76
+ }
77
+
78
+ if (inputs.Count == 0)
79
{
80
Usage(Console.Out);
81
return 1;
82
}
83
56
- var output = args[0];
57
- var sfxDll = args[1];
58
- var inputs = new string[args.Length - 2];
59
- Array.Copy(args, 2, inputs, 0, inputs.Length);
60
-
84
try
85
{
63
- Build(output, sfxDll, inputs, Console.Out);
86
+ Build(output, sfxDll, inputs, logger);
87
return 0;
88
}
89
catch (ArgumentException ex)
@@ -80,12 +103,39 @@ namespace WixToolset.Dtf.MakeSfxCA
103
}
104
}
105
106
+ /// <summary>
107
+ /// Read the arguments include parsing response files.
108
+ /// </summary>
109
+ /// <param name="args">Arguments to expand</param>
110
+ /// <returns>Expanded list of arguments</returns>
111
+ private static List<string> ExpandArguments(string[] args)
112
+ {
113
+ var result = new List<string>(args.Length);
114
+ foreach (var arg in args)
115
+ {
116
+ if (String.IsNullOrWhiteSpace(arg))
117
+ {
118
+ }
119
+ else if (arg.StartsWith("@"))
120
+ {
121
+ var parsed = File.ReadAllLines(arg.Substring(1));
122
+ result.AddRange(parsed.Select(p => p.Trim('"')).Where(p => !String.IsNullOrWhiteSpace(p)));
123
+ }
124
+ else
125
+ {
126
+ result.Add(arg);
127
+ }
128
+ }
129
+
130
+ return result;
131
+ }
132
+
133
/// <summary>
134
/// Packages up all the inputs to the output location.
135
/// </summary>
136
/// <exception cref="Exception">Various exceptions are thrown
137
/// if things go wrong.</exception>
88
- public static void Build(string output, string sfxDll, IList<string> inputs, TextWriter log)
138
+ private static void Build(string output, string sfxDll, IList<string> inputs, TextWriter log)
139
{
140
MakeSfxCA.log = log;
141
@@ -205,7 +255,7 @@ namespace WixToolset.Dtf.MakeSfxCA
255
/// </remarks>
256
private static void ResolveDependentAssemblies(IDictionary<string, string> inputFiles, string inputDir)
257
{
208
- AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += delegate(object sender, ResolveEventArgs args)
258
+ AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += delegate (object sender, ResolveEventArgs args)
259
{
260
AssemblyName resolveName = new AssemblyName(args.Name);
261
Assembly assembly = null;
@@ -416,7 +466,7 @@ namespace WixToolset.Dtf.MakeSfxCA
466
foreach (var argument in attribute.ConstructorArguments)
467
{
468
// The entry point name is the first positional argument, if specified.
419
- entryPointName = (string) argument.Value;
469
+ entryPointName = (string)argument.Value;
470
break;
471
}
472
@@ -472,7 +522,7 @@ namespace WixToolset.Dtf.MakeSfxCA
522
byte[] fileBytes;
523
using (var readStream = File.OpenRead(sfxDll))
524
{
475
- fileBytes = new byte[(int) readStream.Length];
525
+ fileBytes = new byte[(int)readStream.Length];
526
readStream.Read(fileBytes, 0, fileBytes.Length);
527
}
528