繁体   English   中英

在 C# 中运行/存放 Powershell 脚本

[英]Run/deposit a Powershell Script in C#

我试图从 c# 的资源文件夹中运行 ps1 脚本

感谢Yevhen Cherkes

.NET 获取嵌入式资源文件

加载 C# 嵌入式资源路径到 PowerShell 命令 Class

让我靠得更近了。

改变

private void button1_Click_1(object sender, EventArgs e)
        {
            PowerShell ps = PowerShell.Create();
            string skriptpfad = $@"C:\Users\username\Desktop\1Tool_Final\WinformsTool\bin\Debug\zuordnung.ps1";
            ps.AddCommand(skriptpfad);
            ps.AddParameter("Source", folderBrowserDialog1.SelectedPath);
            ps.AddParameter("Destination", folderBrowserDialog2.SelectedPath);
            ps.Invoke();
        }

private void button1_Click_1(object sender, EventArgs e)
    {
        var assembly = Assembly.GetExecutingAssembly();
        var resourceName = "zuordnung_test.Resources.zuordnung.ps1";

        using (Stream stream = assembly.GetManifestResourceStream(resourceName))
        using (StreamReader reader = new StreamReader(stream))
        {
            string skriptpfad = reader.ReadToEnd();
            PowerShell ps = PowerShell.Create();
            //string skriptpfad = $@"C:\zuordnung.ps1";
            ps.AddCommand(skriptpfad);
            ps.AddParameter("Source", folderBrowserDialog1.SelectedPath);
            ps.AddParameter("Destination", folderBrowserDialog2.SelectedPath);
            ps.Invoke();
        }
    }

这只会引发整个 ps 脚本(不称为 cmdlet)的异常,但它确实会读取它,但addcommand之前运行过该脚本。 它现在只是 AddScript 还是我仍然在错误地接近它?

提前致谢

private void button1_Click_1(object sender, EventArgs e)
    {
        var assembly = Assembly.GetExecutingAssembly();
        var resourceName = "%projectname%.Resources.%script.ps1%";

        using (Stream stream = assembly.GetManifestResourceStream(resourceName))
        using (StreamReader reader = new StreamReader(stream))
        {
            string skriptpath = reader.ReadToEnd();
            PowerShell ps = PowerShell.Create();
            ps.AddScript(skriptpath);
            //ps.AddParameter...
            ps.Invoke();
        }
    }

是我的问题的解决方案。 我包含了上述线程的解决方案,并将 AddCommand 更改为 AddScript (idk 为什么 addcommand 可以从本地文件中读取它而在这种情况下没有)

让我为您自己的(有效)答案添加一些背景信息:

注意:您的问题归结为必须从用于执行脚本文件( .ps1 ) 的.AddScript() .AddCommand()到用于执行源代码字符串(从资源)的 .AddScript()。 以下主要关注何时使用.AddCommand().AddScript()来执行脚本文件

  • .AddCommand()是调用脚本文件.ps1和其他命令 forms的方法,即 cmdlet、函数和外部程序。

    • 一个潜在的问题是有效的 PowerShell 执行策略可能会阻止脚本文件的执行 在运行 Windows桌面版的原始机器上,脚本文件执行默认完全禁用( Restricted ),而在服务器机器上是RemoteSigned

    • 假设有效的执行策略不会阻止通过 GPO (组策略对象)执行脚本文件,您可以通过为当前 PowerShell session(仅)设置执行策略来解决此问题 RemoteSigned (浏览器下载的文件必须有一个有效的签名)通常是安全的选择:

       // Create an initial default session state. var iss = InitialSessionState.CreateDefault2(); // Set its script-file execution policy (for the current session only). iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned; // Create a PowerShell instance with a runspace based on the // initial session state. PowerShell ps = PowerShell.Create(iss); //... // Now, .AddCommand() should work fine. ps.AddCommand(skriptpfad); //...
      • 如果 GPO 控制的执行策略阻止您设置会话的执行策略(或者您只是想避免必须显式设置 session 执行策略),您可以使用.AddScript()作为解决方法,如下所述 - 但请注意是有局限性副作用的
  • 有点令人困惑的.AddScript()方法用于调用直接作为字符串提供的 PowerShell 源代码,可以说是脚本文件的内容,或者在您的情况下,从嵌入的资源中检索到的一段 PowerShell 代码一个大会。

    • 因此,只要给定脚本文件的内容(代码)不(直接或间接[1] )调用其他脚本文件,您就可以使用.AddScript()绕过PowerShell 的执行策略(仅适用于脚本文件)。

    • 也就是说,如您的答案所示,您可以预先将.ps1文件的内容读入 memory 中的字符串,然后将该字符串传递给.AddScript() 最简单的打点方法是使用System.IO.File.ReadAllText

       ps.AddScript(File.ReadAllText(skriptpath)); // Call ps.AddParameter() as needed.
    • 警告:这种技术的副作用是,以这种方式调用的脚本文件主体将不知道脚本文件的原始文件名位置


[1] 请注意,某些模块在导入期间会自动执行.ps1文件,并且模块导入本身可能会自动发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM