2009-06-26 4 views
63

Lorsque j'utilise un autre objet dans le .net-Framework en C#, je peux économiser beaucoup de frappe en utilisant la directive using.Equivalent au mot-clé "using" de C# dans PowerShell?

using FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It; 

... 


    var blurb = new Thingamabob(); 

... 

Y a-t-il un moyen dans Powershell de faire quelque chose de similaire? J'accède à beaucoup d'objets .net et je ne suis pas heureux d'avoir à taper

$blurb = new-object FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob; 

tout le temps.

Répondre

11

Vérifiez ce post de blog il y a quelques années: http://blogs.msdn.com/richardb/archive/2007/02/21/add-types-ps1-poor-man-s-using-for-powershell.aspx

Voici add-types.ps1, extrait de cet article:

param(
    [string] $assemblyName = $(throw 'assemblyName is required'), 
    [object] $object 
) 

process { 
    if ($_) { 
     $object = $_ 
    } 

    if (! $object) { 
     throw 'must pass an -object parameter or pipe one in' 
    } 

    # load the required dll 
    $assembly = [System.Reflection.Assembly]::LoadWithPartialName($assemblyName) 

    # add each type as a member property 
    $assembly.GetTypes() | 
    where {$_.ispublic -and !$_.IsSubclassOf([Exception]) -and $_.name -notmatch "event"} | 
    foreach { 
     # avoid error messages in case it already exists 
     if (! ($object | get-member $_.name)) { 
      add-member noteproperty $_.name $_ -inputobject $object 
     } 
    } 
} 

Et, pour l'utiliser:

RICBERG470> $tfs | add-types "Microsoft.TeamFoundation.VersionControl.Client" 
RICBERG470> $itemSpec = new-object $tfs.itemspec("$/foo", $tfs.RecursionType::none) 

Fondamentalement ce que je fais est d'explorer l'assemblée pour les types non triviaux, puis écris un "con structor "qui utilise Add-Member les ajoute (de manière structurée) aux objets qui m'intéressent.

Voir aussi ce poste de suivi: http://richardberg.net/blog/?p=38

+0

Il semble que l'on doive utiliser le nom de l'assembly (par exemple mscorlib) au lieu d'un nom de type (par exemple System.IO.Path). –

+0

Si vous n'avez pas d'objet autour pour le transmettre à la fonction, vous pouvez en créer un en utilisant 'New-Object PSObject'. –

53

Il n'y a vraiment rien au niveau de l'espace de noms comme ça. Je cède souvent les types couramment utilisés pour les variables et les instancier:

$thingtype = [FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob]; 
$blurb = New-Object $thingtype.FullName 

Probablement pas la peine si le type ne sera pas utilisé à plusieurs reprises, mais je crois qu'il est le meilleur que vous pouvez faire.

+0

J'ai parfois besoin de convertir SecureStrings en texte brut. Ce qui suit est utile: '$ ns = [System.Runtime.InteropServices.Marshal]' alors vous pouvez '$ ns :: PtrToStringAuto ($ ns :: SecureStringToBSTR ($ ss))'. – petrsnd

+0

Note à ceux qui recherchent la meilleure réponse: PowerShell 5.0 corrige cela. –

6

c'est juste une blague, blague ...

$fullnames = New-Object ([System.Collections.Generic.List``1].MakeGenericType([String])); 

function using ($name) { 
foreach ($type in [Reflection.Assembly]::LoadWithPartialName($name).GetTypes()) 
    { 
     $fullnames.Add($type.fullname); 
    } 
} 

function new ($name) { 
    $fullname = $fullnames -like "*.$name"; 
    return , (New-Object $fullname[0]); 
} 

using System.Windows.Forms 
using FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It 
$a = new button 
$b = new Thingamabob 
+0

Quelqu'un peut-il s'il vous plaît expliquer le double '' 1 dans le type, je trouve difficile de rechercher. – Pete

+0

Cela équivaudrait à l'instruction C# using, pas à la directive using. –

+0

J'aime la façon dont cela ressemble. Si vous deviez vous engager, cela me semble une solution assez élégante. La flexibilité de PowerShell dans l'élaboration d'une nouvelle syntaxe me rend très heureux. –

2

Merci à tous pour vos commentaires. J'ai marqué la contribution de Richard Berg comme une réponse, parce qu'elle ressemble le plus à ce que je cherche. Toutes vos réponses m'ont amené sur la piste qui me semble la plus prometteuse: En his blog post Keith Dahlby propose un commandlet Get-Type qui permet la construction facile de types pour les méthodes génériques.

Je pense qu'il n'y a aucune raison de ne pas l'exiter aussi de chercher dans un chemin prédéfini d'assemblages pour un type.

Disclaimer: Je n'ai pas construit que - encore ...

Voici comment on pourrait l'utiliser:

$path = (System.Collections.Generic, FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It) 

$type = get-type -Path $path List Thingamabob 
$obj = new-object $type 
$obj.GetType() 

Cela se traduirait par une belle liste générique de Thingamabob. Bien sûr, je terminerais sans la définition du chemin dans une autre fonction utilitaire. Le get-type étendu devrait inclure une étape pour résoudre tout type donné contre le chemin.

5

Voici un code qui fonctionne dans PowerShell 2.0 pour ajouter des alias de type. Mais le problème est que ce n'est pas limité. Avec un peu de travail supplémentaire, vous pouvez "désimporter" les espaces de noms, mais cela devrait vous permettre de bien démarrer.

############################################################################## 
#.SYNOPSIS 
# Add a type accelerator to the current session. 
# 
#.DESCRIPTION 
# The Add-TypeAccelerator function allows you to add a simple type accelerator 
# (like [regex]) for a longer type (like [System.Text.RegularExpressions.Regex]). 
# 
#.PARAMETER Name 
# The short form accelerator should be just the name you want to use (without 
# square brackets). 
# 
#.PARAMETER Type 
# The type you want the accelerator to accelerate. 
# 
#.PARAMETER Force 
# Overwrites any existing type alias. 
# 
#.EXAMPLE 
# Add-TypeAccelerator List "System.Collections.Generic.List``1" 
# $MyList = New-Object List[String] 
############################################################################## 
function Add-TypeAccelerator { 

    [CmdletBinding()] 
    param(

     [Parameter(Position=1,Mandatory=$true,ValueFromPipelineByPropertyName=$true)] 
     [String[]]$Name, 

     [Parameter(Position=2,Mandatory=$true,ValueFromPipeline=$true)] 
     [Type]$Type, 

     [Parameter()] 
     [Switch]$Force 

    ) 

    process { 

     $TypeAccelerators = [Type]::GetType('System.Management.Automation.TypeAccelerators') 

     foreach ($a in $Name) { 
      if ($TypeAccelerators::Get.ContainsKey($a)) { 
       if ($Force) { 
        $TypeAccelerators::Remove($a) | Out-Null 
        $TypeAccelerators::Add($a,$Type) 
       } 
       elseif ($Type -ne $TypeAccelerators::Get[$a]) { 
        Write-Error "$a is already mapped to $($TypeAccelerators::Get[$a])" 
       } 
      } 
      else { 
       $TypeAccelerators::Add($a, $Type) 
      } 
     } 

    } 

} 
+0

Josh, merci, je n'avais pas encore cherché à étendre les accélérateurs de type. C'est très intéressant, je pense que je vais jouer un peu avec ça. – froh42

+0

C'est pratique, mais utilisez-le avec prudence. Rien de pire que d'écrire un script qui ne fonctionne pas sur la machine de quelqu'un d'autre. Pour cette raison, je n'ai jamais mis ces accélérateurs dans mon profil. Si quoi que ce soit, je vais les mettre en haut d'un script de cette façon, il va échouer à l'Add-TypeAccelerator tout de suite. – Josh

4

Si vous avez juste besoin de créer une instance de votre type, vous pouvez enregistrer le nom de long espace de noms dans une chaîne:

$st = "System.Text" 
$sb = New-Object "$st.StringBuilder" 

Ce n'est pas aussi puissant que la directive using en C#, mais au moins c'est très facile à utiliser.

24

PowerShell 5.0 (inclus dans WMF5 ou Windows 10 et plus), ajoute la using namespace construire à la langue. Vous pouvez l'utiliser dans votre script comme ceci:

#Require -Version 5.0 
using namespace FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It 
$blurb = [Thingamabob]::new() 

(La déclaration #Require sur la première ligne n'est pas nécessaire d'utiliser using namespace, mais il empêchera le script de fonctionner en PS 4.0 et au-dessous où using namespace est une syntaxe erreur.)

0
#Requires -Version 5 
using namespace System.Management.Automation.Host 
#using module