powershell에서 C #의 "using"키워드와 동일합니까?


80

C #의 .net-Framework에서 다른 개체를 사용할 때 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입니다. 유일한 요구 사항은 스크립트의 다른 문 앞에 오는 것입니다 (param 블록 포함)
Maximilian Burszley

답변:


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없지만 using namespace구문 오류가있는 PS 4.0 이하에서는 스크립트가 실행 되지 않습니다 .)


1
#Require 문은 알아두면 편리합니다. 감사합니다.
Simon Tewsi

이것은 일반 스크립트에서 작동하지만 인라인 스크립트가있는 Azure DevOps PowerShell 작업은 using이 첫 번째 문이 아니라고 말합니다.
Andrii

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 또는 사용([pscredential]::new('+',$ss)).GetNetworkCredential().Password
니콜라스 Melay

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


유형 이름 (예 : System.IO.Path) 대신 어셈블리 이름 (예 : mscorlib)을 사용해야하는 것 같습니다.
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 유형, 검색하기가 어렵습니다.
Pete

이는 using 지시문이 아니라 C # using 문과 동일합니다.
Paulo Morgado

나는 이것이 보이는 방식을 좋아한다. 당신이 그것에 헌신한다면, 이것은 나에게 매우 우아한 해결책처럼 보입니다. 새로운 구문을 만드는 PowerShell의 유연성은 저를 매우 행복하게합니다.
프로그래머 Paul

@ProgrammerPaul 재미 있다고 생각되면 기능적 언어를 사용해보십시오. 일부 언어 는 Haskell 및 IIRC Clojure를 포함 try..catch하여 라이브러리 로 구현 됩니다 .
jpaugh

@ProgrammerPaul (wrt. functional languages) lol, F # lib (FParsec을 통한 DSL 파서)를 래핑하면서 이것을 읽고 있습니다. 나는 Haskell, Clojure, Scala를 알고 / 좋아하지만 여전히 코멘트를 붙잡을 수 없습니다. 여기에 있습니다. Smalltalk와 같은 진정한 객체 지향 언어를 사용해보십시오. If / Else를 라이브러리로 구현합니다. ;-)))
Miloslav Raus

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

    }

}

Josh, 아직 유형 가속기 확장을 고려하지 않았습니다. 이것은 매우 흥미 롭습니다. 나는 그것에 대해 약간 놀아 볼 것입니다.
froh42

편리하지만주의해서 사용하십시오. 다른 사람의 컴퓨터에서 작동하지 않는 스크립트를 작성하는 것보다 더 나쁜 것은 없습니다. 그런 이유로 나는 이러한 액셀러레이터를 내 프로필에 넣지 않았습니다. 무엇이든 Add-TypeAccelerator에서 즉시 실패 할 수 있도록 스크립트 맨 위에 배치하겠습니다.
Josh

5

유형의 인스턴스를 만들어야하는 경우 긴 네임 스페이스의 이름을 문자열에 저장할 수 있습니다.

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

usingC # 의 지시문 만큼 강력 하지는 않지만 적어도 사용하기는 매우 쉽습니다.


2

귀하의 의견에 감사드립니다. Richard Berg의 기여는 제가 찾고있는 것과 가장 유사하기 때문에 답변으로 표시했습니다.

귀하의 모든 답변은 저를 가장 유망 해 보이는 트랙으로 이끌었습니다. 그의 블로그 게시물에서 Keith Dahlby는 제네릭 메서드의 유형을 쉽게 구성 할 수있는 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-type에는 주어진 유형을 다시 경로로 확인하는 단계가 포함됩니다.



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.