Skip to content

Commit ccbeb23

Browse files
committed
Make sure that the signing of .js and .vbs files with the AzureSignToolSigner uses STA context.
1 parent 2652a87 commit ccbeb23

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

src/Sign.Core/DataFormatSigners/AzureSignToolSigner.cs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Sign.Core
1212
{
1313
internal sealed class AzureSignToolSigner : IAzureSignToolDataFormatSigner
1414
{
15+
private static readonly string[] StaThreadExtensions = [".js", ".vbs"];
16+
1517
private readonly ICertificateProvider _certificateProvider;
1618
private readonly ISignatureAlgorithmProvider _signatureAlgorithmProvider;
1719
private readonly ILogger<IDataFormatSigner> _logger;
@@ -113,25 +115,23 @@ public async Task SignAsync(IEnumerable<FileInfo> files, SignOptions options)
113115
options.FileHashAlgorithm,
114116
timestampConfiguration))
115117
{
118+
FileInfo[] staThreadFiles = [.. files.Where(file => StaThreadExtensions.Contains(file.Extension))];
119+
foreach (FileInfo file in staThreadFiles)
120+
{
121+
await RunOnStaThread(() => SignAsync(signer, file, options));
122+
}
123+
116124
// loop through all of the files here, looking for appx/eappx
117125
// mark each as being signed and strip appx
118126
await Parallel.ForEachAsync(files, async (file, state) =>
119127
{
120-
if (!await SignAsync(signer, file, options))
121-
{
122-
string message = string.Format(CultureInfo.CurrentCulture, Resources.SigningFailed, file.FullName);
123-
124-
throw new SigningException(message);
125-
}
128+
await SignAsync(signer, file, options);
126129
});
127130
}
128131
}
129132

130133
// Inspired from https://github.com/squaredup/bettersigntool/blob/master/bettersigntool/bettersigntool/SignCommand.cs
131-
private async Task<bool> SignAsync(
132-
AuthenticodeKeyVaultSigner signer,
133-
FileInfo file,
134-
SignOptions options)
134+
private async Task SignAsync(AuthenticodeKeyVaultSigner signer, FileInfo file, SignOptions options)
135135
{
136136
TimeSpan retry = TimeSpan.FromSeconds(5);
137137
const int maxAttempts = 3;
@@ -148,7 +148,7 @@ private async Task<bool> SignAsync(
148148

149149
if (RunSignTool(signer, file, options))
150150
{
151-
return true;
151+
return;
152152
}
153153

154154
++attempt;
@@ -157,7 +157,9 @@ private async Task<bool> SignAsync(
157157

158158
_logger.LogError(Resources.SigningFailedAfterAllAttempts);
159159

160-
return false;
160+
string message = string.Format(CultureInfo.CurrentCulture, Resources.SigningFailed, file.FullName);
161+
162+
throw new SigningException(message);
161163
}
162164

163165
private bool RunSignTool(AuthenticodeKeyVaultSigner signer, FileInfo file, SignOptions options)
@@ -198,5 +200,31 @@ private bool RunSignTool(AuthenticodeKeyVaultSigner signer, FileInfo file, SignO
198200

199201
return false;
200202
}
203+
204+
private static Task<bool> RunOnStaThread(Func<Task> func)
205+
{
206+
if (!OperatingSystem.IsWindows())
207+
{
208+
throw new NotSupportedException();
209+
}
210+
211+
TaskCompletionSource<bool> taskCompletionSource = new();
212+
var thread = new Thread(async () =>
213+
{
214+
try
215+
{
216+
await func();
217+
taskCompletionSource.SetResult(true);
218+
}
219+
catch (Exception exception)
220+
{
221+
taskCompletionSource.SetException(exception);
222+
}
223+
});
224+
225+
thread.SetApartmentState(ApartmentState.STA);
226+
thread.Start();
227+
return taskCompletionSource.Task;
228+
}
201229
}
202230
}

0 commit comments

Comments
 (0)