.Net Core exécuter des commandes Bash/Shell

Maintenant que .Net Core fonctionne sur Linux, on est tenté d’utiliser la puissance de cette OS mais aussi des applications qui y fonctionnes.
Mais n’oublions pas non plus les utilisateurs de Windows.

Je vous propose ici un code très légèrement remanié dont la source se trouve ici : https://loune.net/2017/06/running-shell-bash-commands-in-net-core/.
Dans le cas où vous voulez faire fonctionner des appels à Bash sous Windows, pensé à installer Git.
Car c’est sur lui que je me repose pour avoir l’exécutable du Bash.

    public static class ShellHelper
    {
        public static string Bash(this string cmd)
        {
            string bashPath = System.Runtime.InteropServices.RuntimeInformation.OSDescription.ToLower().Contains("windows")
                ? "C:\\Program Files\\Git\\bin\\bash.exe"
                :"/bin/bash";

            if (!File.Exists(bashPath))
            {
                throw new System.Exception("Bash n'est pas installé sur ce système");
            }

            var escapedArgs = cmd.Replace("\"", "\\\"");
            
            var process = new Process()
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = bashPath,
                    Arguments = $"-c \"{escapedArgs}\"",
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                }
            };

            process.Start();

            string result = process.StandardOutput.ReadToEnd();

            process.WaitForExit();

            return result;
        }
    }
}

Comme expliquer pas son auteur original, ce code est une méthode d’extension. Donc après avoir importé le namespace, vous pouvez l’utiliser comme suit :

var output = "ps aux".Bash(); 

output va contenir le STDOUT résultant. Le STDERR n’est pas capturé par la méthode. Mais cela peut être fait de manière simple en changeant la propriété RedirectStandardOutput et en lisant le contenu de process.StandardError

Publié dans .Net Core

.Net Core application console comment cacher la saisie d’un mot de passe

Je travaillais sur une application console (CLI) faite en .Net Core et je me suis demandé :
Mais comment faire pour que la saisie d’un mot de passe dans la console soit comme sur Linux, c’est-à-dire que la saisie ne s’affiche pas dans la console ?

En fait c’est d’une simplicité déconcertante

private string AskForPassword()
{
    Console.Write("Veuillez saisir votre mot de passe : ");

    string password = "";
    ConsoleKeyInfo info = Console.ReadKey(true);
    while (info.Key != ConsoleKey.Enter)
    {
        if (info.Key != ConsoleKey.Backspace)
        {
            password += info.KeyChar;
            info = Console.ReadKey(true);
        }
        else if (info.Key == ConsoleKey.Backspace)
        {
            if (!string.IsNullOrEmpty(password))
            {
                password = password.Substring
                (0, password.Length - 1);
            }
            info = Console.ReadKey(true);
        }
    }

    return password;
}

Source du code

Publié dans .Net Core

How to create Nuget Package for .Net Core

Yep! Another article about Nuget package creation. And you know why? It’s a pain in the ass (hou rude words for a shiny morning…).

When I discover Nuget packages I was really enthusiast. It’s look like Composer package. But not really…

You have to manage by hand all the dependencies. And that’s make me angry!

I’m a lazy developer, so how can I make easily a Nuget package, with just only one command line?

Follow me, I show you.

This article is based on my work on the GST.Library that is a .Net Core solution who hold some libraries. I’ve faced the problem of building multi Nuget package from one solution. We need to automate the build of each package and we need something to manage dependencies and cross dependencies of each project.

The solution file organisation:

| GST.Library.sln
|
+---artifacts
| GST.Library.API.REST.1.0.0.nupkg
| GST.Library.API.REST.1.0.0.symbols.nupkg
|
+---src
| +---GST.Library.API.REST
| | | GST.Library.API.REST.nuspec
| | | project.json
| | |
| | +---Annotations
| | \---Pagination
| |
| +---GST.Library.Data
| | | GST.Library.Data.nuspec
| | | project.json
| | |
| | \---Extentions
| |
| +---GST.Library.Helper
| | | GST.Library.Helper.nuspec
| | | project.json
| | |
| | \---Type
| |
| \---GST.Library.StoredProcedureHelper
| | GST.Library.StoredProcedureHelper.nuspec
| \ project.json
|
+---test
\---tools

First of all, we are using Cake (for once cake is not a lie)! Cake is a task runner like Grunt, but made for Windows stuff, like building .Net Core application or C# DSL. What is nice with Cake, that it is cross platform application (you can use it on Linux).

To use Cake, we have to copy two (or one file) from their Github repo https://github.com/cake-build/example.

Take `build.ps1` for running with Powershell or `build.sh` for running with bash.

These two files contains the code for installing Cake, if it’s not, and running the `build.cake` file who will contain all our needed tasks to build Nuget packages.

Now you have to create a `build.cake` file and put this code inside :

#tool "nuget:?package=xunit.runner.console"
//////////////////////////////////////////////////////////////////////
// ARGUMENTS
//////////////////////////////////////////////////////////////////////

var target = Argument("target", "BuildPackages");
var configuration = Argument("configuration", "Release");

//////////////////////////////////////////////////////////////////////
// PREPARATION
//////////////////////////////////////////////////////////////////////

// Define directories.
var artifactsDir  = Directory("./artifacts/");
var rootAbsoluteDir = MakeAbsolute(Directory("./")).FullPath;

//////////////////////////////////////////////////////////////////////
// TASKS
//////////////////////////////////////////////////////////////////////

Task("Clean")
    .Does(() =>
{
    CleanDirectory(artifactsDir);
});

Task("Restore-NuGet-Packages")
    .IsDependentOn("Clean")
    .Does(() =>
{
	DotNetCoreRestore("src");
});

Task("BuildPackages")
    .IsDependentOn("Restore-NuGet-Packages")
    .Does(() =>
{
	var rootAbsoluteDir = "./build/bin";
    var nuGetPackSettings = new NuGetPackSettings
	{
		OutputDirectory = rootAbsoluteDir + @"\artifacts\",
		IncludeReferencedProjects = true,
		Properties = new Dictionary<string, string>
		{
			{ "Configuration", "Release" }
		}
	};

	var settings = new DotNetCoreBuildSettings
     {
         Framework = "netcoreapp1.1",
         Configuration = "Release",
         OutputDirectory = "./artifacts/"
     };

	DotNetCoreBuild("./src/**/project.json", settings);

	var packageSettings = new DotNetCorePackSettings
     {
         Configuration = "Release",
         OutputDirectory = "./artifacts/"
     };

    // For each project that we want to packaged
    DotNetCorePack("./src/GST.Library.API.REST/", packageSettings);
    DotNetCorePack("./src/GST.Library.Data/", packageSettings);
    DotNetCorePack("./src/GST.Library.Helper/", packageSettings);
    DotNetCorePack("./src/GST.Library.StoredProcedureHelper/", packageSettings);
});


//////////////////////////////////////////////////////////////////////
// EXECUTION
//////////////////////////////////////////////////////////////////////

RunTarget(target);

We have one more things to do. That’s the hard part. You have to install Nuget on your system (and add it to your environment variable) or just download the nuget.exe and put it in your project folder.
Now open a Terminal (Powershell console) and write : `nuget spec`
With this command line Nuget will create a ` Package.nuspec` file. This file is the manifest of your package.
Please take time to read the official documentation. But don’t waste time on the dependencies part. Our Cake script will take care to fill-up dependencies for us. We don’t have to do this manually, and that’s the real comfort to use automation.

You can take a look at our github repository https://github.com/GestionSystemesTelecom/gst-library , you will have a real world example. This repository is tie with Appveyor, and every time we push code on that repo, Appveyor compile and push nuget packages to nuget.org.

For the GST.Library, I wanted that each project would be a Nuget package. By putting in each project a “.nuspec” file and using Cake automation, I can easily create multi Nuget package.

Thanks to this blog post to show me the way: https://blog.codeinside.eu/2017/02/13/create-nuget-packages-with-cake/

Publié dans .Net Core

What to Do When Visual Studio Debugger Won’t Attach to Docker

I use Docker since months to developpe ASP.Net Core applications. It’s really something to work with this kind of technologies.

But sometime, a glitch come around and drive you crazy (just a little bit, not more). Docker was running fine and you update your Nuget’s packages (because it’s a good thing to keep ours dependencies up-to-date). And now, Visual Studio start to yell at you that kind of error:

The target process exited without raising a CoreCLR started event. Ensure that the target process is configured to use Microsoft.NETCoreApp 1.0.0 or newer. This may be expected if the target process did not run .NET code.

Like said the book « Don’t Panic! »

Two step to check.

First, in one of your project.json (if you use it), check if in the dependency you have the right syntax for Microsoft.NETCore.App, like below

"Microsoft.NETCore.App": {
"version": "1.1.1",
"type": "platform"
}

Second step, reset to factory defaults your Docker setup, like explain in this post https://dzone.com/articles/what-to-do-when-visual-studio-2017-debugger-wont-a (Yes I’m lazy, I use the same title with no shame ;) ).

If this two steps don’t resolve your problem, now you panic…

Publié dans Visual Studio

Configuration d’un Linux derrière un serveur proxy

Voici comment configurer pleinement un pc sous Linux (Ubuntu, Linux Mint) pour passer à travers un serveur proxy d’entreprise.

Cet article est donc un tutoriel pour configurer Linux pour l’utilisation de cette merveilleuse chose qu’est un serveur proxy d’entreprise.

Pour commencer il vous faut l’adresse IP et le port du serveur proxy. Pour notre article, le serveur proxy aura l’adresse 192.0.0.1, avec le port 8181.

Puis suivez les étapes ci-dessous :
Étape 1 – Configuration du nsswitch
Étape 2 – Configuration WPAD
Étape 3 – Configuration d’APT
Étape 4 – Configuration des variables d’environnements
Étape 5 – Configuration de la commande sudo
Étape 6 – Autres applications

Lire la suite ›

Publié dans Linux, Ubuntu

Symfony2 et jQuery Datatable

Nous avons tous eu, un jour, le besoin d’afficher un tableau de données dans nos pages Web. Quand c’est un tableau de données figées et peu nombreuses, nous le réalisons à la main. Quand elles sont dynamiques, mais toujours peu nombreuses, nos outils de templating, comme Twig, sont amplement suffisants.
Par contre, quand les données sont dynamiques, très nombreuses, qu’il faut gérer une pagination et si en plus ce tableau doit proposer la manipulation de ces données, là ça commence à être vraiment complexe.

Datatable est un plugin pour jQuery qui permet de réaliser simplement des tableaux de données (aussi appelé datagrid) dynamiques et paginables, avec chargement des données asynchrones, qui trie par colonne, filtre des données affichées et/ou filtre côté serveur. Il propose de nombreuses fonctionnalités ce qui le rend vraiment indispensable. Lire la suite ›

Tagués avec : , ,
Publié dans Doctrine, PHP, Symfony2

Plan d’auto-formation à Symfony2 et les concepts associés

Voici un plan d’auto formation à Symfony2 et ses concepts associés. Cet article comporte beaucoup de liens vers différentes documentations qui vous permettrons d’appréhender simplement Symfony2 et le monde de la qualité de code de PHP.

Sommaire

Lire la suite ›

Tagués avec :
Publié dans Non classé, PHP, Symfony2

Extension Doctrine pour la fonction Match Against

Voici un tutorial Symfony2 pour ajouter la fonction Match Againts à Doctrine pour l’utiliser dans vos requêtes DQL.

Le serveur de base de données Mysql gère la fonction Match Againts uniquement avec le moteur MyISAM. Cela est vrais pour les versions inférieur à la 5.6. Dans la version 5.6 cette fonction sera aussi géré par le moteur innoDB. Ce tutorial est donc à adapter si vous bénéficier d’une version 5.6 ou plus.

Lorsque l’on créé une base de données avec Doctrine, il utilise par défaut le moteur innoDB car il gère les relations entre les tables. On va donc être obligé de s’adapter.

Dans ce tutorial, nous cherchons à faire une recherche Full Text sur certain champ d’une entité Fiche. Pour cela nous allons devoir coder un peu.
Dans un premier temps nous allons ajouter la fonction Match Againts à Doctrine (avec ses tests unitaires).
Nous devrons créer ensuite une classe qui servira uniquement à la recherche Full Text. C’est contraignant, mais si vous tenez à réduire le nombre de requête SQL émise par votre application, c’est un mal nécessaire.
Enfin nous ajouterons un écouteur pour synchroniser notre classe d’indexation avec notre fiche.
Lire la suite ›

Tagués avec : , ,
Publié dans Doctrine, PHP, Symfony2

Symfony 2 – Vérifier le role d’un utilisateur dans un Voter

Petit How-To sur comment vérifier si un utilisateur à bien le rôle nécessaire pour effectuer une action dans un Voter.

Avant tout, deux petits lien, l’un vers la documentation des Voter de Symfony 2 et le second sur le fonctionnement du Gestionnaire de décision d’accès (Access Decision Manager) .

Nous verrons ici comment tester si l’utilisateur en cours dispose bien d’un rôle en prenant en compte la hiérarchisation des rôles offert par Symfony 2.

 

Dans un premier temps, il faut ajouter dans le fichier de configuration de l’injection de dépendance, une dépendance au service “security.access.role_hierarchy_voter”.

Votre déclaration de Voter ressemblera à cela :

<service id="security.voter.categorie" class="MyBundle\Security\Authorization\Voter\CategorieVoter" public="false">
   <argument type="service" id="security.access.role_hierarchy_voter" />
   <tag name="security.voter" />
</service>

Dans la classe de votre Voter, il faut bien entendu ajouter un attribut et le constructeur pour récupérer le service.

namespace MyBundle\Security\Authorization\Voter;

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class CategorieVoter implements VoterInterface
{
    /**
     * @var \Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter
     */
    private $roleVoter;

    public function __construct($roleVoter)
    {
            $this->roleVoter = $roleVoter;
    }
//...
}

L’utilisation est simple.

if($this->roleVoter->vote($token, $token->getUser(), array('ROLE_USER')) === VoterInterface::ACCESS_GRANTED) {
      // l’utilisateur à le role
}

Donc si votre utilisateur à un rôle admin, selon la hiérarchie des rôles, il à aussi un ROLE_USER. Donc le service renverra un VoterInterface::ACCESS_GRANTED !

Tagués avec : , ,
Publié dans PHP, Symfony2

Symfony – Internationalisation des dates pour Twig

Petit How To pour internationaliser l’affichage des dates dans Twig.

Dans le cas où l’on veut afficher des dates du type « 14 février 2032 » vous remarquerez que le filtre « date » avec les paramètres « d F Y » vous affichera la date en anglais.

Pour avoir nos date en français nous allons simplement installer l’extensions Intl de Twig qui ne fait pas partie du package par défaut.

Rendez-vous à l’adresse suivante : http://twig.sensiolabs.org/doc/extensions/intl.html
Sur cette page vous trouverez la commande pour installer l’extension Twig par Composer ou utilisez la commande suivante. Pensez juste à changer le numéro de version pour le dernier.

composer require twig/extensions ~1.2

Une fois ça de fait, vous avez fait la moitié du travail.

Ouvrez le fichier Resources/config/services.xml et ajoutez les lignes suivantes.
Ce paramétrage intègre l’extension à Twig.

    <services>
	< !-- [...] -->
        <service id="twig.extension.intl" class="Twig_Extensions_Extension_Intl">
            <tag name="twig.extension" />
        </service>
    </services>

Pour l’utilisation classique RTFM, et pour aller un peu plus loin (enfin pas trop loin), suivez le guide…

Donc voici quelques exemples :

Pour : 5 janvier

{{ post.published_at|localizeddate('none', 'none', null, null, 'd MMMM') }}

Pour : 5 janvier 1955

{{ post.published_at|localizeddate('none', 'none', null, null, 'd MMMM Y') }}

Pour : lundi 5 janvier 1955

{{ post.published_at|localizeddate('none', 'none', null, null, 'EEEE d MMMM Y') }}

Le formatage des dates se trouve à cette adresse : http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax

Publié dans Symfony2