Skip to content

Commit 0d82ebd

Browse files
Fix runspace issues in threading
1 parent 55340f9 commit 0d82ebd

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

src/code/PSResourceGetCredentialProvider.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Management.Automation;
7+
using System.Management.Automation.Runspaces;
78
using System.Net.Http;
89
using System.Text.Json;
910
using System.Threading;
@@ -24,6 +25,7 @@ internal class PSResourceGetCredentialProvider : ICredentialProvider
2425
{
2526
private readonly PSRepositoryInfo _repository;
2627
private readonly PSCmdlet _cmdletPassedIn;
28+
private readonly Runspace _callerRunspace;
2729
private readonly string _registryHost;
2830
private readonly HttpClient _httpClient;
2931
private Credential _cachedCredential;
@@ -38,6 +40,7 @@ internal PSResourceGetCredentialProvider(PSRepositoryInfo repository, PSCmdlet c
3840
{
3941
_repository = repository;
4042
_cmdletPassedIn = cmdletPassedIn;
43+
_callerRunspace = Runspace.DefaultRunspace;
4144
_registryHost = repository.Uri.Host;
4245
_httpClient = httpClient ?? new HttpClient();
4346
_cachedCredential = new Credential();
@@ -50,6 +53,25 @@ public async Task<Credential> ResolveCredentialAsync(string hostname, Cancellati
5053
throw new ArgumentException("Hostname cannot be null or empty.", nameof(hostname));
5154
}
5255

56+
// ORAS invokes this callback on a thread pool thread which has no
57+
// PowerShell Runspace. Restore the caller's Runspace so that
58+
// InvokeCommand.InvokeScript, WriteVerbose, WriteWarning and any
59+
// nested PowerShell script invocations (SecretManagement, etc.) work.
60+
var previousRunspace = Runspace.DefaultRunspace;
61+
Runspace.DefaultRunspace = _callerRunspace;
62+
63+
try
64+
{
65+
return await ResolveCredentialCoreAsync(hostname, cancellationToken).ConfigureAwait(false);
66+
}
67+
finally
68+
{
69+
Runspace.DefaultRunspace = previousRunspace;
70+
}
71+
}
72+
73+
private async Task<Credential> ResolveCredentialCoreAsync(string hostname, CancellationToken cancellationToken)
74+
{
5375
// Return cached credential if still valid
5476
if (!string.IsNullOrEmpty(_cachedCredential.RefreshToken) && DateTimeOffset.UtcNow < _tokenExpiry)
5577
{

0 commit comments

Comments
 (0)