【问题标题】:PowerShell - Check if .NET class existsPowerShell - 检查 .NET 类是否存在
【发布时间】:2017-09-24 14:50:54
【问题描述】:

我有一个要导入 PS 会话的 DLL 文件。这将创建一个新的 .NET 类。在函数的开始,我想测试这个类是否存在,以及它是否不导入 DLL 文件。

目前我正在尝试给班级打电话。这可行,但我认为它会导致 Do {} Until () 循环出现问题,因为我必须运行脚本两次。

我的代码。请注意Do {} Until () 循环不起作用。 https://gist.github.com/TheRealNoob/f07e0d981a3e079db13d16fe00116a9a

我找到了[System.Type]::GetType() 方法,但是当我针对任何类型的字符串、有效或无效类运行它时,它什么也没做。

【问题讨论】:

标签: .net powershell types


【解决方案1】:

您可以在 powershell 中使用 -as 将字符串转换为 [system.type]

PS C:\> 'int' -as [type]

IsPublic IsSerial Name    BaseType
-------- -------- ----    --------
True     True     Int32   System.ValueType

如果找不到类型(与其他强制转换场景一样),则表达式不会返回任何内容:

PS C:\> 'notatype' -as [type]

PS C:\> 

因此,您可以通过以下方式检索特定类型(无需遍历应用程序域中加载的所有程序集的所有类型):

$type = 'notatype' -as [type]

#or

if ('int' -as [type]) { 
  'Success!' 
}

#and conveniently

$typeName = 'Microsoft.Data.Sqlite.SqliteConnection'
if (-not($typeName -as [type])) {
   #load the type
}

【讨论】:

【解决方案2】:

在 .Net 中存在一种称为 Reflexion 的东西,它允许您处理代码中的所有内容。

$type = [System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() | where {$_.Name -eq 'String'}}

我在这里查找类型String,但您可以查找您的类型或更好的程序集版本,您甚至可以查找是否存在具有正确参数的一种方法。看看C# - How to check if namespace, class or method exists in C#?


@Timmerman cmets ;他和:

[System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() | where {$_.Name -like "SQLiteConnection"}}

[System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() | where {$_.AssemblyQualifiedName -like 'Assembly Qualified Name'}}

【讨论】:

  • 我读过那篇文章。但我认为你不太明白我想要做什么。我的 DLL 文件创建(按照您的示例)[System.AppDomain]。我需要知道它是否存在。我不能只写 If ( (!( [System.AppDomain] -as [type])) ) { #do stuff } 因为这会导致终止错误。
  • 我认为 JAPBlanc,他正试图从外部加载它并明确调用它。
  • 拉纳迪普·杜塔,这是正确的。你可以用任何假课来测试我的困境。例如: If ( (!( [System.NewClass] -as [type])) ) { Add-Type MyDLL.dll }
  • 你不懂。 PowerShell 是一个带有 AppDomain 的 .NET EXE。添加类型将程序集添加到此 AppDomain。此代码只是测试您的类是否存在于当前 PowerShell 实例中。
  • JPBlanc,你是对的。您的解决方案完美运行,然后一些:) 对于所有未来的读者,我要使用的命令如下: [System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() |其中 {$_.Name -like "SQLiteConnection"}}[System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() |其中 {$_.AssemblyQualifiedName -like 'Assembly Qualified Name'}}
【解决方案3】:

这就是 -is 和 -as 的用途。您还可以使用 -is 和 try/catch 语句来检查类是否存在:

try
{
   [test.namespace] -is [type]
}
catch
{
    add-type -typedefinition test.namespace.dll
}

el2iot2 完美地描述了 -as 的使用,这将是我的首选方法。它旨在避免在类转换期间出现错误。

【讨论】:

    【解决方案4】:

    我推荐the el2iot2's approach with -as

    如果您比-as 更喜欢try-catch 方式,我建议您将我的答案中的[SomeType]::Equals($null, $null) 替换为[SomeType] -is [type],根据the Shaun Stevens's answer

    但是,如果我没有阅读 el2iot2 和 Shaun Stevens 的回答,我会使用以下内容:

    try {
        [SomeType]::Equals($null, $null) >$null
        Write-Host '"SomeType" exists'
    }
    catch {
        Write-Host '"SomeType" does not exist'
    }
    

    (说明:每个类型都应该有Equals静态方法,它允许用两个$nulls调用自己并在这种情况下返回$true;试图以这种方式引用一个不存在的类型应该抛出SystemException 的一个实例,可以被捕获。)

    它甚至可以用作单线:

    $someTypeExists = try {[SomeType]::Equals($null, $null)} catch {$false}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      • 2015-04-10
      • 2015-10-31
      • 2018-10-18
      • 1970-01-01
      相关资源
      最近更新 更多