简体   繁体   English

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

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

Im trying to run a ps1 script out of the resource Folder in c#我试图从 c# 的资源文件夹中运行 ps1 脚本

Thanks to Yevhen Cherkes感谢Yevhen Cherkes

.NET Get embedded Resource File .NET 获取嵌入式资源文件

Load C# Embedded Resource Path into PowerShell Command Class 加载 C# 嵌入式资源路径到 PowerShell 命令 Class

Got me closer.让我靠得更近了。

Changing改变

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();
        }

to

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();
        }
    }

This only throws an exception with the whole ps script - not known as cmdlet - though, it does read it but addcommand ran the script before.这只会引发整个 ps 脚本(不称为 cmdlet)的异常,但它确实会读取它,但addcommand之前运行过该脚本。 Is it simply AddScript now or am i still approaching it wrong?它现在只是 AddScript 还是我仍然在错误地接近它?

Thanks in Advance提前致谢

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();
        }
    }

is the solution for my question.是我的问题的解决方案。 I included the solutions of the mentioned above threads and changed AddCommand to AddScript ( idk why addcommand worked with reading it from the local file and doesnt in this case )我包含了上述线程的解决方案,并将 AddCommand 更改为 AddScript (idk 为什么 addcommand 可以从本地文件中读取它而在这种情况下没有)

Let me add some background information to your own (effective) answer :让我为您自己的(有效)答案添加一些背景信息:

Note: Your problem came down to having to switch from .AddCommand() for script- file execution ( .ps1 ) to .AddScript() for source-code string execution (from a resource).注意:您的问题归结为必须从用于执行脚本文件( .ps1 ) 的.AddScript() .AddCommand()到用于执行源代码字符串(从资源)的 .AddScript()。 The following focuses mainly on when to use .AddCommand() vs. .AddScript() for script- file execution.以下主要关注何时使用.AddCommand().AddScript()来执行脚本文件

  • .AddCommand() is the right PowerShell SDK method for invoking script files ( .ps1 ) and other command forms , namely cmdlets, functions, and external programs. .AddCommand()是调用脚本文件.ps1和其他命令 forms的方法,即 cmdlet、函数和外部程序。

    • A potential problem is that the effective PowerShell execution policy may prevent execution of script files .一个潜在的问题是有效的 PowerShell 执行策略可能会阻止脚本文件的执行 On pristine machines running Windows desktop editions, script-file execution is by default disabled altogether ( Restricted ), whereas it is RemoteSigned on server machines.在运行 Windows桌面版的原始机器上,脚本文件执行默认完全禁用( Restricted ),而在服务器机器上是RemoteSigned

    • Assuming the effective execution policy doesn't prevent script-file execution via GPOs (Group Policy Objects), you can solve this problem by setting the execution policy for the current PowerShell session (only) , via the SDK ;假设有效的执行策略不会阻止通过 GPO (组策略对象)执行脚本文件,您可以通过为当前 PowerShell session(仅)设置执行策略来解决此问题RemoteSigned (browser-downloaded files must have a valid signature) is usually the safe choice: 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); //...
      • If a GPO-controlled execution policy prevents you from setting the session's execution policy (or you simply want to avoid having to set the session execution policy explicitly), you can use .AddScript() as workaround , as discussed next - but do note that is has limitations and side effects .如果 GPO 控制的执行策略阻止您设置会话的执行策略(或者您只是想避免必须显式设置 session 执行策略),您可以使用.AddScript()作为解决方法,如下所述 - 但请注意是有局限性副作用的
  • The somewhat confusingly named .AddScript() method is for invoking PowerShell source code provided directly as a string , the content of a script file, so to speak, or, as in your case, a piece of PowerShell code retrieved from a resource embedded in an assembly.有点令人困惑的.AddScript()方法用于调用直接作为字符串提供的 PowerShell 源代码,可以说是脚本文件的内容,或者在您的情况下,从嵌入的资源中检索到的一段 PowerShell 代码一个大会。

    • Therefore, as long as a given script file's content (code) doesn't (directly or indirectly [1] ) invoke other script files, you can use .AddScript() to bypass PowerShell's execution policies (which apply only to script files ).因此,只要给定脚本文件的内容(代码)不(直接或间接[1] )调用其他脚本文件,您就可以使用.AddScript()绕过PowerShell 的执行策略(仅适用于脚本文件)。

    • That is, as shown in your answer, you can read a .ps1 file's content into a string in memory up front, and pass that string to .AddScript() ;也就是说,如您的答案所示,您可以预先将.ps1文件的内容读入 memory 中的字符串,然后将该字符串传递给.AddScript() the simplest way to dot that is to use System.IO.File.ReadAllText :最简单的打点方法是使用System.IO.File.ReadAllText

       ps.AddScript(File.ReadAllText(skriptpath)); // Call ps.AddParameter() as needed.
    • Caveat : A side effect of this technique is that the script-file body invoked this way will be unaware of the script file's original file name and location .警告:这种技术的副作用是,以这种方式调用的脚本文件主体将不知道脚本文件的原始文件名位置


[1] Note that some modules automatically execute .ps1 files during their import, and that the module import itself may happen automatically. [1] 请注意,某些模块在导入期间会自动执行.ps1文件,并且模块导入本身可能会自动发生。

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

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