Еквівалентно ключовому слову C # у використанні в PowerShell?


80

Коли я використовую інший об'єкт у .net-Framework в C #, я можу заощадити багато набору тексту, використовуючи директиву using.

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

...


  var blurb = new Thingamabob();

...

То чи є в Powershell спосіб зробити щось подібне? Я отримую доступ до багатьох об'єктів .net і не радий набирати текст

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

весь час.


1
Я знаю, що це старе питання, але PowerShell 5 представив usingзаяву. Ви можете використовувати це для просторів імен .net або модулів (що є одним із єдиних способів імпорту користувацьких класів). Синтаксис - це using namespace Name.Space.Hereабо using module C:\Path\to\manifest. Єдина вимога полягає в тому, щоб воно
— стояло

Відповіді:


43

PowerShell 5.0 (входить до складу WMF5 або Windows 10 і новіших версій) додає using namespaceконструкцію до мови. Ви можете використовувати його у своєму сценарії так:

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

( #RequireВираз у першому рядку використовувати не потрібно using namespace, але це заважатиме сценарію працювати в PS 4.0 і нижче, де using namespaceє синтаксична помилка.)


1
Це твердження #Require - це дуже зручно знати, дякую.
— Саймон Тевсі,

Це працює в загальних сценаріях, але завдання Azure DevOps PowerShell із вбудованим сценарієм говорить, що використання - не перший вираз
— Андрій

57

Насправді нічого такого на рівні простору імен немає. Я часто призначаю змінні часто використовувані типи, а потім створюю їх за допомогою екземплярів:

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

Можливо, не варто, якщо тип не буде використовуватися неодноразово, але я вважаю, що це найкраще, що ви можете зробити.


Мені іноді потрібно перетворити SecureStrings назад у звичайний текст. Корисно наступне: $ns = [System.Runtime.InteropServices.Marshal]тоді можна $ns::PtrToStringAuto($ns::SecureStringToBSTR($ss)).
— petrsnd

1
Примітка для тих, хто шукає найвищу оцінку відповіді: PowerShell 5.0 це виправляє.
— Dave Markle

@petrsnd or use([pscredential]::new('+',$ss)).GetNetworkCredential().Password
— Ніколас

12

Ознайомтесь із цим дописом у блозі кілька років тому: http://blogs.msdn.com/richardb/archive/2007/02/21/add-types-ps1-poor-man-s-using-for-powershell.aspx

Ось add-types.ps1, уривок із цієї статті:

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
        }
    }
}

І, щоб використовувати його:

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

В основному те, що я роблю, це сканувати збірку для нетривіальних типів, а потім написати «конструктор», який використовує Add-Member, додаючи їх (структурованим способом) до об’єктів, які мене цікавлять.

Дивіться також цей наступний пост: http://richardberg.net/blog/?p=38


Здається, що потрібно використовувати ім'я збірки (наприклад, mscorlib) замість імені типу (наприклад, System.IO.Path).
— Micha Wiedenmann

Якщо у вас немає об’єкта для передачі його функції, ви можете створити його за допомогою New-Object PSObject.
— Micha Wiedenmann

7

це просто жарт, жарт ...

$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

Хтось може пояснити подвійне `` 1 у типі, мені важко шукати.
— Піт

Це було б еквівалентно оператору C # using, а не директиві using.
— Паулу Моргадо

Мені подобається, як це виглядає. Якби ви взяли на себе зобов'язання, це здається мені досить елегантним рішенням. Гнучкість PowerShell при розробці нового синтаксису мене дуже радує.
— Програміст Пол

@ProgrammerPaul Якщо вам це забавно, спробуйте функціональну мову - деякі з них реалізовані try..catchяк бібліотека , включаючи Haskell та IIRC Clojure.
— jpaugh

@ProgrammerPaul (wrt. Функціональні мови) ха-ха, просто читаючи це, обертаючи F # lib (DSL Parser через FParsec). Я знаю / люблю Haskell, Clojure, Scala, і досі не можу вмістити коментар. Ось воно: Може, спробувати якусь справді об’єктно-орієнтовану мову, як Smalltalk - він реалізує If / Else як бібліотеку ;-)))
— Мілослав Раус,

5

Ось деякий код, який працює в PowerShell 2.0 для додавання псевдонімів типу. Але проблема в тому, що він не застосовується. З деякою додатковою роботою ви можете «деімпортувати» простори імен, але це повинно вас добре розпочати.

##############################################################################
#.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)
            }
        }

    }

}

Джош, дякую, я ще не дивився на розширення прискорювачів типу. Це дуже цікаво, я думаю, я з ним трохи пограюся.
— froh42

Це зручно, але використовуйте його з обережністю. Нічого гіршого, ніж написання сценарію, який не працює на чужій машині. З цієї причини я ніколи не розміщував ці прискорювачі у своєму профілі. Якщо що, я розміщу їх у верхній частині сценарію таким чином, що він відразу ж провалиться в Add-TypeAccelerator.
— Джош,

5

Якщо вам просто потрібно створити екземпляр вашого типу, ви можете зберегти ім'я довгого простору імен у рядку:

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

Він не такий потужний, як usingдиректива на C #, але принаймні дуже простий у використанні.


2

Дякуємо усім за ваш внесок. Я зазначив внесок Річарда Берга як відповідь, оскільки він найбільше нагадує те, що я шукаю.

Усі ваші відповіді вивели мене на шлях, який здається найбільш перспективним: У своєму дописі в блозі Кіт Дальбі пропонує командлет Get-Type, який дозволяє легко використовувати типи типів для загальних методів.

Я думаю, що немає жодної причини проти продовжувати це, а також шукати за заздалегідь визначеним шляхом збірок для типу.

Застереження: Я ще не будував цього - поки ...

Ось як можна ним скористатися:

$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()

Це призведе до гарного загального списку Thingamabob. Звичайно, я б обгорнув все, що є без визначення шляху, просто черговою функцією корисності. Розширений тип get включав би крок для вирішення будь-якого заданого типу проти шляху.



-2

Я розумію, що це стара публікація, але я шукав те саме і натрапив на це: http://weblogs.asp.net/adweigert/powershell-adding-the-using-statement

Редагувати: Я гадаю, мені слід вказати, що це дозволяє використовувати знайомий синтаксис ...

using ($x = $y) { ... }

1
Це було б еквівалентно оператору C # using, а не директиві using.
— Паулу Моргадо,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.