2008-12-19 4 views
15

J'ai déjà utilisé le setargv.obj linking for Expanding Wildcard Arguments pour un certain nombre d'applications C et C++, mais je ne trouve aucune mention similaire pour les applications .net.Existe-t-il une option d'extension générique pour les applications .net?

Existe-t-il un standard pour que les paramètres de ligne de commande de votre application soient automatiquement développés? (c'est-à-dire développer * .doc d'une entrée dans le paramètre args vers tout ce qui correspond à ce caractère générique).

P.S. J'ai piraté quelque chose avec Directory.GetFiles() pour mon petit projet actuel, mais il ne couvre pas (encore) les jokers avec des chemins, et ce serait bien de le faire sans code personnalisé.

Mise à jour: Voici mon hack grossier, par exemple. Il doit diviser les paramètres pour le chemin et le nom pour le GetFiles, mais c'est l'idée générale. Lier setargv.obj dans une application C ou C++ ferait essentiellement toute l'expansion générique, laissant l'utilisateur à seulement parcourir le tableau argv.


static void Main(string[] args) 
{ 
    foreach (String argString in args) 
    { 
     // Split into path and wildcard 
     int lastBackslashPos = argString.LastIndexOf('\\') + 1; 
     path = argString.Substring(0, lastBackslashPos); 
     filenameOnly = argString.Substring(lastBackslashPos, 
            argString.Length - lastBackslashPos); 

     String[] fileList = System.IO.Directory.GetFiles(path, filenameOnly); 
     foreach (String fileName in fileList) 
     { 
      //do things for each file 
     } 
    } 
} 
+0

Par ce que tu veux dire non seulement les noms de fichiers génériques, mais les noms de dossiers génériques aussi? Par exemple quelque chose comme: C: \ Windows \ System32 \ * \ Test * .doc? – BenAlabaster

+0

Le paramètre "original" setargv.obj ne fonctionnerait qu'avec des caractères génériques dans le nom de fichier, c'est donc ce que je recherche. – crashmstr

+0

qui ne ressemble pas à un hack du tout, il semble assez simple. –

Répondre

1

Votre code ressemble exactement à la façon dont vous êtes censé le faire.

+0

True, mais en C/C++ il existe un mécanisme dans le compilateur pour faire le travail pour vous. Au moins, il est beaucoup plus facile de faire cela. – crashmstr

4

Je ne sais pas exactement ce que vous êtes après ... mais si je reçois où vous allez avec les Directory.GetFiles() « hack » vous avez mentionné, alors quelque chose comme cela pourrait fonctionner:

var Dirs = Directory.GetDirectories(@"C:\Windows", "sys*", 
SearchOption.TopDirectoryOnly).ToList(); 
var Files = new List<String>(); 
Dirs.ForEach(dirName => Files.AddRange(Directory.GetFiles(dirName, "*.sys", SearchOption.AllDirectories))); 

l'option générique sur les GetDirectories appel vous permettra de saisir tous les répertoires contenus dans le dossier Windows [directement] qui correspondent au modèle « sys * ».

Vous pouvez ensuite itérer sur ces dossiers en saisissant tous les fichiers correspondant au modèle "* .sys".

Est-ce le genre de choses que vous cherchez? Pour développer automatiquement les args, vous auriez à extraire les caractères génériques dans une sorte de manière significative et les appliquer à ce modèle ...

Par exemple:

RunMyApp « C: \ Windows \ * Sys \ * .sys "

Vous tirez la chaîne C: \ Windows - probablement avec une expression régulière, recherchez le répertoire de niveau le plus bas qui ne contient pas de caractère générique et l'appliquer à la méthode GetDirectories, en attachant la chaîne générique comme paramètre de recherche.

Ensuite, si votre fin de chaîne (dans ce cas * .sys) comme motif de recherche pour Directory.GetFiles.

Si vous voulez obtenir plus compliqué et faire quelque chose comme:

C:\Windows\*\Sys*\*.sys 

Vous utilisez les SearchOptions pour définir ce comportement:

Directory.GetDirectories(@"C:\Windows", "sys*", SearchOptions.AllDirectories) 

Ce saisirait tous les répertoires qui correspondent le sys * joker dans le répertoire Windows et tous les répertoires en dessous. Si vous vouliez être beaucoup plus compliqué que ça, je ne sais pas comment vous feriez cela ... Par exemple, disons que vous vouliez des dossiers qui sont contenus par des dossiers directement dans le répertoire Windows - je n'ai pas idée comment vous allez quelque chose comme ça, j'ai peur ...Je n'imagine pas exporter la structure arborescente entière vers XML et l'utilisation de XPath pour le faire serait si efficace - le XPath serait fabuleusement simple pour analyser en utilisant des caractères génériques - mais la conversion en XML ne serait pas aussi efficace ...

+0

Merci pour les exemples. La méthode C/C++ ne ferait que développer les noms de fichiers, autant que je m'en souvienne. Ma question principale est s'il y a un moyen de le faire comme la méthode C/C++ sans écrire votre propre code (comme je l'ai fait). Bien que .net le rende plus facile qu'il aurait été en C/C++! – crashmstr

+0

@crashmstr: Je ne dirai pas qu'il n'y en a certainement pas - il y a trop de coins cachés du framework .NET. Pour autant que je sache, il n'y a pas de façon native de le faire automatiquement. – BenAlabaster

+0

C'est la bonne façon de faire cela. –

9

Ici nous mon hack rugueux. J'aimerais qu'il soit récursif. Et ayant expérimenté la faille des jokers Windows, je pourrais décider d'utiliser des expressions régulières plutôt que de laisser GetFiles() le faire pour moi.

using System.IO; 

public static string[] ExpandFilePaths(string[] args) 
{ 
    var fileList = new List<string>(); 

    foreach (var arg in args) 
    { 
     var substitutedArg = System.Environment.ExpandEnvironmentVariables(arg); 

     var dirPart = Path.GetDirectoryName(substitutedArg); 
     if (dirPart.Length == 0) 
      dirPart = "."; 

     var filePart = Path.GetFileName(substitutedArg); 

     foreach (var filepath in Directory.GetFiles(dirPart, filePart)) 
      fileList.Add(filepath); 
    } 

    return fileList.ToArray(); 
} 
3

voir le code source de la classe Microsoft.Build.Shared.FileMatcher démontées dans Microsoft.Build.dll vous pouvez obtenir une idée de la mise en œuvre de GetFiles méthode.

en tant que client, vous pouvez utiliser la méthode comme suit

var filelist = FileMatcher.GetFiles(@"c:\alaki",@"c:\alaki\**\bin\*.dll"); 
+1

Bonne trouvaille ... si seulement cette classe n'était pas 'internal'. –

Questions connexes