在 C# 中授权 OneDrive 用户导致程序神秘崩溃
Authorizing OneDrive user in C# causes program to crash mysteriously
我正在使用 .Net Core 3.1 版编写控制台应用程序。目的是允许用户访问 Microsoft OneDrive 帐户并根据需要使用它们 fiddle。通过授权阶段被证明是困难的。这是一个代码片段,演示了我的工作:
//using statements
namespace HelloOneDrive
{
public class Program
{
static void Main(string[] args)
{
Task handleThing = (new Thing()).Handle();
}
}
public class Thing
{
public async Task Handle()
{
ClientCredentialProvider credentials;
string tenantId = //value
string clientId = //value
string clientSecret = //value
AuthenticationResult authResult;
string[] scopes = { "https://graph.microsoft.com/.default" };
CancellationToken cancellationToken = new CancellationToken();
GraphServiceClient client = null;
try
{
credentials = new ClientCredentialProvider(ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build());
}
catch (Exception ex)
{
//[logic for handling an exception, that never gets thrown]
}
try
{
authResult = await credentials
.ClientApplication
.AcquireTokenForClient(scopes)
.ExecuteAsync(cancellationToken);
}
catch (Exception ex)
{
//[logic for handling an exception, that never gets thrown]
//The program fails silently and suddenly, rather than hit
//this catch block.
Console.WriteLine("hello");
}
if (authResult != null)
{
client = new GraphServiceClient(
new DelegateAuthenticationProvider(
requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
}
if (client != null)
{
...
调试器将到达第二个try-catch
块,尝试定义authResult
,然后突然结束。没有异常被捕获;节目刚刚结束。
如果有用,我使用的 NuGet 包是:
- Microsoft.Graph v3.21.0
- Microsoft.Graph.Auth v1.0.0-preview.6
- Microsoft.Graph.Core v1.23.0 (v2.0.0-preview.4)
- Microsoft.Identity.Client v4.24.0
帮忙?
您正在从非异步 Main
调用 async
方法,而不是等待结果。因此,您的 Handle()
方法会同步执行,直到它到达第一个异步调用为止。 (authResult = await credentials...
) 然后把同步执行流程交还给Main
方法,这个方法没有别的事,就退出了。如果 Main
方法结束,当然整个过程结束,因为运行时不会等待 运行 任务完成,除非你明确告诉它这样做。
例如,您可以 Wait()
在 Main
方法中完成任务
static void Main(string[] args)
{
Task handleThing = (new Thing()).Handle();
handleThing.Wait();
}
或者您也可以让您的 Main
异步,然后 await
您的 Handle()
任务
static async Task Main(string[] args)
{
await (new Thing()).Handle();
}
我正在使用 .Net Core 3.1 版编写控制台应用程序。目的是允许用户访问 Microsoft OneDrive 帐户并根据需要使用它们 fiddle。通过授权阶段被证明是困难的。这是一个代码片段,演示了我的工作:
//using statements
namespace HelloOneDrive
{
public class Program
{
static void Main(string[] args)
{
Task handleThing = (new Thing()).Handle();
}
}
public class Thing
{
public async Task Handle()
{
ClientCredentialProvider credentials;
string tenantId = //value
string clientId = //value
string clientSecret = //value
AuthenticationResult authResult;
string[] scopes = { "https://graph.microsoft.com/.default" };
CancellationToken cancellationToken = new CancellationToken();
GraphServiceClient client = null;
try
{
credentials = new ClientCredentialProvider(ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build());
}
catch (Exception ex)
{
//[logic for handling an exception, that never gets thrown]
}
try
{
authResult = await credentials
.ClientApplication
.AcquireTokenForClient(scopes)
.ExecuteAsync(cancellationToken);
}
catch (Exception ex)
{
//[logic for handling an exception, that never gets thrown]
//The program fails silently and suddenly, rather than hit
//this catch block.
Console.WriteLine("hello");
}
if (authResult != null)
{
client = new GraphServiceClient(
new DelegateAuthenticationProvider(
requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
}
if (client != null)
{
...
调试器将到达第二个try-catch
块,尝试定义authResult
,然后突然结束。没有异常被捕获;节目刚刚结束。
如果有用,我使用的 NuGet 包是:
- Microsoft.Graph v3.21.0
- Microsoft.Graph.Auth v1.0.0-preview.6
- Microsoft.Graph.Core v1.23.0 (v2.0.0-preview.4)
- Microsoft.Identity.Client v4.24.0
帮忙?
您正在从非异步 Main
调用 async
方法,而不是等待结果。因此,您的 Handle()
方法会同步执行,直到它到达第一个异步调用为止。 (authResult = await credentials...
) 然后把同步执行流程交还给Main
方法,这个方法没有别的事,就退出了。如果 Main
方法结束,当然整个过程结束,因为运行时不会等待 运行 任务完成,除非你明确告诉它这样做。
例如,您可以 Wait()
在 Main
方法中完成任务
static void Main(string[] args)
{
Task handleThing = (new Thing()).Handle();
handleThing.Wait();
}
或者您也可以让您的 Main
异步,然后 await
您的 Handle()
任务
static async Task Main(string[] args)
{
await (new Thing()).Handle();
}