Afficher des bulles de notification dans la barre des tâches en C#

icon Tags de l'article : , ,

Avril 16, 2015
Hello,

Un besoin qui revient souvent en C#, pour des appli Winforms simples : pouvoir afficher des notifications dans la barre des tâches en C#.

Pour cela, j'utilise toujours la même méthode : un notifyIcon et l'appel à la méthode ShowBalloonTip :

this.notifyIconFormMain.Visible = true;
this.notifyIconFormMain.BalloonTipIcon = ToolTipIcon.Info;
this.notifyIconFormMain.BalloonTipTitle = "Relax your eyes";
this.notifyIconFormMain.BalloonTipText = string.Format("You will have to relax your eyes in {0} minutes.", minutes);
this.notifyIconFormMain.ShowBalloonTip(4); // 4 = le nombre de secondes d'affichage du message

Et voilà, une bulle apparaitra dans le coin de votre écran pour afficher votre message pendant 4 secondes !



Bon dev à tous !

Verrouiller une session en C#

icon Tags de l'article : , , ,

Avril 15, 2015
Hello,

Juste un mini article : comment verrouiller une session en C#.

La réponse est simple, à l'aide de ce petit morceau de code qui utilise user32.dll :

private const int WmSyscommand = 0x0112;
private const int ScMonitorpower = 0xF170;
private const int HwndBroadcast = 0xFFFF;
private const int ShutOffDisplay = 2;
[DllImport("user32.dll")]
private static extern void LockWorkStation();
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

Voilà, vous n'avez plus qu'à appeler la jolie méthode LockWorkStation qui s'occupera de verrouiller la session utilisateur ! Pensez juste à faire attention quand vous testez, car si vous mettez ça dans une boucle vous risquez d'être bloqué... [oui, ça sent le vécu]

Bon dev!

source

Une classe de base pour manipuler SQLite facilement en C#

icon Tags de l'article : ,

Avril 03, 2015
Hello à tous,

Aujourd'hui je vais vous parler de SQLite. Lors d'un projet récent, j'ai eu à manipuler une BDD SQLite en C#. Pour cela j'ai créé une classe qui peut vous intéresser.

La première étape, pour manipuler du SQLite, est d'installer le package Nuget SQLite (et ses prérequis).

Ensuite, j'ai créé cette classe abstraite :

using System;
using System.Collections.Generic;
using System.Data.SQLite;

public abstract class BaseDA<T>
{
	public string ConnectionString { get; set; }

	public BaseDA(string connectionString)
	{
		this.ConnectionString = connectionString;
	}

	protected T GetUniqueItem(string sql, Func<SQLiteDataReader, T> mappingMethod)
	{
		var connection = new SQLiteConnection(this.ConnectionString);

		try
		{
			var command = new SQLiteCommand(sql, connection);

			var reader = command.ExecuteReader();

			if (reader.Read())
			{
				return mappingMethod(reader);
			}
		}
		finally
		{
			connection.Close();
		}

		return default(T);
	}

	protected IEnumerable<T> GetItems(string sql, Func<SQLiteDataReader, T> mappingMethod)
	{
		var connection = new SQLiteConnection(this.ConnectionString);

		try
		{
			var command = new SQLiteCommand(sql, connection);

			var reader = command.ExecuteReader();

			var result = new List<T>();

			while (reader.Read())
			{
				result.Add(mappingMethod(reader));
			}

			return result;
		}
		finally
		{
			connection.Close();
		}
	}

	protected int ExecuteNonQuery(string sql)
	{
		var connection = new SQLiteConnection(this.ConnectionString);

		try
		{
			var command = new SQLiteCommand(sql, connection);

			return command.ExecuteNonQuery();
		}
		finally
		{
			connection.Close();
		}
	}
}

Comme vous le voyez, cette classe contient 3 méthodes basiques me permettant de requêter facilement ma BDD SQLite.

Je n'ai plus qu'à créer une classe qui hérite de cette classe abstraite, pour, par exemple, gérer mes utilisateurs :

using ApiManager.BusinessEntities;
using System.Collections.Generic;
using System.Data.SQLite;

public class UserDA : BaseDA<UserBE>
{
	public UserDA(string connectionString) : base(connectionString)
	{
	}

	public UserBE GetUserByLogin(string login)
	{
		var sql = string.Format("SELECT * FROM User WHERE Login='{0}'", login);

		return GetUniqueItem(sql, this.MapUser);
	}

	public IEnumerable<UserBE> GetUsers()
	{
		var sql = "SELECT * FROM User";

		return (IEnumerable<UserBE>)GetItems(sql, this.MapUser);
	}

	public bool AddUser(UserBE user)
	{
		var sql = string.Format("INSERT INTO User VALUES ('{0}', '{1}', {2})", user.Login, user.Password, user.IsAdmin ? "1" : "0");

		return ExecuteNonQuery(sql) == 1;
	}

	public bool DeleteUser(int idUser)
	{
		var sql = string.Format("DELETE FROM User WHERE Id = {0}", idUser);

		return ExecuteNonQuery(sql) == 1;
	}

	private UserBE MapUser(SQLiteDataReader reader)
	{
		return new UserBE()
		{
			Id = (int)reader["Id"],
			Login = reader["Login"].ToString(),
			IsAdmin = (bool)reader["IsAdmin"],
			Password = reader["Password"].ToString()
		};
	}
}

Voilà, en résumé :
  • Ma classe mère, BaseDA, contient 3 méthodes pour requêter la BDD à partir de la connection string passée dans le constructeur.
  • Ensuite on crée une classe qui hérite de BaseDA et qui appelera le constructeur de cette dernière.
  • Enfin, on n'a plus qu'à appeler les méthodes de la classe mère avec le SQL désiré (et la méthode de mapping reader => objet dans le cas des méthodes de Get)

Voilà, on ne sait jamais, ça vous servira peut-être un jour !

Bonne journée à tous... Et bon weekend !

Comment stocker ses mots de passe en .Net

icon Tags de l'article : , ,

Novembre 24, 2014
Il existe de nombreuses façons de stocker les mots de passe pour une application ou un site web. La triste nouvelle, c'est que la majorité des sites et des applications n'utilisent pas les bonnes.

Aujourd'hui nous allons voir comment bien faire les choses.

Déjà, voici les différentes façons de faire, de la plus ridicule à la plus paranoïaque :

  • Niveau 0 : tout en clair. Rien de bien compliqué, aucune sécurité, la moindre fuite de données et on doit demander à nos utilisateurs de changer de mots de passe... Vraiment pas top pour l'image. Sécurité : 0%

  • Niveau 1 : mots de passe hashés avec une clef en dur. Pourquoi pas, sauf que... ça ne sert à rien. Le hacker n'aura qu'à générer des rainbow tables à partir de votre clef, et il aura les correspondances en clair pour tous les mots de passe hashés en base. Sécurité : 1%

  • Niveau 2 : on hashe les mots de passe avec un sel, généré aléatoirement pour chaque utilisateur. Un petit peu mieux. Seul bémol : il suffit de régénérer des Rainbow Tables, une par utilisateur, et ... on a tous les mots de passe. Sécurité : 5%

  • Niveau 3 : on hashe les mots de passe avec un sel, généré aléatoirement pour chaque utilisateur, à l'aide d'un algorithme lent : BlowFish. Ici on corrige le principal problème du niveau 2 : générer des Rainbow Tables pour chaque utilisateur peut prendre des jours, voire des mois... Sécurité : 80%

  • Niveau 4 : on utilise un module physique pour hasher les mots de passe. Si quelqu'un essaye de le déplacer ou d'y accéder, il effacera automatiquement toutes les données. Vous l'avez compris, il s'agit du mode paranoïaque ! Sécurité : 99%

Vous l'aurez compris, on va surtout s'intéresser au niveau 3, facilement réalisable et ne demandant pas, lui, d'investissements financiers. La clef repose sur le fait d'avoir un sel généré unique par utilisateur, et d'utiliser l'algorithme lent BlowFish. A l'échelle d'un site web, le temps de hash de l'algorithme est court. Mais lorsqu'on fait du bruteforce, le temps pour générer un dictionnaire entier de mots de passe est gigantesque !

La mise en place est plutôt simple :

Il faut d'abord créer deux entrées dans notre base, une pour le mot de passe hashé, et une pour le sel. Il ne faut jamais stocker ni déplacer le mot de passe non hashé. Si vous voulez bien faire les choses, utilisez HTTPS et stockez le sel ailleurs.



Ensuite, il faut ajouter BCrypt.Net à notre projet (via NuGet) :



Cette implémentation de l'algorithme BlowFish offre 2 méthodes : GenerateSalt et HashPassword, à utiliser comme suit :



Maintenant vous n'avez plus qu'à implémenter la bonne logique dans votre code :
  • Lorsque l'utilisateur s'inscrit, on génère et stocke un salt aléatoire pour lui, puis on se sert de ce salt pour hasher son mot de passe.
  • Lorsqu'il se connecte, on récupère le salt, et on hashe le mot de passe saisi à l'aide du salt pour ensuite comparer les deux hashs générés.
  • Lorsqu'il a perdu son mot de passe, on génère un mot de passe et un salt aléatoires, pour ensuite lui envoyer un mail avec son nouveau mot de passe.

Voilà, j'espère que ce petit article vous a plu,

Bonne soirée à tous !

Un petit outil pour gérer ses fichiers de traduction en PHP

icon Tags de l'article : , ,

Septembre 17, 2014
Hello,

Juste pour ceux que ça intéresse, voici un petit outil très simple que j'ai développé pour moi afin de gérer les traductions dans mes applications en PHP.

Resmanager (sur Github)

Le fonctionnement est très simple :
  • on remplit le fichier resources.lng avec nos traductions
  • on lance le petit exécutable ResourcesSplitter.exe
  • ce dernier va générer automatiquement des fichiers PHP avec nos traductions, un fichier par langue
  • on n'a plus qu'à inclure/utiliser ces fichiers dans nos applications

Le petit exe est fait en .Net, il est très simple et son code source est également présent sur le repository (fichier ResourcesSplitter.cs).

Voilà, on ne sait jamais, ça vous servira peut-être ! Si vous avez des questions n'hésitez pas !

Bon développement à tous !

(Et oui, pour ceux qui se demandent, je m'en sert pour la nouvelle version à venir de MyCryptoChat :)

Tests unitaires, présentation

icon Tags de l'article : , ,

Mars 25, 2014
Aujourd'hui, je vais vous parler de tests unitaires.

On teste tous nos développements. Que ce soit en compilant et regardant rapidement si ça marche, en déroulant un cahier de tests, en faisant n'importe quoi pour voir si on arrive à planter l'application, etc.

Sauf qu'assez peu de gens font des tests unitaires.

C'est triste, car il s'agit du meilleur moyen d'améliorer considérablement la qualité de vos développements, mais aussi d'anticiper sur les différents bugs à venir.

En effet, beaucoup de développeurs auront tendance à considérer les tests unitaires comme une perte de temps, voire un truc plutôt gadget qui coute toujours plus que ce qu'il apporte.

Ce n'est pas vrai.

De vrais bons tests unitaires auront effectivement un cout assez lourd au départ, mais ce cout sera vite amorti si vous passez du temps sur votre application.

Ca peut sembler idiot, mais c'est vrai.

A chaque développement, il y a un risque de coder un ou plusieurs bug. Voire même de faire réapparaître un ancien bug. Les tests unitaires permettent d'éliminer 90% des bugs.

Le vrai problème qui se pose est donc : comment bien faire mes tests unitaires ?

Nous verrons cela très bientôt, dans de futurs articles :
  • Quand faire des tests unitaires ?
  • Les tests de connectivité
  • Présentation des tests unitaires pour la couche d'accès aux données
  • Présentation des tests unitaires pour la couche métier

Bonne soirée !

Faut-il créer sa variable dans la boucle, ou en dehors ?

icon Tags de l'article :

Mars 24, 2014
Il s'agit d'une question qu'on a tous, je pense, entendu au moins une fois. Il existe trois types de réponses :

  • Il faut créer ta variable dans ton for, comme ceci :

for(int i = 0 ; i < maListe.Count ; i++) 
{
	int monI = maListe[i];
}

  • Pas du tout, il faut la créer avant :

int monI;
for(int i = 0 ; i < maListe.Count ; i++) 
{
	monI = maListe[i];
}

  • Et la bonne réponse : ça ne change rien.

Il faut savoir que les "variables" éphémères (monI dans ce cas) n'existent que pour le développeur.

En effet, le compilateur est capable d'identifier les variables qui ont une utilisation très spécifique, dans un scope réduit. Il remplacera alors l'utilisation de la variable par un accès direct à cette dernière.

Sur notre exemple :

for(int i = 0 ; i < maListe.Count ; i++) 
{
	int monI = maListe[i];
}

// génèrera strictement le même code MSIL que :

int monI;
for(int i = 0 ; i < maListe.Count ; i++) 
{
	monI = maListe[i];
}
// je n'utilise plus monI à partir d'ici

L'endroit où nous créerons notre variable monI n'a donc aucun impact sur le code MSIL généré.

Néanmoins, il est plutôt conseillé de la créer à l'intérieur du for, et ce pour plusieurs raisons :
  • L'optimiseur comprendra directement que la variable ne sera utilisée que dans la boucle et pas en dehors,
  • On ne transportera pas, à chaque itération, la valeur précédente,
  • On ne risque pas, par inadvertance, de la réutiliser en dehors de la boucle.

Mais il s'agit plus d'une bonne pratique que d'une optimisation.

Bonne soirée et bon dev à tous !

Méthodes d'extensions C# - 2

icon Tags de l'article :

Mars 24, 2014
Bonjour à tous !

Prêts pour une nouvelle fournée de méthodes d'extensions C# super-méga-ultra utiles ?

C'est parti !

Déjà, une méthode d'extension pour la classe string afin de faire bien plus rapidement nos String.Format (et non pas string.Format) :

public static string Format(this string s, params object[] args)
{
    return String.Format(s, args);
}

// et son appel

string myString = "{0} {1}";
myString.Format("Hello", "World");

Ensuite, une autre petite méthode qui va nous servir de raccourci : créer notre propre méthode d'extension Log sur la classe Exception pour unifier le logging de nos erreurs :

public static void Log(this Exception obj)
{
    // votre logique de logging ici
}

// et son utilisation

try
{
    // votre code
}
catch(Exception ex)
{
    ex.Log();
}

Ces deux petites méthodes vous feront gagner un temps fou, croyez-moi ;)

Bon dev à tous !

Méthodes d'extensions C# - 1

icon Tags de l'article :

Mars 21, 2014
Hello à tous,

J'ai décidé de commencer une petite série d'articles sur les méthodes d'extensions vraiment utiles.

A force de développer en C# sur différents projets, je me suis rendu compte que je m'étais constitué un joli petit pool de méthodes d'extensions... que je vais partager avec vous. Merci qui ? :)

Pour commencer, voici une méthode d'extension qui sert à faire un .Contains() case-insensitive sur une collection. Ca peut sembler simple et idiot, mais le faire à la main plusieurs fois est encore plus embêtant :

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    return source.IndexOf(toCheck, comp) >= 0;
}

// et son appel

bool contains = myString.Contains("hello", StringComparison.OrdinalIgnoreCase);

Et pour continuer sur cette lancée, voici une petite méthode d'extension pour vérifier si notre objet est présent dans une liste d'objets passés en paramètres, bien plus utile que ça en a l'air :

public static bool IsIn<T>(this T source, params T[] list)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    return list.Contains(source);
}

// et son appel

if (myString.IsIn("string1", "string2", "string3", "string4"))
{
    // do something
}

Bon weekend et bon dev à tous !

DateTime.Now ou DateTime.UtcNow

icon Tags de l'article :

Mars 20, 2014
Et vous, comment vous faites avec les dates ? - Doc Emmet Brown, ou pas.

Aujourd'hui on utilise tous les dates dans nos applications : récupération de la date courante, stockage d'une date précise, calculs sur des dates, etc.

Sauf qu'il existe deux façons de récupérer et de manipuler la date courante :

DateTime.Now
// ou
DateTime.UtcNow

Maintenant la question : laquelle utiliser ?

La réponse est simple : DateTime.UtcNow.

Pourquoi ?

Déjà DateTime.UtcNow est bien plus performant que DateTime.Now (du fait de ne pas avoir à gérer le fuseau horaires et les changements d'heure).

Ensuite, stocker des dates au format UTC permet d'éviter les nombreux problèmes d'incohérences sur les dates. En effet, utiliser DateTime.Now vous posera problème dès que vous hébergerez votre application dans un autre fuseau horaire (merci le Cloud !), dès que vous migrerez vos données, dès que vous effectuerez des calculs sur les dates, ...

Après vous pouvez toujours convertir la date pour l'afficher ou la manipuler, mais pour le stockage et à la récupération, il faut privilégier DateTime.UtcNow.

Vous ne direz pas qu'on ne vous a pas prévenu !

EDIT : Attention, il existe une exception : la réutilisation de dates. Lorsqu'on veut stocker une donnée au format date la réutiliser (par exemple planifier un rendez-vous récurrent tous les vendredis à 9h00), il ne faut pas la stocker au format UTC. Pourquoi ? Si on la stocke au format UTC et qu'on la convertie à chaque fois, le jour où on changera d'heure... Notre rendez-vous aussi changera d'heure ! Dans ce genre de situations (assez rares, il faut bien l'admettre), la solution est d'utiliser le DateTimeOffset.