java - 从 Java 运行 PowerShell 文件显示该文件没有 '.ps1' 扩展名

标签 java bash powershell fedora

我正在尝试弄清楚如何从 Java 中运行 PowerShell 脚本。请记住,我对 Java 还很陌生,因此可能有更好的方法来做到这一点。

目前我在 Fedora 25 工作站上安装了 PowerShell。

正如 here 所解释的,首先安装 Fedora .NET Core 包:

sudo dnf config-manager --add-repo https://copr.fedorainfracloud.org/coprs/nmilosev/dotnet-sig/repo/fedora-25/nmilosev-dotnet-sig-fedora-25.repo
sudo dnf update
sudo dnf install dotnetcore

然后下载 RPM for CentOS 7 并安装它。

sudo dnf install Downloads/powershell-6.0.0_beta.1-1.el7.centos.x86_64.rpm
powershell

然后我使用此 post 中的代码来运行“Hello world”ps1 文件:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class PowerShellCommand {
    public static void main(String[] args) throws IOException {
        String command = "powershell $PSVersionTable.PSVersion";
        command = "powershell -ExecutionPolicy RemoteSigned -NoProfile -NonInteractive -File \"/home/b/Downloads/MyScript.ps1\"";

        Process powerShellProcess = Runtime.getRuntime().exec(command);
        powerShellProcess.getOutputStream().close();
        String line;
        System.out.println("Standard Output:");
        BufferedReader stdout = new BufferedReader(new InputStreamReader(
                powerShellProcess.getInputStream()));
        while ((line = stdout.readLine()) != null) {
            System.out.println(line);
        }
        stdout.close();
        System.out.println("Standard Error:");
        BufferedReader stderr = new BufferedReader(new InputStreamReader(
                powerShellProcess.getErrorStream()));
        while ((line = stderr.readLine()) != null) {
            System.out.println(line);
        }
        stderr.close();
        System.out.println("Done");
    }
}

尝试运行 .ps1 文件时遇到的错误是:

Processing -File '"/home/b/Downloads/MyScript.ps1"' failed because the file does not have a '.ps1' extension. Specify a valid Windows PowerShell script file name, and then try again.

当尝试从 Java 代码中运行它时,我确实得到了变量的正确输出:

String command = "powershell $PSVersionTable.PSVersion";

当在 Gnome 终端中从 bash shell 运行以下命令时,这也可以正常工作,并且通过说“Hello world”可以正确执行脚本:

powershell -ExecutionPolicy RemoteSigned -NoProfile -NonInteractive -File "/home/b/Downloads/MyScript.ps1"

感谢您的帮助。

最佳答案

注意:

  • 自问题发布以来,PowerShell Core 可执行文件的名称已从 powershell 更改为 pwsh,这反射(reflect)在下面的解决方案中。

  • 问题中的特定脚本文件路径 - /home/b/Downloads/MyScript.ps1 - 严格要求引用(包含在“...”中),但是通常稳健的解决方案应该使用引用 - 这就是下面演示的内容。


通过将命令构造为单个字符串嵌入的 " 实例将保留为文字>,错误消息反射(reflect)的是:

Processing -File '"/home/b/Downloads/MyScript.ps1"' ...

请注意 '...' 中的引号值如何包含封闭的 "..." - 以及字面上包含 " 的路径字符显然不存在,并且 - 由于以 " 结尾 - 没有 .ps1 扩展名。
什么是single-command-string form of Runtime.exec()所做的是通过 StringTokenizer 执行字符串的仅空白标记化。因此,生成的数组保留嵌入的引号,并且也不会将带有嵌入空格的带引号的标记识别为单个标记。


您有两种选择来解决此问题:

  • (a) 使用 -Command& 而不是 -File 来调用脚本,在这种情况下,PowerShell 使用另一轮解析,因此嵌入的 " 实例被识别为具有语法功能。

    String command = "pwsh -NoProfile -Command & \"/home/b/Downloads/MyScript.ps1\"";
    
  • (b) 最好,将命令行的标记作为字符串数组传递:

    String[] command = new String[] { "pwsh", "-NoProfile", "-File", "/home/b/Downloads/MyScript.ps1" };
    

请注意,对于 (a),如果您在命令字符串中包含要传递给脚本的参数,这些参数也会由 PowerShell 进行解析,这意味着您可能也需要为它们嵌入引用。

请注意,对于脚本路径参数,(b) 不需要嵌入引用,因为它被指定为其自己的数组元素。通过使用 PowerShell 的 -File 参数,所有传递的参数都被视为文字

关于java - 从 Java 运行 PowerShell 文件显示该文件没有 '.ps1' 扩展名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44087451/

相关文章:

java - 为什么 Java 框架不强制使用接口(interface)?

java - 将实体移动到带有像素的位置 - libgdx - vector 数学

linux - 将文本提取到新文件中

bash - env -0 转储环境。但是如何加载呢?

powershell - 具有十六进制值的 Invoke-WebRequest

java - 使用和公开 REST 服务并传递 JSON 正文

java - 将后缀表达式转换为中缀并计算后缀并给出答案

linux - 在日志中用主机名替换 IP

file - Powershell读取主机用户输入添加

Azure Functions-新-AzContainerGroup : Object reference not set to an instance of an object