【问题标题】:PowerShell Add-Type : Cannot add type. already existPowerShell Add-Type:无法添加类型。已经存在
【发布时间】:2023-03-27 12:44:01
【问题描述】:

我正在使用 PowerShell 脚本直接在脚本中运行 C# 代码。我已经多次遇到特定错误的错误。如果我对 PowerShell ISE 中的 C# 代码进行任何更改并尝试再次运行它,我会收到以下错误。

Add-Type : Cannot add type. The type name 'AlertsOnOff10.onOff' already exists.
At C:\Users\testUser\Desktop\test.ps1:80 char:1
+ Add-Type -TypeDefinition $Source -ReferencedAssemblies $Assem
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (AlertsOnOff10.onOff:String) [Add-Type], Exception
    + FullyQualifiedErrorId : TYPE_ALREADY_EXISTS,Microsoft.PowerShell.Commands.AddTypeCommand

我解决此错误的方法是更改​​命名空间和调用 C# 方法 [AlertsOnOff10.onOff]::Main("off") 的命令。我有什么方法可以防止此错误发生而无需更改命名空间和方法调用?

【问题讨论】:

  • 我建议使用 VS 和 ex。用于开发和调试程序集的控制台应用程序。 PowerShell 可以使用托管代码,但它并非旨在用作 VS 的替代品(尽管它是一个很好的补充)
  • 这有帮助吗?当然,如果您的类型定义发生更改,这将无济于事,但如果您不打算重新定义类型,这可能是一种解决方法:stackoverflow.com/questions/16552801/…

标签: c# powershell runtime-error


【解决方案1】:

对于那些想要避免错误或避免加载已经加载的类型的人,请使用以下检查:

if ("TrustAllCertsPolicy" -as [type]) {} else {
        Add-Type "using System.Net;using System.Security.Cryptography.X509Certificates;public class TrustAllCertsPolicy : ICertificatePolicy {public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {return true;}}"
        [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}

我发布此内容是因为如果您对 C# 代码进行肤浅(例如格式化)更改,则会收到错误 OP。

【讨论】:

    【解决方案2】:

    据我所知,一旦添加了类型,就无法从 PowerShell 会话中删除它。

    我建议的(烦人的)解决方法是在一个 ISE 会话中编写您的代码,然后在一个完全不同的会话中执行它(单独的控制台窗口或单独的 ISE,如果您希望能够进行调试)。

    这仅在您更改 $Source 时才重要(积极开发类型定义)。如果那不是正在更改的部分,则忽略错误,如果是终止错误,请使用 -ErrorAction 进行更改。

    【讨论】:

    • 据我了解,如果我关闭 ISE 会话,我不会遇到此错误。对吗?
    • 在运行 ISE 时更改不会丢失。因此,变量$wazzup 将在运行一段特定的代码或脚本后持续存在。
    • 您可以使用Remove-Variable 摆脱一个defiend 变量,并且您可以清除其他运行时对象。但这不适用于类型。
    • 这个问题不是 PowerShell 限制,而是 .NET 限制。加载程序集后,不支持删除程序集的方法。
    【解决方案3】:

    您可以将其作为作业执行:

    $cmd = {    
    
        $code = @'
            using System;
    
            namespace MyCode
            {
                public class Helper
                {
                    public static string FormatText(string message)
                    {
                        return "Version 1: " + message;
                    }
                }
            }
    '@
    
        Add-Type -TypeDefinition $code -PassThru | Out-Null
    
        Write-Output $( [MyCode.Helper]::FormatText("It Works!") )
    }
    
    $j = Start-Job -ScriptBlock $cmd
    
    do 
    {
        Receive-Job -Job $j
    
    } while ( $j.State -eq "Running" )
    

    【讨论】:

      【解决方案4】:

      Adam Furmanek 的blog 有最简单和最好的解决方法。这在下面是这样的。如果你想看看如何为此传递参数,你可以看到https://samtran.me/2020/02/09/execute-c-code-with-parameters-using-powershell/

      $id = get-random
      $code = @"
      using System;
      namespace HelloWorld
      {
          public class Program$id
          {
              public static void Main(){
                  Console.WriteLine("Hello world again!");
              }
          }
      }
      "@
      
      Add-Type -TypeDefinition $code -Language CSharp 
      Invoke-Expression "[HelloWorld.Program$id]::Main()"
      

      【讨论】:

        猜你喜欢
        • 2017-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-26
        相关资源
        最近更新 更多