@joebigelow / wix-1 / commits / 88b472e8

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->'&quot;%(Identity)&quot;')" 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