Retrieve filename and ID with Google Drive API in C# I am trying to retrieve filename and ID list with Google Drive API (the latest Drive API version v3 is used here) as a first step in order to analyze and manipulate these files on Google Drive. The experimental implementation is as below. (Note: credentials.json file is needed and the step to generate this file is here. )
The experimental implementation
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GoogleDriveFileManager
{
    class Program
    {
        static string[] Scopes = { DriveService.Scope.DriveReadonly };
        static string ApplicationName = &quot;GoogleDriveFileManager&quot;;

        static void Main(string[] args)
        {
            UserCredential credential;

            using (var stream =
                new FileStream(&quot;credentials.json&quot;, FileMode.Open, FileAccess.Read))
            {
                string credPath = &quot;token.json&quot;;
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    Scopes,
                    &quot;user&quot;,
                    CancellationToken.None,
                    new FileDataStore(credPath, true)).Result;
                Console.WriteLine($&quot;Credential file saved to: {credPath}&quot;);
            }

            // Create Drive API service.
            var service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = ApplicationName,
            });

            // Define parameters of request.
            FilesResource.ListRequest listRequest = service.Files.List();
            listRequest.PageSize = 1000;
            listRequest.Fields = &quot;nextPageToken, files(id, name)&quot;;

            // List files.
            IList&lt;Google.Apis.Drive.v3.Data.File&gt; files = listRequest.Execute()
                .Files;
            Console.WriteLine(&quot;Files:&quot;);
            Console.WriteLine($&quot;file.Name{new String('\t', 6)}file.Id{new String('\t', 8)}file.ModifiedTime&quot;);
            if (files != null &amp;&amp; files.Count &gt; 0)
            {
                foreach (var file in files)
                {
                    Console.WriteLine(
                        $&quot;{file.Name.PadRight(56)}{file.Id.PadRight(36)}{file.ModifiedTime}&quot;
                        );
                }
            }
            else
            {
                Console.WriteLine(&quot;No files found.&quot;);
            }
            Console.Read();
        }
    }
}

If there is any possible improvement about potential drawback or unnecessary overhead, please let me know.
First of all let me clarify that I'm not familiar with the Google Drive API. I've done some refactoring but I haven't tested it (just make it compile).
If I can assume you are using greater C# version than 8 then you can refactor your code like this:
using static {YourMainNamespace}.Constants;

class Program
{
    static async Task Main(string[] args)
    {
        UserCredential credential = await AuthorizeAgainstGoogleDriveAsync();
        IList&lt;Google.Apis.Drive.v3.Data.File&gt; files = await GetFilesMetaInfoAsync(credential);
        DisplayFilesMetaInfoInTabularFashion(files);
        Console.ReadLine();
    }

    static async Task&lt;UserCredential&gt; AuthorizeAgainstGoogleDriveAsync(
        string sourceRelativePath = Authorize.RelativeFilePath.Source,
        string targetRelativePath = Authorize.RelativeFilePath.Target)
    {
        using var stream = new FileStream(sourceRelativePath, FileMode.Open, FileAccess.Read);

        var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.Load(stream).Secrets,
            Authorize.Scopes,
            Authorize.User,
            CancellationToken.None,
            new FileDataStore(targetRelativePath, true));

        Console.WriteLine($&quot;Credential file saved to: {Authorize.RelativeFilePath.Target}&quot;);

        return credential;
    }

    static async Task&lt;IList&lt;Google.Apis.Drive.v3.Data.File&gt;&gt; GetFilesMetaInfoAsync(
        UserCredential credential,
        string applicationName = GetFiles.ApplicationName,
        int pageSize = GetFiles.PageSize,
        string fields = GetFiles.Fields)
    {
        var service = new DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = applicationName,
        });

        FilesResource.ListRequest listRequest = service.Files.List();
        listRequest.PageSize = pageSize;
        listRequest.Fields = fields;

        var fileList = await listRequest.ExecuteAsync();

        return fileList.Files;
    }

    static void DisplayFilesMetaInfoInTabularFashion(IList&lt;Google.Apis.Drive.v3.Data.File&gt; files)
    {
        Console.WriteLine(&quot;Files:&quot;);
        Console.WriteLine($&quot;{DisplayFiles.Name}{new string('\t', 6)}{DisplayFiles.Id}{new string('\t', 8)}{DisplayFiles.ModifiedTime}&quot;);

        if (files == null || files.Count &lt;= 0)
        {
            Console.WriteLine(DisplayFiles.NoFileMessage);
            return;
        }

        foreach (var file in files)
        {
            Console.WriteLine($&quot;{file.Name,-56}{file.Id,-36}{file.ModifiedTime}&quot;);
        }
            
    }
}

static class Constans
{
    public static class Authorize
    {
        public const string User = &quot;user&quot;;
        public readonly static string[] Scopes = new[] { DriveService.Scope.DriveReadonly };

        public static class RelativeFilePath
        {
            public const string Source = &quot;credentials.json&quot;;
            public const string Target = &quot;token.json&quot;;
        }
    }

    public static class GetFiles
    {
        public const string ApplicationName = &quot;GoogleDriveFileManager&quot;;
        public const int PageSize = 1000;
        public const string Fields = &quot;nextPageToken, files(id, name)&quot;;
    }

    public static class DisplayFiles
    {
        private const string prefix = &quot;file.&quot;;
        public const string Name = prefix + nameof(Name);
        public const string Id = prefix + nameof(Id);
        public const string ModifiedTime = prefix + nameof(ModifiedTime);
        public const string NoFileMessage = &quot;No files found.&quot;;
    }
}


Let me give you some context for each part:
Main
static async Task Main(string[] args)
{
    UserCredential credential = await AuthorizeAgainstGoogleDriveAsync();
    IList&lt;Google.Apis.Drive.v3.Data.File&gt; files = await GetFilesMetaInfoAsync(credential);
    DisplayFilesMetaInfoInTabularFashion(files);
    Console.ReadLine();
}


I've made your Main async (supported since C# 7.1) to be able to use async-await
I've split your logic into three smaller functions to make your Main short and concise

If the scope of the application is this small then you can use shorter names of course, like

AuthorizeAsync
GetFiles
DisplayFiles





Constants
using static {YourMainNamespace}.Constants;

...

static class Constans
{
    public static class Authorize
    {
        public const string User = &quot;user&quot;;
        public readonly static ImmutableArray&lt;string&gt; Scopes = new[] { DriveService.Scope.DriveReadonly }.ToImmutableArray();

        public static class RelativeFilePath
        {
            public const string Source = &quot;credentials.json&quot;;
            public const string Target = &quot;token.json&quot;;
        }
    }

    public static class GetFiles
    {
        public const string ApplicationName = &quot;GoogleDriveFileManager&quot;;
        public const int PageSize = 1000;
        public const string Fields = &quot;nextPageToken, files(id, name)&quot;;
    }

    public static class DisplayFiles
    {
        private const string prefix = &quot;file.&quot;;
        public const string Name = prefix + nameof(Name);
        public const string Id = prefix + nameof(Id);
        public const string ModifiedTime = prefix + nameof(ModifiedTime);
        public const string NoFileMessage = &quot;No files found.&quot;;
    }
}


I've put all of the hardcoded values into a hierarchical structure

Because I'm unfamiliar with the domain I've organize them based on the usage
In normal cases you should organize them based on their semantics


I've used const (which is implicit static) to prevent modification
In case of Scope I've used ImmutableArray to prevent modification

Here I can't use const but it could (and should) be marked as readonly


I've used using static to avoid prefixing with Constants each and every time

AuthorizeAgainstGoogleDriveAsync
static async Task&lt;UserCredential&gt; AuthorizeAgainstGoogleDriveAsync(
    string sourceRelativePath = Authorize.RelativeFilePath.Source,
    string targetRelativePath = Authorize.RelativeFilePath.Target)
{
    using var stream = new FileStream(sourceRelativePath, FileMode.Open, FileAccess.Read);

    var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
        GoogleClientSecrets.Load(stream).Secrets,
        Authorize.Scopes,
        Authorize.User,
        CancellationToken.None,
        new FileDataStore(targetRelativePath, true));

    Console.WriteLine($&quot;Credential file saved to: {Authorize.RelativeFilePath.Target}&quot;);

    return credential;
}


I've made the source and target file paths configurable (but with default values)

If you wish you can make the same with user and scopes


One can argue whether the Console.WriteLine should belong here or inside the Main

I've put it here to make the main as concise as possible
But from reusability point of view it should not belong here


I've used using declaration (which is a C# 8 feature) to avoid the block operator ({ ... })

GetFilesMetaInfoAsync
static async Task&lt;IList&lt;Google.Apis.Drive.v3.Data.File&gt;&gt; GetFilesMetaInfoAsync(
    UserCredential credential,
    string applicationName = GetFiles.ApplicationName,
    int pageSize = GetFiles.PageSize,
    string fields = GetFiles.Fields)
{
    var service = new DriveService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential,
        ApplicationName = applicationName,
    });

    FilesResource.ListRequest listRequest = service.Files.List();
    listRequest.PageSize = pageSize;
    listRequest.Fields = fields;

    var fileList = await listRequest.ExecuteAsync();

    return fileList.Files;
}


I've made this API call to async (Execute &gt;&gt; ExecuteAsync) to make use of the async non-blocking I/O
I've declared the function with three optional parameters to be able to customize the request if needed
I've realized that you are not making use of the nextPageToken but I did not remove it

I've assumed that the implementation of paging will be your next step



DisplayFilesMetaInfoInTabularFashion
static void DisplayFilesMetaInfoInTabularFashion(IList&lt;Google.Apis.Drive.v3.Data.File&gt; files)
{
    Console.WriteLine(&quot;Files:&quot;);
    Console.WriteLine($&quot;{DisplayFiles.Name}{new string('\t', 6)}{DisplayFiles.Id}{new string('\t', 8)}{DisplayFiles.ModifiedTime}&quot;);

    if (files == null || files.Count &lt;= 0)
    {
        Console.WriteLine(DisplayFiles.NoFileMessage);
        return;
    }

    foreach (var file in files)
    {
        Console.WriteLine($&quot;{file.Name,-56}{file.Id,-36}{file.ModifiedTime}&quot;);
    } 
}


This operation is tightly coupled to the request

It highly relies on the retrieved fields
So, it might make sense to it make more dynamic if needed


I've used new string instead of new String

I suggest to read this article


I've reverted the if statement to use the early exit pattern

With this the main logic (foreach) is not indented


I've also used the capabilities of string interpolation to avoid calls like PadRight