PowerShell运行Java进程问题

7
我将为您翻译以下内容:“我正在尝试通过Windows XP中的PowerShell运行Java进程。这是命令:”
java.exe -cp .;./common.jar -Dcontext=atest1 -Dresourcepath=. DW_Install

因此,类路径是.和.\common.jar(我认为Java使用了错误的斜杠,对吗?)有两个环境变量,一个是“ atest1”,另一个是“。”要执行main函数的类位于DW_Install中(在默认包中)。

这个命令在cmd.exe中可以工作,但在PS中无法工作。发生了什么?解析此命令时,PS做了什么CMD没有做的事情(反之亦然)?

Aaron


2
当你说在Powershell中它不起作用时,实际上发生了什么? - DanielGibbs
我得到了java.exe的帮助输出,就好像我刚刚输入了 javajava -help - lmat - Reinstate Monica
5个回答

9
问题在于,由于某种原因,PS解析-Dresourcepath=.的方式与cmd不同。有效的方法是:
java -cp '.;.\common.jar' -Dcontext=atest1 "-Dresourcepath=." DW_Install

斜杠的方向和引号的使用方式并不重要(可以使用单引号或双引号)。但是,类路径必须用某种引号进行转义。为了测试PS解释器的效果,可以使用echo命令。以下是示例:

echo java -cp '.;.\common.jar' -Dcontext=atest1 -Dresourcepath=. DW_Install

产生以下输出:
java
-cp
.;.\common.jar
-Dcontext=atest1
-Dresourcepath=
.
DW_Install

请注意resourcepath和resourcepath的值不在同一行。而输出结果为

echo java -cp '.;.\common.jar' -Dcontext=atest1 '-Dresourcepath=.' DW_Install

产生以下输出:
java
-cp
.;.\common.jar
-Dcontext=etaste1
-Dresourcepath=.
DW_Install

这更符合我们的喜好。

虽然我不希望你们中的任何人遇到这种情况,但我希望这篇文章能帮助那些必须在Windows机器上部署Java项目的人(即使它们永远不能在其他平台上运行)。


7

在PowerShell中运行外部命令行程序有时会有些问题,因为PowerShell公开了两种不同的解析模式,这些模式会被外部程序的不同语法所取代。

无论如何,在PowerShell中运行命令需要使用.前缀(dot-"sourcing")或&运算符。

您可以通过将每个参数作为单独的变量传递给外部程序来解决此问题,例如:

PS> $classpath = ".;./common.jar"
PS> $env = "-Dcontext=atest1 -Dresourcepath=."
PS> $class = "DW_Install"

PS> . java.exe -cp $classpath $env $class

输入 . java.exe -cp .;.\common.jar -Dcontext=atest1 -Dresourcepath=. DW_Install. java.exe -cp ".;.\common.jar" -Dcontext=atest1 -Dresourcepath="." DW_Install 以及 . java.exe -cp '.;.\common.jar' -Dcontext=atest1 -Dresourcepath='.' DW_Install 都不起作用。虽然使用第一个选项时,我可以看到 Java 的使用输出,但是我已经进入了 java.exe 进程。 - lmat - Reinstate Monica
1
(a)仅在程序名称会触发另一种解析模式时(7za.exe是一个例子)才需要使用,但即使如此,您也应该使用&而不是,因为您不是将外部程序进行点源化。 (b)$ env变量将无法按预期工作。 - Joey
虽然你的回答非常好,解决了许多问题,但是1)它有些过度,2)它并不完全准确。对于1)的证明,请参见我下面的回答。对于2),(假设我将$env更改为$en),我需要一个不同的PS变量来处理每个-D参数,以使一切正常工作。这确实解决了我在下面指出的问题(错误解析resourcepath =.),但对我来说过于繁琐...再想想,每次都不必输入这些环境变量可能会有所帮助...再次感谢您的帖子,您得到了我的投票。 - lmat - Reinstate Monica

3

以下是基于https://gaming.stackexchange.com/questions/24543/how-do-i-change-player-name-in-minecraft-multiplayer-in-offline-mode-in-linux的另一个示例。

function mineCraftAs {
    Param (
        [parameter(mandatory=$true, HelpMessage="Minecraft character name." ,ValueFromPipeline=$true)]
        [string] $name
    )
    if(!(test-path $env:appdata)) { $(throw "Appdata not found at $env:appdata")}
    $private:minecraftPath=Join-Path $env:appdata .minecraft
    if(!(test-path $minecraftPath)) { $(throw "Minecraft not found at $minecraftpath")}
    $private:minebinPath=join-path $minecraftPath "bin"
    if(!(test-path $minebinPath)) { $(throw "Minecraft bin not found at $minebinPath")}

    $minebinPath | write-debug
    gci $minebinpath | write-debug

    #java -Xms512m -Xmx1024m -cp "%APPDATA%/.minecraft\bin\*" -Djava.library.path="%APPDATA%\.minecraft\bin\natives" net.minecraft.client.Minecraft '"'%1'"'

    echo java -Xms512m -Xmx1024m  -cp ('"'+$minebinPath+'\*"') ('-Djava.library.path="'+$minebinPath+'\natives"') net.minecraft.client.Minecraft ($name)

    $minecraftJob=& 'C:\Program Files (x86)\Java\jre6\bin\java.exe' -Xms512m -Xmx1024m  -cp ('"'+$minebinPath+'\*"') ('-Djava.library.path="'+$minebinPath+'\natives"') net.minecraft.client.Minecraft ($name)
}
minecraftas newbie

谢谢提供信息!这是一个有用的例子,我支持它。 - lmat - Reinstate Monica

1
以下代码应该可以正常工作:
java.exe -cp '.;./common.jar' -Dcontext=atest1 -Dresourcepath=. DW_Install

我猜PowerShell将类路径中的;解释为命令分隔符,因此尝试运行java -cp ../common.jar -D...


不行,不起作用,尽管尝试了。我已经找到答案了,请看下面。 - lmat - Reinstate Monica

0
start-process -nnw java "-cp .;./common.jar -Dcontext=atest1 -Dresourcepath=. DW_Install"

谢谢晚回复!我不再拥有微软Windows,也没有我试图运行的项目,因此我无法验证其有效性。 - lmat - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接