BugshunterJérémy Jeanson - chasseur de bugs depuis .net 1.0uuid:159e33a6-cab7-4155-af2e-7c9518edb805;id=292018-07-22T06:19:25Z219Besoin de vider le dossier obj avant une build ?2018-07-20T17:24:00Z

Par moment, il est utile de vider le dossier obj avant de lancer une build. S’il faut la faire avant chaque build, ce petit désagrément devient vite insupportable. Il existe heureusement une solution.

Il suffit d’ajouter l’élément suivant à la fin du fichier .csprpoj :


<Target Name="CleanObj" BeforeTargets="BeforeBuild">
    <RemoveDir Directories="$(BaseIntermediateOutputPath)" />
</Target>

Personnellement, je réserve cette opération aux builds en mode Release. Je refaire donc utiliser la version suivante :


<Target Name="CleanObj" BeforeTargets="BeforeBuild" Condition="'$(Configuration)'=='Release'">
    <RemoveDir Directories="$(BaseIntermediateOutputPath)" />
</Target>
221Le package NuGet Boostrap Sass passe en version 4.1.22018-07-19T17:27:00Z

Bonne nouvelle pour les utilisateurs de Boostrap dans sa variante Sass. Le package nuget de la version 4.1.2 est enfin disponible !

Logo Bootstrapbootstrap.sass 4.1.2

Bootstrap Sass – Lien vers le package


Il aura fallu attendre un peu, mais on peut enfin mettre à jour ses projets web ;)

217Ouvrir un fichier Excel avec VSTO sans l&rsquo;afficher2018-07-18T17:21:00Z

À défaut, quand on créé un add-in Office avec les Visual Studio Tools for Office (VSTO pour C# et VB), l’ouverture de documents ouvre une nouvelle fenêtre par document. Ceci est valable pour tous les types de documents Office (Word, Excel, Poser Point, Visio…).

Si l’on souhaite cacher la fenêtre de ce document, on peut utiliser la collection Windows de celui-ci. Il y a cependant quelques effets de bord :

  • On ne peut exécuter aucune macro du fichier.
  • Le fichier peut demander à être enregistré à fermeture d’office (mais on peut ajouter un code à l’add-in pour interdire l’enregistrement).

Heureusement, il existe une solution plus élégante sous Excel : utiliser la propriété IsAddin du fichier. Celle-ci bien fait comprendre à office que le document est à considérer comme un add-in (ou un complément à notre add-in).

Comme indiqué par la documentation Excel, ceci a en plus les avantages suivants :

  • Il n’est jamais demandé à l’utilisateur d’enregistrer ce document.
  • Le document n’est pas visible.
  • La liste des macros n’est pas accessible à l’utilisateur (via les listes, et boites de dialogues).
  • On peut exécuter les macros du fichier.
  • La touche Shift n’a pas d’impact si elle est pressée lors de l’ouverture du document (l’utilisateur ne peut donc pas utiliser le debuger de macros Office pour intercepter vos macros)

Exemple d’utilisation :


// Fermeture du classeur courant
Globals.ThisAddIn.Application.ActiveWorkbook.Close(SaveChanges: false);

Workbook wb = Globals.ThisAddIn.Application.Workbooks.Open(
    // Fichier
    Filename: "MonFichier.xls",
    // Edition interdite
    ReadOnly: true,
    // Ne pas ajouter à l'historique
    AddToMru: false
    );

// Activer les macros
_wb.RunAutoMacros(Microsoft.Office.Interop.Excel.XlRunAutoMacro.xlAutoActivate);

//_pgpp.Application.Visible = false;
_wb.IsAddin = true;
218Le singleton le plus court au monde s&rsquo;&eacute;crit en C#2018-07-17T11:00:00Z

Depuis des années, j’écris des singletons avec le code suivant :


private static readonly MyClass Instance;

/// <summary>
/// Constructeur static
/// </summary>
static MyClass()
{
    // Instantiation du singelton
    Instance = new MyClass();
}

/// <summary>
/// Instance courante unique
/// </summary>
public static MyClass Current { get { return Instance; } }

/// <summary>
/// Constructeur privé
/// </summary>
private MyClass()
{
}

Mon singleton n’étant jamais supprimé, il n’est donc pas besoin d’être vérifié et instancié lors du Get. Je n’utilise pas de lock pour l’instanciation, car mon instance est créée via le constructeur statique (celui-ci ne peut être appelé qu’une fois).

Avec les dernières optimisations et simplifications de C# (propriétés privées en lecture seule), mon Singleton est devenu toujours plus court (2 lignes spécifiques):


/// <summary>
/// Constructeur statique
/// </summary>
static MyClass()
{
    // Instantiation du singelton
    Current = new MyClass();
}

/// <summary>
/// Instance courante unique
/// </summary>
public static MyClass Current { get; }


/// <summary>
/// Constructeur privé
/// </summary>
private MyClass()
{
}

À quand le Singleton en une ligne ?

216ALINK et x64 : L'assembly r&eacute;f&eacute;renc&eacute; 'mscorlib.dll' cible un processeur diff&eacute;rent2018-07-12T17:56:00Z

Peut-être avez-vous déjà rencontré le warning suivant :

L'assembly référencé 'mscorlib.dll' cible un processeur différent


Celui-ci se produit sur des projets exploitant des fichiers .resx quand on veut les compiler en 64 bits.

Un très vieux problème à l’époque de Visual Studio 2010 provoquait le même warning. En furetant ici et là sur le web on peut trouver diverses solutions plus ou moins compliquées pour résoudre ou contourner ce warning. Mais l’ensemble de ces solutions mixées ou mises bout à bout ne fonctionne pas sur Visual Studio 2017 (ou alors elles incluent des manipulations inutiles).

Pour résoudre le problème, il faut que le projet concerné indique à Visual Studio où se trouve le SDK en version 64 bits (c’est là que se trouve l’utilitaire dont Visual Studio 2017 a besoin lors de la compilation). Il se trouve que la seule différence entre la version 32, et la version 64 est qu’il faut ajouter x64 au nom du dossier en version 64 bits.

L’information doit être ajoutée en toute fin du fichier .csporoj (juste avant la balise fermante </Project> ).


<Target Name="Resx" BeforeTargets="BeforeBuild" >
  <PropertyGroup Condition="'$(Platform)'=='x64'">
    <TargetFrameworkSDKToolsDirectory>$(TargetFrameworkSDKToolsDirectory)$(Platform)\</TargetFrameworkSDKToolsDirectory>
  </PropertyGroup>
</Target>

Description de la modification :

  • Target a une propriété Name donnée en rapport avec le problème à résoudre. Mais on peut très bien lui donner un autre nom (du moment qu’il n’est pas déjà utilisé ou qu’il ne s’agit pas de BeforeBuild ou AfterBuild)
  • Target a un attribut BeforeTargets égale à BeforeBuild, car l’information doit être disponible avant la build.
  • PropertyGroup a une Condition pour n’utiliser les porpiétés qui suivant qu’avec la compilation en 64 bits.
  • TargetFrameworkSDKToolsDirectory est le chemin que l’on veut définir.


Je n’ai pas fourni de liens vers des solutions similaires, car comme évoqué plus haut, elles ne concernent pas de cas, ou incluent plus de modifications que nécessaire.

215Probl&egrave;mes de compatibilit&eacute; entre Entity Framework et le Multilingual App Toolkit ?2018-07-11T17:46:00Z

Entity Framework et le le Multilingual App Toolkit  (MAT) utilisent tous deux les fichiers de ressources :.

  • EF les utilise pour garder des traces des migrations.
  • MAT les utilise pour trouver les informations à localiser.

EF et MAT sont compatibles?

Si les deux sont utilisées dans un même projet, il est utile de prendre une précaution simple :

  • Pour chaque fichier .xlf manipuler par MAT, il faut marquer les informations de EF comme n’étant pas à traduire.
  • Un fichier de rexs est produit par MAT pour chaque migration. Il est vide, mais ne faut pas le supprimer.

MAT et EF sont alors compatibles.

Où est le problème?

Malgré cela, il peut arriver que le MAT fasse remonter des warnings du type :

Warnings liés à MAT


Côté migration, il manque effectivement des fichiers .fr-FR.resx (2 sur 4).

Liste de fichier produits pour la migration Entity Framework

Dans ce cas, le MAT indique que des ressources ne sont plus présentes. Un développeur les a peut être supprimées par erreur.

Comment s’en sortir?

Pour s’en sortir, il faut créer un fichier fr-FR.rex pour chaque fichier manquant (si cela est possible, aller les chercher dans TFS).

Le fichier peut être créé en faisant une copie du fichier d’origine.

Ensuite, il faut bien vérifier que le fichier fr-FR.xlf indiqué, les ressources sont bien indiquées comme n’étant pas à traduire.

Liste de données marquées comme n'étant pas à traduire


Peut-on avoir une approche plus propre?

Il existe une solution qui n'est pas documentée, mais qui est expliquée sur le Uservoice de MAT. Elle consiste à marquer les fichiers que MAT doit ignorer.

Pour cela il faut ouvrir son fichier .csproj et modifier à la main les noeuds EmbeddedResource qui concernent un fichier à exclure. Pour chaque noeud, on ajoute <SuppressAutomaticLocalization>true</SuppressAutomaticLocalization>.

Noeuds xml à modifier

Moralité

Toujours être vigilant et méthodique quand on utilise des technologies qui exploitent le même type de solutions pour des usages bien différents.

Bien évidemment, l'approche la plus simple consiste à isoler les ressources à localiser dans une autre assembly. Ainsi MAT ne cherchera pas à interagir avec un fichier qui n'est pas à localiser.

214Erreur de redirection de version de System.Net.Http2018-07-10T11:00:00Z

Peut-être avez-vous un souci récurant avec System.Net.Http qui fait qu’à chaque mise à jour de vos packages nuget, votre configuration n’est plus bonne.

Votre librairie System.Net.Http en version 4.3.3 devrait inclure une redirection vers l’assembly 4.2.2.0, mais celui-ci change pour une autre valeur.

Dans l’idéal votre configuration contiendrait ceci :


<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
   <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
</dependentAssembly>

Mais devient régulièrement :


<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
   <bindingRedirect oldVersion="0.0.0.0-4.1.1.2" newVersion="4.1.1.2"/>
</dependentAssembly>

Le numéro 4.x.x.x peut varier

Pas terrible comme situation. Plutôt que de pester après Visual studio, il serait bon de jeter un œil aux warnings de votre solution.

Il est fort probable que vous ayez un message de la sorte :

Liste de warnings liés à la configuration

Pour s’en sortir, il suffit de suivre la consigne indiquée. On sélectionne la ligne de warning et on valide la correction via la touche Enter de son clavier (le double click fonctionne aussi). Ce qui affichera la boite de dialogue suivante :

Question préléminaire à la correction du fichier de configuration

Après validation, votre fichier de configuration contiendra les redirections manquantes et vous ne rencontrerez plus de problèmes avec System.Net.Http.

Moralité

Toujours laisser visibles les warnings, et prendre le temps de les lire pour les résoudre. Les cacher, c’est mal !

Un projet qui est stable et qui s’inscrit dans le temps n’a pas de warnings.213Alertes invisibles avec bootstrap 4 ?2018-07-09T18:04:00Z

Si vous utilisez un code tel que celui-ci avec bootstrap 3, vos alertes seront invisibles quand vous migrerez vers bootstrap 4.


<div class="alert alert-info fade in">
...
</div>

Voici un petit problème tout simple qui m’a déjà été remonté une paire de fois. Je présume que la documentation de la migration de bootstrap 3 à 4 n’est pas suffisamment explicite.

Il y a en fait une classe qui a changé de la version 3 à la version 4. On ne doit plus utiliser in, mais show.

Ce qui donne :


<div class="alert alert-info fade show">
...
</div>

On peut voire son usage dans la documentions des alertes (section Dismissing).

212Stop la multiplication des migrations inutiles avec EF Code First !2018-07-05T18:04:00Z

À mon sens la migration est la fonctionnalité ultime d’Entity Framework. Par moment, il m’arrive cependant de la détester…

Vous avez peut-être déjà vécu l’un de ces moments : On reprend un projet qui beaucoup évolué par rapport au plan initial et l’on souhaite explorer le modèle de donnée. Là on découvre qu’il y a plus de 100 fichiers dans le dossier Migrations alors que l’application en est tout au plus à sa 10ème release…

Forcément quand l’application créé une nouvelle base, c’est un peu lent.

Ce rapport dix migrations pour une Release est totalement disproportionné. Alors que s’est-il passé ?

Si vous explorer votre TFS ou votre Git, vous allez certainement constater l’un des points suivants :

  • Il y a eu trop de micro-check-in sur le modèle de données.
  • Lors d’un même de check-in il y a plusieurs migrations.

Parfois, il peut effectivement être utile de faire des micro-check-in (je suis d’ailleurs partisan de ceux-ci le reste du temps). Mais si cela implique la multiplication des migrations, c’est une mauvaise idée.

Mais pourquoi cela impliquerait la multiplication des migrations ? Et pourquoi un développeur remonterait plusieurs migrations en un seul check-in ?

En discutant avec plusieurs équipes, je me suis rendu compte qu’il y avait une grosse méprise sur l’utilité des migrations :

  • Dès que le modèle de données change, une migration est ajoutée au projet.
  • Durant les tests, on peut avoir besoin de faire plusieurs tests pour préparer une release. Une migration est produite avant chaque test

L’intérêt de la migration, est de faire évoluer une base de données existante sans perde ses données tout en restant en mesure de monter ou descendre de version son modèle. Donc si on ne déploie pas l’application en production, il n’est pas d’intérêt à produire une migration.

Alors, pourquoi font-ils ainsi ?

La réponse est malheureusement simple : ils ne savent pas que l’on peut utiliser plusieurs fois de suite la commande add-migration avec le même nom de migration. Finalement, une seule migration sera produite.

Pourtant, quand on ajoute une migration, le message affiché dans la console est très explicite :


PM> add-migration MigrationName
Scaffolding migration 'MigrationName'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration MigrationName' again.

Moralité

Prenez le temps de lire ce qui s’affiche dans la console. Vous éviterez de polluer vos projets ;)

Pour rappel, lors des tests, on peut aussi supprimer des migration via la commande Remove-Migration. Alors, pourquoi se priver ?

211MVP Award 2018-20192018-07-02T18:36:00Z

Logo Microsoft Most Valuable Professional

Ce dimanche, j’ai été récompensé par Microsoft qui m’a décerné un nouveau MVP Award (catégorie Visual Studio and Development Technologies).

Un grand merci à Microsoft et à la communauté des développeurs qui me suit. Sans eux cette belle aventure ne serait pas possible.

Pour fêter cela, mon blog inaugure une option d’accessibilité pour les utilisateurs dyslexiques.