Авторизация пользователя OneDrive в C # приводит к таинственному сбою программы

#c# #.net-core #microsoft-graph-api #onedrive

#c# #.net-core #microsoft-graph-api #onedrive

Вопрос:

Я пишу консольное приложение с .Net Core версии 3.1. Цель состоит в том, чтобы разрешить пользователю доступ к учетным записям Microsoft OneDrive и манипулировать ими по своему усмотрению. Пройти стадию авторизации оказывается непросто. Вот фрагмент кода, демонстрирующий, что у меня происходит:

 //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 authResu<
            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, которые я использую, следующие:

  • Майкрософт.График v3.21.0
  • Майкрософт.График.Auth v1.0.0-предварительный просмотр.6
  • Майкрософт.График.Ядро v1.23.0 (v2.0.0-предварительный просмотр.4)
  • Майкрософт.Личность.Клиент v4.24.0

Помогите?

Комментарии:

1. Откуда вы знаете, что исключение не генерируется? Ваш код улавливает исключения, а затем отбрасывает их. Вы ничего не увидите, если не сделаете что-то в пределах блоков catch. Подавление допустимых исключений — это антишаблон.

2. Мой фактический код обрабатывает исключение; однако, для краткости, я не включил логику, точно так же, как я не включил свои using операторы или значения некоторых из моих переменных. Я знаю, что код не улавливает никаких исключений, потому что я несколько раз запускал отладчик через него построчно и был свидетелем возникновения. ^_^

3. Не могли бы вы отредактировать пример кода, чтобы было более понятно, что вы делаете с исключениями? Прямо сейчас ваши комментарии выглядят так, как будто вы напоминаете себе о необходимости реализовать обработку исключений.

4. ОК. Это действительно было совсем не ясно из вашего образца. Вы были бы удивлены, узнав, как много людей используют пустой catch только для того, чтобы избежать исключения, а затем он возвращается, чтобы укусить их, когда они не могут диагностировать ошибки. В любом случае, значит, в вашем журнале исключений ничего нет, когда код таинственным образом заканчивается? И он вообще никогда не попадает в if (authResult != null) строку? .NET-программы не просто случайным образом останавливаются в обычном режиме. Возможно, есть что-нибудь в главном журнале событий Windows?

5. В моем журнале исключений ничего нет, и он никогда не попадает в if блок. The program '[30860] HelloOneDrive.exe' has exited with code 0 (0x0). это единственное значение, выводимое отладчиком, которое только подтверждает, что программа по какой-то причине просто завершается.

Ответ №1:

Вы вызываете async метод из Main неасинхронного и не ждете результата. Таким образом, ваш 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();
}
 

Комментарии:

1. handleThing.Wait() сработало; большое вам спасибо! ^_^