gpt4 book ai didi

c# - 为什么无法从 C# 调用我的 powershell 函数?

转载 作者:行者123 更新时间:2023-11-30 22:51:41 25 4
gpt4 key购买 nike

尝试使用具有如下功能的 powershell 脚本:

    function MoveCompressFiles{
Param
(
[Parameter(Mandatory=$true )]
[string] $Des,
[Parameter(Mandatory=$true)]
[string] $Src
)
Add-Type -AssemblyName System.Drawing
$files = Get-ChildItem $Src
foreach ($f in $files) {
if (($f.Length / 1KB) -lt [int32]200) {
Copy-Item -Path $f.FullName -Destination $Des
}
else {
Copy-Item -Path $f.FullName -Destination $Des
while (((Get-Item (($Des).ToString() + "\$f")).Length / 1KB ) -gt 500) {
$img = [System.Drawing.Image]::FromFile((($Des).ToString() + "$f"))
[int32]$new_width = $img.Width * (20 / 100);
[int32]$new_height = $img.Height * (20 / 100);
$img2 = New-Object System.Drawing.Bitmap($new_width, $new_height)
$graph = [System.Drawing.Graphics]::FromImage($img2)
$graph.DrawImage($img, 0, 0, $new_width, $new_height)
$newImgName = "M".ToString() + $f.ToString()
$img2.Save(($Des).ToString()+"\$newImgName")
$img.Dispose()
$img2.Dispose()
Remove-Item ($Des.ToString()+$f)
Rename-Item -Path ($Des.ToString()+$newImgName) -NewName "$f"
Write-Host ((Get-Item ($Des.ToString()+$f)).Length / 1KB )
}
$filesize = $f.Length * 0.8
$filesize=($filesize / 1KB)
#$filesize = [math]::round(($filesize / 1KB), 0)
$abc = "KB"
$filesizeSTR = $filesize.ToString() + $abc
Push-Location $Src
mogrify -path $Des -define jpeg:extent=$filesizeSTR $f
Pop-Location
Write-Host "Moved file $f"
}
}
}

在 Powershell 中工作,但是当我尝试在我的解决方案中这样做时,

private static void Powershell()
{
string SCRIPT_PATH = System.IO.File.ReadAllText(@"C:\Untitled2.ps1");
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddScript(SCRIPT_PATH);
ps.Invoke();
ps.AddCommand("MoveCompressFiles").AddParameters(new Dictionary<string, string>
{
{"Des" , @"C:\Des"},
{"Src", @"C:\Src"}
});
}
}

它不起作用,我尝试了其他一些从 ps 脚本调用函数的方法,但它仍然无法将文件移动到另一个位置

最佳答案

由于您需要dot-source你的脚本文件 ( . <script> ) 来制作 MoveCompressFiles功能可用,需要 .AddScript()称呼,我建议在一个字符串变量中构建一段 PowerShell 代码,它既点源脚本又通过单个 .AddScript() 调用您的函数。打电话。

但是,为了保证.AddScript()有效,您必须首先确保 PowerShell execution policy允许脚本调用,调用Set-ExecutionPolicy ;下面的代码使用 -Scope Process , 从而限制对当前进程的更改。

  • 更新:有一种更简单的方法来配置执行策略,通过初始 session 状态 - 参见this answer .
var SCRIPT_PATH = @"C:\Untitled2.ps1";
var src = @"C:\Src";
var des = @"C:\Des";
var script = $@". ""{SCRIPT_PATH}""; MoveCompressFiles -Des ""{des}"" -Src ""{src}""";

using (PowerShell ps = PowerShell.Create())
{
// Make sure that script execution is allowed.
ps.AddCommand("Set-ExecutionPolicy")
.AddParameter("Scope", "Process")
.AddParameter("ExecutionPolicy", "Bypass")
.AddParameter("Force", true);
ps.Invoke();

// Add the PowerShell code constructed above and invoke it.
ps.AddScript(script);
// Use foreach (var o in ps.Invoke()) { Console.WriteLine(o); } to print the output.
ps.Invoke();
}

注意使用 PowerShell.Create() 简化的隐式 运行空间创建仅。

嵌入式 PowerShell 代码点源您的脚本文件 (. <script>) 以定义 MoveCompressFiles函数,然后调用该函数。

请注意,上面的代码作为您自己的代码,不会捕获或打印 PowerShell 代码的输出(.Invoke() 的输出)。

要查看是否发生错误,您可以检查ps.HadErrors并检查 ps.Streams.Error或任何其他流,例如 .ps.Streams.Information对于 Write-Host输出(成功 流的输出是 .Invoke() 直接返回的内容)。

例如,使用类似下面的内容打印发生在控制台标准错误流中的所有错误(仅消息):

foreach (var o in ps.Streams.Error) {
Console.Error.WriteLine(o);
}

至于你尝试了什么:

ps.AddScript(SCRIPT_PATH); ps.Invoke();

虽然这执行您的脚本,但它是在子作用域中执行的,所以嵌入式函数MoveCompressFiles定义添加到 session 的顶级范围,因此后续的 .AddCommand()调用失败,因为 MoveCompressFiles功能不可用。

相反,您必须 dot-source你的脚本 ( . <script> ),这使得它在调用者的范围内运行,因此它的函数定义在那里可用。

顺便说一句:尽管 .AddScript()方法的名称,其主要目的是执行一段PowerShell 代码,而不是脚本文件。要执行后者(无点源),请使用 .AddCommand() .

关于c# - 为什么无法从 C# 调用我的 powershell 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58949088/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com