无法使用 Google Calendar API 加载 System.Threading.Task

Cannot load System.Threading.Tasks assembly, using Google Calendar API(无法使用 Google Calendar API 加载 System.Threading.Tasks 程序集)
本文介绍了无法使用 Google Calendar API 加载 System.Threading.Tasks 程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

非常感谢 Sam Leach

Huge thank to Sam Leach

这是我的工作 app.config 文件的示例:

Here is a sample of my working app.config file:

<configuration>
       ...
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="B03F5F7F11D50A3A" culture="neutral"/>
                <bindingRedirect oldVersion="0.0.0.0-2.5.19.0" newVersion="2.5.19.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Net.Http" publicKeyToken="B03F5F7F11D50A3A" culture="neutral"/>
                <bindingRedirect oldVersion="0.0.0.0-2.1.10.0" newVersion="2.1.10.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="B03F5F7F11D50A3A" culture="neutral"/>
                <bindingRedirect oldVersion="0.0.0.0-2.1.10.0" newVersion="2.1.10.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

我还发现 来源

原始问题在该行下方.

我正在使用 .NET 4.0 框架,根据我的研究,我知道不再需要 System.Threading.Tasks 程序集(因为它是自动包含的).我错了吗?

I am using the .NET 4.0 Framework and from my research I know that the System.Threading.Tasks assembly is no longer needed (because it's included automatically). Am I wrong about this?

如果我是对的,我现在很确定会引发错误,因为 google-api-dotnet-client 的开发人员使用的 System.Threading.Tasks 版本与 Visual Studio 2010 使用的版本不同.

If I am right, I am now pretty sure that the error is raised because the version of System.Threading.Tasks used by the developers of the google-api-dotnet-client and the one used by Visual Studio 2010 are different.

我注意到当我删除一些行时检查我的应用程序的行为.

I noticed that when inspecting the behavior of my app when I remove some lines.

这些台词出来了:

gcal = new CalendarService(new BaseClientService.Initializer()
{
    Authenticator = auth,
    ApplicationName = APP_NAME,
});

所以,我的新问题是:

有没有办法在 VS2010 中强制使用一个特定版本的参考程序集?

Is there a way to force the usage of one specific version of a reference assembly in VS2010 ?

感谢您帮助我,我相信它会帮助很多人,因为 google-calendar-api-v3 的文档记录不充分.

Thank you for helping me, I am sure it will help lots of people because the google-calendar-api-v3 is badly documented.

亲切的问候,布鲁诺.

我的问题是我无法通过 VisualStudio 访问 Google API 即服务.

My problem is that I can't get access to the Google API as a service through VisualStudio.

我收到此错误:

L'exception System.IO.FileLoadException n'a pas été gérée
  Message=Impossible de charger le fichier ou l'assembly 'System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' ou une de ses dépendances. La définition trouvée du manifeste de l'assembly ne correspond pas à la référence de l'assembly. (Exception de HRESULT : 0x80131040)
  Source=MVMA
  FileName=System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
  FusionLog==== Informations d'état de liaison préalable ===
JRN : utilisateur = MODALrbo
JRN : DisplayName = System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 (Fully-specified)
JRN : Appbase = file:///C:/Users/brbo/Documents/Visual Studio 2010/Projects/MVMA-V5.0 (With Gantt)/MVMA/bin/Debug/
JRN : PrivatePath initial = NULL
Assembly appelant : Google.Apis, Version=1.4.0.28227, Culture=neutral, PublicKeyToken=null.
===
JRN : cette liaison démarre dans le contexte de chargement de default.
JRN : utilisation du fichier de configuration de l'application : C:UsersrboDocumentsVisual Studio 2010ProjectsMVMA-V5.0 (With Gantt)MVMAinDebugMVMA.vshost.exe.Config
JRN : utilisation du fichier de configuration d'hôte : 
JRN : utilisation du fichier de configuration de l'ordinateur à partir de C:WindowsMicrosoft.NETFramework64v4.0.30319configmachine.config.
JRN : référence post-stratégie : System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
JRN : tentative de téléchargement de la nouvelle URL file:///C:/Users/brbo/Documents/Visual Studio 2010/Projects/MVMA-V5.0 (With Gantt)/MVMA/bin/Debug/System.Threading.Tasks.DLL.
AVT : la comparaison du nom de l'assembly a entraîné l'incompatibilité : Version principale
ERR : impossible de terminer l'installation de l'assembly (hr = 0x80131040). Détection terminée.

  StackTrace:
   à MVMA.Classes.GoogleCalendar.BuildCalendarService()
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   à System.Threading.ThreadHelper.ThreadStart()

这是我的类(相同的命名空间),它尝试使用 Json Web 令牌连接到 Google Calendar API v3:

And here is my classes (same namespace) which tries to connect to the Google Calendar API v3 using Json Web Tokens:

public class GoogleCalendar
{

    // Chaînes d'accès aux services Google
    public const string APP_NAME = "HIDDEN";
    public const string CLIENT_ID = "HIDDEN";
    public const string CLIENT_SECRET = "HIDDEN";
    public const string SERVICE_CLIENT_ID = "HIDDEN";
    public const string EMAIL_ADDRESS = "HIDDEN";
    public const string PUB_KEY = "HIDDEN";
    public const string PRIV_KEY_PATH = @"C:MVMAHIDDEN-privatekey.p12";
    public const string PRIV_KEY_SECRET = "notasecret";
    public const string SIMPLE_API_KEY = "HIDDEN";
    public const string SCOPE_CALENDAR = "https://www.googleapis.com/auth/calendar";
    public const string SCOPE_CALENDAR_READONLY = "https://www.googleapis.com/auth/calendar.readonly";

    private static CalendarService gcal;

    public static void ImportFromMVMA()
    {
        Thread yat = new Thread(new ThreadStart(BuildCalendarService));
        yat.Start();
    }

    // Permet de récupérer le service calendrier
    // Define the method that receives a callback when the results are available.
    private static void BuildCalendarService() {

        var certificate = new X509Certificate2(PRIV_KEY_PATH, PRIV_KEY_SECRET, X509KeyStorageFlags.Exportable);
        var privateKey = certificate.Export(X509ContentType.Cert);

        var provider = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
        {
            ServiceAccountId = EMAIL_ADDRESS,
            Scope = SCOPE_CALENDAR
        };

        var auth = new OAuth2Authenticator<AssertionFlowClient>(provider, AssertionFlowClient.GetState);

        gcal = new CalendarService(new BaseClientService.Initializer()
                        {
                            Authenticator = auth,
                            ApplicationName = APP_NAME,
                        });
    }
}

public enum JwtHashAlgorithm
{
    RS256,
    HS384,
    HS512
}

public class JsonWebToken
{


    private static Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>> HashAlgorithms;

    static JsonWebToken()
    {
        HashAlgorithms = new Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>>
        {
            { JwtHashAlgorithm.RS256, (key, value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } },
            { JwtHashAlgorithm.HS384, (key, value) => { using (var sha = new HMACSHA384(key)) { return sha.ComputeHash(value); } } },
            { JwtHashAlgorithm.HS512, (key, value) => { using (var sha = new HMACSHA512(key)) { return sha.ComputeHash(value); } } }
        };
    }

    public static string Encode(object payload, string key, JwtHashAlgorithm algorithm)
    {
        return Encode(payload, Encoding.UTF8.GetBytes(key), algorithm);
    }

    public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm)
    {
        var segments = new List<string>();
        var header = new { alg = algorithm.ToString(), typ = "JWT" };

        byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
        byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));

        segments.Add(Base64UrlEncode(headerBytes));
        segments.Add(Base64UrlEncode(payloadBytes));

        var stringToSign = string.Join(".", segments.ToArray());

        var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);

        byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign);
        segments.Add(Base64UrlEncode(signature));

        return string.Join(".", segments.ToArray());
    }

    public static string Decode(string token, string key)
    {
        return Decode(token, key, true);
    }

    public static string Decode(string token, string key, bool verify)
    {
        var parts = token.Split('.');
        var header = parts[0];
        var payload = parts[1];
        byte[] crypto = Base64UrlDecode(parts[2]);

        var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
        var headerData = JObject.Parse(headerJson);
        var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
        var payloadData = JObject.Parse(payloadJson);

        if (verify)
        {
            var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload));
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var algorithm = (string)headerData["alg"];

            var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
            var decodedCrypto = Convert.ToBase64String(crypto);
            var decodedSignature = Convert.ToBase64String(signature);

            if (decodedCrypto != decodedSignature)
            {
                throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature));
            }
        }

        return payloadData.ToString();
    }

    private static JwtHashAlgorithm GetHashAlgorithm(string algorithm)
    {
        switch (algorithm)
        {
            case "RS256": return JwtHashAlgorithm.RS256;
            case "HS384": return JwtHashAlgorithm.HS384;
            case "HS512": return JwtHashAlgorithm.HS512;
            default: throw new InvalidOperationException("Algorithm not supported.");
        }
    }

    // from JWT spec
    private static string Base64UrlEncode(byte[] input)
    {
        var output = Convert.ToBase64String(input);
        output = output.Split('=')[0]; // Remove any trailing '='s
        output = output.Replace('+', '-'); // 62nd char of encoding
        output = output.Replace('/', '_'); // 63rd char of encoding
        return output;
    }

    // from JWT spec
    private static byte[] Base64UrlDecode(string input)
    {
        var output = input;
        output = output.Replace('-', '+'); // 62nd char of encoding
        output = output.Replace('_', '/'); // 63rd char of encoding
        switch (output.Length % 4) // Pad with trailing '='s
        {
            case 0: break; // No pad chars in this case
            case 2: output += "=="; break; // Two pad chars
            case 3: output += "="; break; // One pad char
            default: throw new System.Exception("Illegal base64url string!");
        }
        var converted = Convert.FromBase64String(output); // Standard base64 decoder
        return converted;
    }
}

public class GoogleJsonWebToken
{

    public static string GetAccessToken(string email, string certificateFilePath, string serviceScope)
    {
        var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        var issueTime = DateTime.Now;

        var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
        var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; // Expiration time is up to 1 hour, but lets play on safe side

        var payload = new
        {
            iss = email,
            scope = serviceScope,
            aud = "https://accounts.google.com/o/oauth2/token",
            exp = exp,
            iat = iat
        };

        var certificate = new X509Certificate2(certificateFilePath, GoogleCalendar.PRIV_KEY_SECRET);

        var privateKey = certificate.Export(X509ContentType.Cert);

        return JsonWebToken.Encode(payload, privateKey, JwtHashAlgorithm.RS256);
    }
}

我不明白为什么我在 System.Threading.Tasks 程序集上有一个 FileLoadException.我尝试向已经使用 Tasks 的应用程序添加新功能而没有问题.此应用使用在不同线程中运行的 TabPage 对象.

I don't understand why I have a FileLoadException on the System.Threading.Tasks assembly. I try to add a new functionality to an application which already use Tasks without problems. This app uses TabPage objects which run in different threads.

推荐答案

删除所有对 System.Threading.Tasks 的引用,然后从您使用的任何 .NET 版本中添加一个(.NET4.0).

Remove all references to System.Threading.Tasks and then add in the one from whatever .NET version you are using (.NET 4.0).

Google Calendar API 可能使用不同版本的 .NET

The Google Calendar API might be using a different version of .NET

手动重定向程序集

您可以在 app.config 中指定要使用的程序集版本

You can specify which version of the assembly to use in your app.config

  <dependentAssembly>
    <assemblyIdentity name="someAssembly"
      publicKeyToken="32ab4ba45e0a69a1"
      culture="en-us" />

    <bindingRedirect oldVersion="7.0.0.0" newVersion="8.0.0.0" />
  </dependentAssembly>

这篇关于无法使用 Google Calendar API 加载 System.Threading.Tasks 程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)