Partager via



Septembre 2016

Volume 31, numéro 9

Cet article a fait l'objet d'une traduction automatique.

Essential .NET - Traitement de ligne de commande avec.NET Core 1.0

Par Mark Michaelis

Mark Michaelis Dans la colonne de .NET essentielles de ce mois-ci, mon enquête dans les différentes fonctionnalités de .NET Core, cette fois avec une version complète (et n’est plus en version bêta ou une version euphemistic finale) de continuer. En particulier, je vais me concentrer sur ses utilitaires de ligne de commande (qui se trouvent dans la bibliothèque .NET Core commun à github.com/aspnet/Common) et comment les utiliser pour l’analyse d’une ligne de commande. J’avoue que je suis actuellement particulièrement enthousiasme pour finalement voir l’assistance d’analyse de ligne de commande intégrée à .NET Core, comme c’est quelque chose que j’ai désiré depuis .NET Framework 1.0. J’espère qu’une bibliothèque intégrée de .NET Core peut-être vous aider à normaliser, même si seuls un peu, la format de ligne de commande/structure entre les programmes. Il n’est pas aussi important pour moi ce que la norme existe-t-il qu’être une convention de personnes par défaut, au lieu de tout le monde créer leurs propres.

Une Convention de ligne de commande

L’essentiel des fonctionnalités de ligne de commande se trouve dans le package NuGet de Microsoft.Extensions.CommandLineUtils. Inclus dans l’assembly est une classe CommandLineApplication qui fournit l’analyse de ligne de commande avec prise en charge pour les noms longs et courts pour les options de valeurs (un ou plusieurs) affecté par un signe deux-points ou égal signe et symboles comme- ? pour l’aide. À propos de l’aide, la classe prend en charge automatiquement et affiche le texte d’aide. Figure 1 montre des exemples de lignes de commande qui est pris en charge.

Figure 1 exemples de ligne de commande

Options Program.exe -f = Inigo, -l Montoya – hello – noms Princess – noms Buttercup

Option -f, avec la valeur « Inigo »

Option -l, avec la valeur « Montoya »

L’option – hello avec la valeur « on »

Option – noms avec les valeurs « Princesse » et « Buttercup »

Commandes avec des arguments Program.exe « hello », « Inigo », « Montoya », « It », « est », « a », « plaisir », « à », « répondre aux », « vous ».

Commande « hello »

Argument « Inigo »

Argument « Montoya »

Greetings argument avec les valeurs « It », « est », « a », « plaisance, » « à », « rencontrer », « vous. »

Symboles Program.exe- ? Afficher l’aide

 

Comme décrit plus loin, il existe plusieurs types d’arguments, une d’elles est appelée « Argument ». La surcharge de l’argument expression pour faire référence aux valeurs spécifiées sur la ligne de commande et les données de configuration de ligne de commande peut entraîner une ambiguïté significatif. Par conséquent, pour le reste de cet article, je vais faire la distinction entre un argument générique de n’importe quel type — spécifié après le nom du fichier exécutable, et le type d’argument appelée « Argument » (majuscule) par la casse. De même, je vais distinguer les autres types d’arguments, Option et commande, à l’aide de la casse, plutôt qu’aux termes de minuscules qui référence de manière générique à l’argument. Prenez note de ce car elle sera importante dans le reste de l’article.

Chacun des types d’argument est décrit comme suit :

  • Options Les options sont identifiées par un nom, où le nom est préfixé avec un seul (-) ou double tiret (-). Les noms des options sont définies par programme à l’aide de modèles et un modèle peut inclure une ou plusieurs des indicateurs suivants de trois : abrégée du nom, nom complet, symbole. En outre, une Option peut avoir une valeur associée. Par exemple, un modèle peut être «-n | --nom | -# < nom complet >, « la possibilité de nom complet être identifié par un des trois indicateurs. (Toutefois, le modèle n’a pas besoin tous les indicateurs de trois.) Notez qu’il s’agit de l’utilisation d’un tiret simple ou double qui détermine si un nom court ou long est spécifié, quelle que soit la longueur réelle du nom.
    Pour associer une valeur à une option, vous pouvez utiliser un espace ou l’opérateur d’assignation (=). -f = Inigo et -l Montoya, par conséquent, les deux exemples de spécifier une valeur d’option.
    Si les nombres sont utilisés dans le modèle, ils amèneront faire partie des noms courts ou trop longs, pas le symbole.
  • Arguments : Arguments sont identifiés par l’ordre dans lequel ils apparaissent, plutôt que par un nom. Par conséquent, une valeur de la ligne de commande qui n’est pas précédée d’un nom d’option est un argument. L’argument de la valeur correspond au repose sur l’ordre dans lequel il apparaît (les commandes et Options sont exclus dans le nombre).
  • Commandes : Les commandes fournissent un regroupement d’arguments et options. Par exemple, vous pouvez avoir une commande nom « hello » suivi d’une combinaison d’Arguments et Options (ou même sous-commandes). Commandes sont identifiés par un mot clé configuré, le nom de commande, qui regroupe toutes les valeurs qui suivent le nom de commande de faire partie de la définition de cette commande.

Configuration de la ligne de commande

Programmation de la ligne de commande après que référençant le Microsoft.Extensions.CommandLineUtils Core .NET commence par la classe CommandLineApplication. Avec cette classe, vous pouvez configurer chaque commande et Argument. Lorsque vous instanciez la CommandLineApplication, le constructeur a une valeur booléenne facultative qui configure la ligne de commande n’a pas été configurée spécifiquement pour lever une exception (par défaut) si un argument s’affiche.

Une instance donnée de le CommandLineApplication, configurer les arguments à l’aide de méthodes Option Argument et commande. Imaginons, par exemple, que vous souhaitez prendre en charge une syntaxe de ligne de commande comme suit, où les éléments entre crochets sont facultatifs et les crochets pointus sont les valeurs spécifiées par l’utilisateur ou les arguments :

Program.exe <-g|--greeting|-$ <greeting>> [name <fullname>] 
     [-?|-h|--help] [-u|--uppercase]

Figure 2 configure la fonctionnalité analyse de base.

Figure 2 Configuration de la ligne de commande

public static void Main(params string[] args)
{
    // Program.exe <-g|--greeting|-$ <greeting>> [name <fullname>]
    // [-?|-h|--help] [-u|--uppercase]
  CommandLineApplication commandLineApplication =
    new CommandLineApplication(throwOnUnexpectedArg: false);
  CommandArgument names = null;
  commandLineApplication.Command("name",
    (target) =>
      names = target.Argument(
        "fullname",
        "Enter the full name of the person to be greeted.",
        multipleValues: true));
  CommandOption greeting = commandLineApplication.Option(
    "-$|-g |--greeting <greeting>",
    "The greeting to display. The greeting supports"
    + " a format string where {fullname} will be "
    + "substituted with the full name.",
    CommandOptionType.SingleValue);
  CommandOption uppercase = commandLineApplication.Option(
    "-u | --uppercase", "Display the greeting in uppercase.",
    CommandOptionType.NoValue);
  commandLineApplication.HelpOption("-? | -h | --help");
  commandLineApplication.OnExecute(() =>
  {
    if (greeting.HasValue())
    {
      Greet(greeting.Value(), names.Values, uppercase.HasValue());
    }
    return 0;
  });
  commandLineApplication.Execute(args);
}
private static void Greet(
  string greeting, IEnumerable<string> values, bool useUppercase)
{
  Console.WriteLine(greeting);
}

Il commence par CommandLineApplication

Pour commencer, j’instancie le CommandLineApplication, spécifiez si l’analyse de ligne de commande sera strict, throwOnUnexpectedArg a la valeur true, ou moyenne. Si je spécifie pour lever une exception lorsqu’un argument est inattendu, tous les arguments devez être configurées de façon explicite. Vous pouvez également si throwOnUnexpectedArg a la valeur false, tous les arguments qui ne sont pas reconnus par la configuration stockées dans le champ CommandLineApplication.RemainingArguments.

Configuration d’une commande et son Argument

La prochaine étape dans Figure 2 consiste à configurer la commande « name ». Le mot clé qui identifie la commande dans une liste d’arguments est le premier paramètre de la fonction de la commande, nom. Le deuxième paramètre est un délégué Action < CommandLineApplication > appelé configuration, dans les sous-dossier tous les arguments du nom de commande sont configurés. Dans ce cas, il existe uniquement, un Argument de type CommandArgument avec le nom de la variable de « greeting ». Toutefois, il est tout à fait possible d’ajouter des Arguments supplémentaires, Options et même sous-commandes dans le délégué de la configuration. En outre, le paramètre de la cible du délégué, un CommandLineApplication, a une propriété Parent qui pointe vers l’attribut commandLineArgument, le parent attribut CommandLineArgument de cible sous lequel le nom de commande est configuré.

Notez que dans la configuration des noms de l’Argument I identifie spécifiquement que multipleValues prendra en charge. Ce faisant, autoriser plusieurs valeur — dans ce cas spécifier plusieurs noms. Chacune de ces valeurs s’affiche après l’identificateur d’argument « nom » jusqu'à l’apparition d’un autre identificateur d’argument ou option. Les deux premiers paramètres de la fonction d’Argument sont le nom, qui fait référence au nom de l’Argument qui vous pouvez d’identifier dans la liste des Arguments et la description.

Une dernière chose à remarquer dans la configuration de la commande nom est le fait que vous devez enregistrer le retour de la fonction d’Argument (et la fonction de l’Option s’il en existe une). Cela est nécessaire afin de récupérer les arguments associés à l’Argument de noms plus tard. Sans enregistrer une référence, vous obtenez ainsi effectuer une recherche dans les commandLineApplication.Commands[0]. Collection d’arguments afin de récupérer les données de l’Argument.

Une méthode élégante pour enregistrer toutes les données de ligne de commande consiste à placer dans une classe séparée qui est décorée avec les attributs du référentiel de génération de modèles automatique ASP.NET (github.com/aspnet/Scaffolding), en particulier dans le dossier src/Microsoft.VisualStudio.Web.CodeGeneration.Core/CommandLine. Pour plus d’informations, consultez « Mise en œuvre un en ligne de commande classe avec .NET Core » (bit.ly/296SluA).

Configuration d’une Option

L’argument suivant est configuré dans Figure 2 est le message d’accueil Option, qui est de type OptionCommande. Configuration d’une Option est effectuée via la fonction de l’Option, où le premier paramètre est un paramètre de chaîne appelé modèle. Notez que vous pouvez spécifier trois noms différents (pour par exemple, -$, -g et - message d’accueil) pour l’option et chacun d'entre eux seront être utilisés pour identifier l’option dans la liste d’arguments. En outre, un modèle peut éventuellement spécifier une valeur associée au moyen d’un nom entre crochets pointus après les identificateurs de l’option. Le paramètre description, la fonction de l’Option inclut un paramètre de CommandOptionType obligatoire. Cette option identifie :

  1. Si une valeur quelconque peut être spécifié après l’identificateur d’option. Si un CommandOptionType de NoValue est spécifié, la fonction CommandOption.Value est définie sur « on » si l’option apparaît dans la liste d’arguments. La valeur « on » est retournée même si une valeur différente est spécifiée après l’identificateur d’option et, en fait, si une valeur est spécifiée. Pour afficher un exemple, consultez l’option majuscules dans Figure 2.
  2. Également, si la CommandOptionType est SingleValue et l’identificateur d’option est spécifiée, mais aucune valeur n’apparaît, une CommandParsingException sera levée identifiant l’option a été pas identifié, car il ne correspond pas au modèle. En d’autres termes, SingleValue fournit un moyen de vérifier que la valeur est fournie, en supposant que l’identificateur d’option apparaît.
  3. Enfin, vous pouvez fournir un CommandOptionType de MultipleValue. Contrairement à plusieurs valeurs associées à une commande, toutefois, plusieurs valeurs dans le cas d’une option d’autorisent le même être spécifié plusieurs fois. Par exemple, program.exe-nom Inigo-nom Montoya.

Notez qu’aucune des options de configuration va configurer l’option n’est requise. Et, en fait, cela vaut pour un argument. Pour une erreur si une valeur n’est pas spécifiée, vous devez vérifier si la fonction HasValue signale une erreur si elle retourne false. Dans le cas d’un CommandArgument, la propriété Value retourne null si aucune valeur n’est spécifiée. Pour signaler l’erreur, envisagez d’afficher un message d’erreur suivi par le texte d’aide utilisateurs ont donc plus d’informations sur ce qu’ils faut faire pour corriger le problème.

Un autre comportement important du mécanisme d’analyse de CommandLineApplication est qu’elle respecte la casse. Et, en fait, pour l’instant aucune option de configuration simple qui vous permet d’effectuer la casse. Par conséquent, vous devrez modifier la casse des arguments réels passés dans la CommandLineApplication (via la méthode Execute, comme je vais décrire) avance pour atteindre le non-respect de la casse. (Sinon, vous pouvez essayer soumettant une requête d’extraction à github.com/aspnet/Common pour activer cette option.)

Afficher l’aide et Version

Intégrée à la CommandLineApplication est une fonction ShowHelp qui affiche le texte d’aide associé à la configuration de ligne de commande automatiquement. Par exemple, Figure 3 montre la sortie ShowHelp pour Figure 2.

Figure 3 ShowHelp afficher la sortie

Usage:  [options] [command]
Options:
  -$|-g |--greeting <greeting>  The greeting to display. 
                                The greeting supports a format string 
                                where {fullname} will be substituted 
                                with the full name.
  -u | --uppercase              Display the greeting in uppercase.
  -? | -h | --help              Show help information
Commands:
  name 
Use " [command] --help" for more information about a command.

Malheureusement, l’aide affichée n’identifie pas si une option ou de commande, en fait, facultatif. En d’autres termes, le texte d’aide suppose et affiche (via des crochets) que toutes les options et les commandes sont facultatives.

Bien que vous puissiez appeler ShowHelp explicitement, par exemple lors de la gestion d’une erreur de ligne de commande personnalisée, il est automatiquement appelé chaque fois qu’un argument correspondre au modèle HelpOption est spécifié. Et, le modèle HelpOption est spécifié via l’argument de la méthode CommandLineApplication.HelpOption.

De même, il est une méthode ShowVersion pour afficher la version de votre application. Comme ShowHelp, il est configuré via une des deux méthodes :

public CommandOption VersionOption(
  string template, string shortFormVersion, string longFormVersion = null).
public CommandOption VersionOption(
  string template, Func<string> shortFormVersionGetter,
  Func<string> longFormVersionGetter = null)

Notez que les deux méthodes requièrent les informations de version que vous souhaitez afficher pour être spécifié dans l’appel à VerisionOption.

L’analyse et lire les données de ligne de commande

Jusqu'à présent, j’ai révisé en détail comment configurer la CommandLineApplication, mais je n’ai pas encore abordé le processus jamais donc critique de déclenchement de l’analyse de ligne de commande, ou ce qui se produit immédiatement après l’appel de l’analyse.

Pour déclencher l’analyse de ligne de commande, vous devez appeler la fonction CommandLineApplication.Execute et transmettre la liste d’arguments spécifiés sur la ligne de commande. Dans Figure 1, les arguments sont spécifiés dans le paramètre args de Main afin qu’ils sont passés directement à la fonction Execute (veillez à gérer tout d’abord une casse si la casse n’est pas souhaitable). Il est la méthode Execute qui définit les données de ligne de commande associées à chaque Argument et l’Option est configurée.

Notez que CommandLineAppliction inclut un OnExecute (appelez Func < int >) fonction dans laquelle vous pouvez passer un délégué Func < int > qui s’exécutera automatiquement une fois l’analyse terminée. Dans Figure 2, la méthode OnExecute prend un délégué simple qui vérifie que la commande greet a été spécifiée avant d’appeler une fonction Greet.

Notez également que l’int retourné par le délégué à appeler est conçu comme un moyen de spécifier une valeur de retour à partir de Main. Et, en fait, la valeur est retournée à partir de l’appel correspond au retour de l’exécution. En outre, étant donné que l’analyse d’est considérée comme une opération relativement lente (je suppose que son rapport toutes les), Execute prend en charge une surcharge qui prend une Func < tâche < int >>, ce qui permet un appel asynchrone de l’analyse de ligne de commande.

Instructions : Commandes, les Arguments et Options

Les types de trois commande disponibles, il est nécessaire de revoir rapidement à utiliser.

Faire utiliser les commandes lorsque vous compilez sémantiquement identifiant une action, par exemple, importer ou de sauvegarde.

Faire Options permet d’activer les informations de configuration sur le des deux programmes en entier ou une commande spécifique.

Favor un verbe pour le nom d’une commande et un adjectif ou un nom pour le nom d’une option (tels que - couleur, - parallèle, - NomProjet).

Quel que soit le type d’argument que vous configurez, respectez les consignes suivantes :

Faire consulter la casse des noms d’identificateur argument. Il peut être très déroutant pour un utilisateur spécifie FullName - ou - fullname lorsque la recherche de la ligne de commande pour une casse différente.

Faire écrire des tests pour l’analyse de ligne de commande. Méthodes Execute et OnExecute que ce soit relativement facile à faire.

Faire utilisent des Arguments identifiant les arguments spécifiques par son nom est fastidieuse ou plusieurs valeurs sont autorisées, mais chacun d’eux à un identificateur d’option préfixant est difficile à gérer.

Envisagez en exploitant IntelliTect.AssertConsole (itl.tc/CommandLineUtils) pour rediriger l’entrée de la console et de sortie pour injecter et capturer la console de sorte qu’il peut être testé.

Il existe un inconvénient possible à l’utilisation de la CommandLineUtils Core .NET et qu’ils ne sont pas localisés et en anglais. Texte affiché comme celles qui figurent dans ShowHelp (ainsi que les messages d’exception qui en général ne sont pas localisés) sont tous en anglais. Normalement, cela peut ne pas être un problème, mais comme une ligne de commande fait partie de l’interface de l’application avec l’utilisateur, il existe probablement à des scénarios où l’uniquement anglais est inacceptable. Pour cette raison :

Envisagez écriture de fonctions personnalisées pour ShowHelp et ShowHint si la localisation est importante.

Faire vérifier CommandLineApplication.RemainingArguments lorsque la CommandLineApplication est configurée pour ne pas lever d’exceptions (throwOnUnexpectedArg = false).

Pour résumer

Au cours des trois dernières années du .NET Framework a subi certaines transitions principales :

  • Il prend désormais en charge d’inter-plateformes, notamment la prise en charge pour iOS, Android et Linux : Wow !
  • Il a migré à partir d’une approche secret, propriétaire développement à un entièrement ouvert, comme dans open source : module.
  • Il y a eu une importante refactorisation des API BCL de la bibliothèque Standard de .NET dans une plate-forme (cross) hautement modulaire qui peut être exploitée par le large éventail de types d’application, si le logiciel en tant que Service, mobile, en local, Internet des objets, bureau et bien plus encore.
  • Il a été un Renaissance de .NET, suivant l’ère Windows 8 sur lequel il a été ignoré avec très peu de stratégie ou de feuille de route de note.

Tout ce qui est à dire, si vous n’avez pas encore commencé plonger dans le nouveau .NET Core 1.0, est maintenant un moment idéal pour ce faire, vous donnant ainsi l’intervalle de temps plus long dans lequel amortir la courbe d’apprentissage. En d’autres termes, si vous devez prendre la mise à niveau vers elle à partir de versions antérieures, faites-le maintenant. Sans doute bon que vous allez mettre à niveau à un moment donné, et vous faire rapidement, plus tôt vous pouvez tirer parti de ses nouvelles fonctionnalités.


Mark Michaelis est le fondateur de IntelliTect, où il sert de son poste d’architecte en chef technique et un formateur.  Depuis près de 20 ans, il a été MVP Microsoft et directeur régional Microsoft depuis 2007. Michaelis fait plusieurs logiciels conception révision équipes Microsoft, notamment c#, Microsoft Azure, SharePoint et Visual Studio ALM. Il participe à des conférences de développeurs et a écrit de nombreux ouvrages, y compris sa plus récente, « Essential c# 6.0 (5e édition) » (itl.tc/EssentialCSharp). Contactez-le sur Facebook à facebook.com/Mark.Michaelis, sur son blog à l’adresse IntelliTect.com/Mark, sur Twitter : @markmichaelis ou par courrier électronique à mark@IntelliTect.com.

Je remercie les experts techniques IntelliTect suivants d’avoir relu cet article : Philippe Spokas et Michael Stokesbary