如何将 add-type 与 -path 和 -language csharpversion3 一起使用?

发布于 2024-10-27 22:20:33 字数 207 浏览 1 评论 0原文

我一直在 Powershell 中使用 add-type 来动态编译我想要使用的一些 C# 类。效果很好,只是它只是 2.0。

我刚刚发现了 -language csharpversion3 选项,但它不适用于 -path。我该如何解决这个问题?

[编辑:删除了有关 ReadAllText 的部分 - 我错了。]

I've been using add-type in Powershell to dynamically compile in some C# classes I want to use. Works great except it's 2.0 only.

I just discovered the -language csharpversion3 option, but it does not work with -path. How can I work around this?

[Edit: removed bit about ReadAllText - I was mistaken.]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

人生百味 2024-11-03 22:20:33

解决方法如下:将文件作为文本读取。

$script = [io.file]::readalltext($scriptpath)
add-type $script -lang csharpversion3

我不妨粘贴其余部分,并以某种方式使这个答案有用。我有一个调试标志,可以让我生成 DLL,这样我就可以更轻松地使用调试器,使用 Reflector 检查它等。

$cp = new-object codedom.compiler.compilerparameters
$cp.ReferencedAssemblies.Add('system.dll') > $null
$cp.ReferencedAssemblies.Add('system.core.dll') > $null

# optionally turn on debugging support
if ($debugscript)
{
    # delete old unused crap while we're at it
    dir "$($env:temp)\-*.dll" |%{
        del $_ -ea silentlycontinue
        if ($?) { del $_.fullname.replace('.dll', '.pdb') -ea silentlycontinue }
    }

    $cp.TreatWarningsAsErrors = $true
    $cp.IncludeDebugInformation = $true
    $cp.OutputAssembly = $env:temp + '\-' + [diagnostics.process]::getcurrentprocess().id + '.dll'
}

$script = [io.file]::readalltext($scriptpath)
add-type $script -lang csharpversion3 -compilerparam $cp

这增加了一些如果 $debugscript 设置为 true,则附加功能:

  • 编译时将警告视为错误
  • 生成 PDB
  • 使用与进程 ID 相关联的特定 DLL/PDB 名称(在临时文件夹中),以便每个会话都有自己的名称。这对于迭代 .cs 的更改很有用。
  • 删除旧的 dll 和 pdb,在迭代时也很好。

Here's the workaround: read the file as text.

$script = [io.file]::readalltext($scriptpath)
add-type $script -lang csharpversion3

I might as well paste in the rest and make this answer useful in some way.. I have a debug flag that lets me generate the DLL so I can more easily break in with the debugger, inspect it with Reflector, etc.

$cp = new-object codedom.compiler.compilerparameters
$cp.ReferencedAssemblies.Add('system.dll') > $null
$cp.ReferencedAssemblies.Add('system.core.dll') > $null

# optionally turn on debugging support
if ($debugscript)
{
    # delete old unused crap while we're at it
    dir "$($env:temp)\-*.dll" |%{
        del $_ -ea silentlycontinue
        if ($?) { del $_.fullname.replace('.dll', '.pdb') -ea silentlycontinue }
    }

    $cp.TreatWarningsAsErrors = $true
    $cp.IncludeDebugInformation = $true
    $cp.OutputAssembly = $env:temp + '\-' + [diagnostics.process]::getcurrentprocess().id + '.dll'
}

$script = [io.file]::readalltext($scriptpath)
add-type $script -lang csharpversion3 -compilerparam $cp

This adds some additional functionality if $debugscript is set to true:

  • Compile with warnings as errors
  • Generate a PDB
  • Use a specific DLL/PDB name (in the temp folder) that is tied to the process ID so each session gets its own. This is good for iterating on changes to the .cs.
  • Deletes the old dll's and pdb's, also good when iterating.
北斗星光 2024-11-03 22:20:33

我不知道这是否正是您所需要的,但您可以在 powershell 中启用 .NET 4 支持。请记住,默认情况下它使用 .NET 2。为此,您需要在 $PSHome 中添加一个名为 powershell.exe.config 的 XML 和以下内容:

<?xml version="1.0"?>
<configuration>
        <startup useLegacyV2RuntimeActivationPolicy="true">
                <supportedRuntime version="v4.0.30319"/>
                <supportedRuntime version="v2.0.50727"/>
        </startup>
</configuration>

之后,任何针对更大 .net 版本的代码都可以工作,例如看看这个:

Slytherin>> gc new.cs
using System.IO;

public static class testeo
{
        public static string joinP(string[] arr)
        {
                return Path.Combine(arr);
        }
}
Slytherin>> $arr = "uno", "dos", "tres", "cuatro", "cinco"
Slytherin>> Add-Type -Path .\new.cs
Slytherin>> [testeo]::joinP($arr)
uno\dos\tres\cuatro\cinco

该方法使用 Path.Combine 和 .NET4 中定义的 N 个参数。在 .NET2 中,Combine 最多只能处理两个参数。我测试了使用匿名委托的其他示例,这是 C#3 的特征之一:

Slytherin>> $sharp = [IO.file]::readalltext((resolve-path new.cs))
Slytherin>> add-type  -typedef $sharp -Language CsharpVersion3
Slytherin>> gc .\new.cs
using System.IO;
using System;
using System.Linq;

namespace grantest
{

public static class testeo
{
        public static void joinP(string[] arr)
        {
                arr.ToList<string>().ForEach(x=>Console.WriteLine(x));

        }
}
}
Slytherin>> [grantest.testeo]::joinP($arr)
uno
dos
tres
cuatro
cinco
Slytherin>>

最后一个示例,如果您尝试下一个代码,它将不起作用,

Slytherin>> $sharp = [IO.file]::readalltext((resolve-path new.cs))
Slytherin>> $sharp
using System.IO;
using System;
using System.Linq;

namespace grantest
{

public static class testeo4
{
        public static string joinP(string[] arr)
        {
                arr.ToList<string>().ForEach(x=>Console.WriteLine(x));
                return Path.Combine(arr);
        }
}
}
Slytherin>> Add-Type -TypeDefinition $sharp
Add-Type : c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(3) : The type or namesp
ace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly
reference?)
c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(2) : using System;
c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(3) : >>> using System.Linq;
c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(4) :
At line:1 char:9
+ Add-Type <<<<  -TypeDefinition $sharp
    + CategoryInfo          : InvalidData: (c:\Users\voodoo...bly reference?):Compile
   rError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddType
   Command

其他尝试指定语言参数

Slytherin>> add-type -TypeDefinition $sharp -Language CSharpVersion3
Add-Type : c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(13) : No overload for m
ethod 'Combine' takes '1' arguments
c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(12) :         arr.ToList<string>()
.ForEach(x=>Console.WriteLine(x));
c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(13) : >>>         return Path.Comb
ine(arr);
c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(14) :     }
At line:1 char:9
+ add-type <<<<  -TypeDefinition $sharp -Language CSharpVersion3
    + CategoryInfo          : InvalidData: (c:\Users\voodoo...s '1' arguments:Compile
   rError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddType
   Command

发生这种情况是因为使用 . net4 ,显然如果你说该语言是版本 3,则自动使用 .net 3 库。为了完成这项工作,您需要添加 System.Core 作为引用的程序集,并忘记语言参数(可能值的枚举没有 Csharpversion4),因此它将使用 4 版本,因为我们之前启用了它。

Slytherin>> Add-Type -TypeDefinition $sharp -ReferencedAssemblies System.core
Slytherin>> [grantest.testeo4]::joinP($arr)
uno
dos
tres
cuatro
cinco
uno\dos\tres\cuatro\cinco

祝你好运,编码愉快。

I don't know if it exactly what you need, but you can enable .NET 4 support in powershell. Remember that by default it use .NET 2. To do this you need to add in $PSHome an XML with this name powershell.exe.config and this content:

<?xml version="1.0"?>
<configuration>
        <startup useLegacyV2RuntimeActivationPolicy="true">
                <supportedRuntime version="v4.0.30319"/>
                <supportedRuntime version="v2.0.50727"/>
        </startup>
</configuration>

After that any code targeted to a bigger .net version will work, for example look this:

Slytherin>> gc new.cs
using System.IO;

public static class testeo
{
        public static string joinP(string[] arr)
        {
                return Path.Combine(arr);
        }
}
Slytherin>> $arr = "uno", "dos", "tres", "cuatro", "cinco"
Slytherin>> Add-Type -Path .\new.cs
Slytherin>> [testeo]::joinP($arr)
uno\dos\tres\cuatro\cinco

That method use Path.Combine with N arguments that is defined in .NET4. In .NET2 Combine can only handle up to two arguments. I test other example that use anonymous delegates, one of the characteristics of C#3:

Slytherin>> $sharp = [IO.file]::readalltext((resolve-path new.cs))
Slytherin>> add-type  -typedef $sharp -Language CsharpVersion3
Slytherin>> gc .\new.cs
using System.IO;
using System;
using System.Linq;

namespace grantest
{

public static class testeo
{
        public static void joinP(string[] arr)
        {
                arr.ToList<string>().ForEach(x=>Console.WriteLine(x));

        }
}
}
Slytherin>> [grantest.testeo]::joinP($arr)
uno
dos
tres
cuatro
cinco
Slytherin>>

One last example if you try the next code it doesn't going to work

Slytherin>> $sharp = [IO.file]::readalltext((resolve-path new.cs))
Slytherin>> $sharp
using System.IO;
using System;
using System.Linq;

namespace grantest
{

public static class testeo4
{
        public static string joinP(string[] arr)
        {
                arr.ToList<string>().ForEach(x=>Console.WriteLine(x));
                return Path.Combine(arr);
        }
}
}
Slytherin>> Add-Type -TypeDefinition $sharp
Add-Type : c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(3) : The type or namesp
ace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly
reference?)
c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(2) : using System;
c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(3) : >>> using System.Linq;
c:\Users\voodoomsr\AppData\Local\Temp\5ikkmpfn.0.cs(4) :
At line:1 char:9
+ Add-Type <<<<  -TypeDefinition $sharp
    + CategoryInfo          : InvalidData: (c:\Users\voodoo...bly reference?):Compile
   rError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddType
   Command

other try specifying the language parameter

Slytherin>> add-type -TypeDefinition $sharp -Language CSharpVersion3
Add-Type : c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(13) : No overload for m
ethod 'Combine' takes '1' arguments
c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(12) :         arr.ToList<string>()
.ForEach(x=>Console.WriteLine(x));
c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(13) : >>>         return Path.Comb
ine(arr);
c:\Users\voodoomsr\AppData\Local\Temp\v3r5whoc.0.cs(14) :     }
At line:1 char:9
+ add-type <<<<  -TypeDefinition $sharp -Language CSharpVersion3
    + CategoryInfo          : InvalidData: (c:\Users\voodoo...s '1' arguments:Compile
   rError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddType
   Command

This is happen because where using a method of .net4 and apparently if you say that the language is version 3 automatically use .net 3 libraries . In order to make this work you need to add System.Core as referenced assembly and forget about the language parameter(the enumeration of possible values doesn't have Csharpversion4) so its going to use the 4 version, because we enable it before.

Slytherin>> Add-Type -TypeDefinition $sharp -ReferencedAssemblies System.core
Slytherin>> [grantest.testeo4]::joinP($arr)
uno
dos
tres
cuatro
cinco
uno\dos\tres\cuatro\cinco

Good luck, and happy coding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文