我一直在使用Powershell中的add-type来动态编译我想要使用的一些C#类。效果很好,除了它只有2.0。
我刚刚发现-language csharpversion3
选项,但它不适用于-path
。我该如何解决这个问题?
[编辑:删除了有关ReadAllText的内容 - 我错了。]
答案 0 :(得分:4)
我不知道它是否正是您需要的,但您可以在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
该方法使用带有N个参数的Path.Combine,这些参数在.NET4中定义。在.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版本,因为我们之前启用它。 / p>
Slytherin>> Add-Type -TypeDefinition $sharp -ReferencedAssemblies System.core
Slytherin>> [grantest.testeo4]::joinP($arr)
uno
dos
tres
cuatro
cinco
uno\dos\tres\cuatro\cinco
祝你好运,编码愉快。
答案 1 :(得分:4)
以下是解决方法:将文件作为文本阅读。
$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,则会添加一些额外的功能: