解决了 !
非常感谢Sam Leach
以下是我工作的app.config文件的示例:
<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>
我也发现了source
编辑:原始问题在线下.
我正在使用.NET 4.0 Framework,从我的研究中我知道不再需要System.Threading.Tasks程序集(因为它是自动包含的).
我错了吗?
如果我是对的,我现在非常确定会引发错误,因为google-api-dotnet-client开发人员使用的System.Threading.Tasks版本与Visual Studio 2010使用的版本不同.
当我删除一些行时,我注意到在检查应用程序的行为时.
这些线出来了:
gcal = new CalendarService(new BaseClientService.Initializer() { Authenticator = auth,ApplicationName = APP_NAME,});
所以,我的新问题是:
Is there a way to force the usage of one specific version of a reference assembly in VS2010 ?
感谢您帮助我,我相信它会对很多人有所帮助,因为google-calendar-api-v3的记录很糟糕.
亲切的问候,
布鲁诺.
我的问题是我无法通过VisualStudio访问Google API作为服务.
我收到此错误:
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,PublicKeyToken=b03f5f7f11d50a3a FusionLog==== Informations d'état de liaison préalable === JRN: utilisateur = MODAL\brbo JRN: DisplayName = System.Threading.Tasks,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,PublicKeyToken=null. === JRN: cette liaison démarre dans le contexte de chargement de default. JRN: utilisation du fichier de configuration de l'application: C:\Users\brbo\Documents\Visual Studio 2010\Projects\MVMA-V5.0 (With Gantt)\MVMA\bin\Debug\MVMA.vshost.exe.Config JRN: utilisation du fichier de configuration d'hôte: JRN: utilisation du fichier de configuration de l'ordinateur à partir de C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config. JRN: référence post-stratégie: System.Threading.Tasks,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,Object state) à System.Threading.ThreadHelper.ThreadStart()
这是我的类(相同的命名空间),它尝试使用Json Web Tokens连接到Google Calendar API v3:
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:\MVMA\HIDDEN-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,}); } } public enum JwtHashAlgorithm { RS256,HS384,HS512 } public class JsonWebToken { private static Dictionary<JwtHashAlgorithm,Func<byte[],byte[],byte[]>> HashAlgorithms; static JsonWebToken() { HashAlgorithms = new Dictionary<JwtHashAlgorithm,byte[]>> { { JwtHashAlgorithm.RS256,(key,value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } },{ JwtHashAlgorithm.HS384,value) => { using (var sha = new HMACSHA384(key)) { return sha.ComputeHash(value); } } },{ JwtHashAlgorithm.HS512,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,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,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.
我尝试向已经使用任务而没有问题的应用程序添加新功能.此应用程序使用在不同线程中运行的TabPage对象.
解决方法
删除对System.Threading.Tasks的所有引用,然后从您使用的任何.NET版本中添加一个(.NET 4.0).
Google Calendar API可能使用不同版本的.NET
您可以指定要在app.config中使用的程序集版本
<dependentAssembly> <assemblyIdentity name="someAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="en-us" /> <bindingRedirect oldVersion="7.0.0.0" newVersion="8.0.0.0" /> </dependentAssembly>