是否等效于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.Hereusing module C:\Path\to\manifest。唯一的要求是,它
要比

Answers:


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任务表示使用不是第一条语句。
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
Nicolas 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


似乎需要使用程序集名称(例如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指令。
Paulo Morgado

我喜欢这种外观。如果您愿意这样做,那么对我来说,这似乎是一个非常优雅的解决方案。PowerShell在编写新语法方面的灵活性使我感到非常高兴。
程序员保罗

@ProgrammerPaul如果您觉得很有趣,请尝试一下功能语言-其中一些功能可以实现try..catch,包括Haskell和IIRC Clojure。
jpaugh

@ProgrammerPaul(功能语言写的),大声笑,只是在包装F#库(通过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上失败。
乔什

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将包括一个再次解析路径的给定类型的步骤。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.