-3

I'm very new to the coding space and was wondering if someone could help me start a .jar file. BTW This is using C#. My issue is this wont run the file. I got it to work with .txt files though, so I'm just a bit confused.

private void button1_Click(object sender, EventArgs e)
    {
        Process.Start("java" , "server.jar");
    }
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 4
    Naively, that should work. What makes you think that it doesn't (what errors do you see, etc)? – canton7 Jan 22 '21 at 09:19
  • Well what the server.jar file does is start a server in a CMD panel. I dont get any errors and when I push my button it does nothing. – MIthrilDragon Jan 22 '21 at 09:22
  • Make sure Java is in your path, and JAVA_HOME environment variable is set properly – CoolBots Jan 22 '21 at 09:23
  • Ok so I just checked and everything seems fine. but when I use java.exe instead of just java for a second it flashes a cmd of the java directory on my screen. – MIthrilDragon Jan 22 '21 at 09:25
  • Ok butthe server also is suppose to make a eula.txt file when run and that is not happing when I run it using the program. But if I run it without the program it makes that file and works normaly – MIthrilDragon Jan 22 '21 at 09:27
  • I'd probably put in the full path to server.jar to see if it makes a difference. – PeterJ Jan 22 '21 at 09:33
  • 2
    Hint: do things separately. Your first problem is to run java from C#. You do. not need a button for that or anything. Just write the minimal C# code that does what you want, like from here: https://stackoverflow.com/questions/873809/how-to-execute-a-java-program-from-c ... then carefully debug that, and make sure it does what you expect it to do. And **then**, when that stuff all works, then call it from your UI code. – GhostCat Jan 22 '21 at 09:35
  • 2
    Of course it won't work. I don't know what the first argument of the `Process.Start` method should be (_[JAVAHOME\bin\]java[.exe]_), but `java` accepts `-jar` to indicate a JAR. – terrorrussia-keeps-killing Jan 22 '21 at 09:41

3 Answers3

1

In short, for the answer, add -jar right before the JAR file name.

The accepted answer is not 100% correct for several reasons: it does not recognize whitespace-delimited and whitespace-containing arguments, and may mess up with quote characters that must be passed (therefore properly escaped) to the delegated Java app. In short, do not use Arguments if the string is not known to be a constant (having spaces will require manual escaping anyway), but merely prefer ArgumentList that handles each argument properly.

Here is an example Java application to deal with command line arguments:

public final class SayHello {
    private SayHello() {}
    public static void main(final String... names) {
        for ( final String name : names ) {
            System.out.printf("hello %s!\n", name);
        }
    }
}

The manifest for the JAR file:

Manifest-Version: 1.0
Main-Class: SayHello

Making a JAR file out of it is simple:

javac SayHello.java
jar cfm SayHello.jar MANIFEST.MF SayHello.class

Example of use:

java -jar SayHello.jar 'John Doe' Anonymous

that gives:

hello John Doe!
hello Anonymous!

Now, an example C# program that passes the -jar argument to the java process so that it recognizes the given file as a JAR file and demonstrates what can go wrong with Arguments if passed as a string.

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>
</Project>
using System.Diagnostics;
public static class SayHello {
    public static void Main() {
        // interprets 3 names: John, Doe, Anonymous (wrong)
        RunJavaJarBadly1("SayHello.jar", "John Doe Anonymous");
        // interprets 1 name: John Doe Anonymous (wrong)
        RunJavaJarBadly2("SayHello.jar", "John Doe Anonymous");
        // interprets 2 names: John Doe, Anonymous (correct, but bad: requires the first name to be quoted at the call-site)
        RunJavaJarBadly1("SayHello.jar", "\"John Doe\" Anonymous");
        // interprets 1 name: "John Doe" Anonymous (wrong: interprets everything as a single name)
        RunJavaJarBadly2("SayHello.jar", "\"John Doe\" Anonymous");
        // interprets 2 names, no ambiguous call, each name is recognized properly, does not require quoting at the call site
        RunJavaJar("SayHello.jar", "John Doe", "Anonymous");
    }
    private static void RunJavaJarBadly1(string jarPath, string argumentsFortheJarFile) {
        var process = new Process();
        process.StartInfo.FileName = "java";
        process.StartInfo.Arguments = @"-jar "+ jarPath +" " + argumentsFortheJarFile;
        process.Start();
        process.WaitForExit();
    }
    private static void RunJavaJarBadly2(string jarPath, string jarArgs) {
        var process = new Process();
        process.StartInfo = new ProcessStartInfo("java") {
            ArgumentList = { "-jar", jarPath, jarArgs }
        };
        process.Start();
        process.WaitForExit();
    }
    private static void RunJavaJar(string jarPath, params string[] jarArgs) {
        var process = new Process();
        process.StartInfo = new ProcessStartInfo("java") {
            ArgumentList = { "-jar", jarPath }
        };
        foreach ( var jarArg in jarArgs ) {
            process.StartInfo.ArgumentList.Add(jarArg);
        }
        process.Start();
        process.WaitForExit();
    }
}

The code above produces (no legend in the output, but added for explanation):

hello John!                 \_ #1/1: incorrect, the space is ignored
hello Doe!                  /
hello Anonymous!            -- #1/2: correct, no spaces in-between
hello John Doe Anonymous!   -- #2/1|2: incorrect
hello John Doe!             -- #3/1: correct, but requires the call site to escape the argument
hello Anonymous!            -- #3/2: correct, no need to escape, thanks to no spaces
hello "John Doe" Anonymous! -- #4/1|2: incorrect, similar to #2/1|2
hello John Doe!             -- #5/1: correct, let the framework do its job
hello Anonymous!            -- #5/2: correct, let the framework do its job
-1

In order to get it to work, the file name needs to be "java" and contain the file location in the arguments.

System.Diagnostics.Process clientProcess = new Process();
clientProcess.StartInfo.FileName = "java";
clientProcess.StartInfo.Arguments = @"-jar "+ jarPath +" " + argumentsFortheJarFile;
clientProcess.Start();
clientProcess.WaitForExit();   
int code = clientProcess.ExitCode;

Taken from similar question here

Optional way using ArgumentList:

System.Diagnostics.Process clientProcess = new Process();
var info = new System.Diagnostics.ProcessStartInfo("java.exe")
{
    ArgumentList = {
        "-jar",
        jarPath,
        jarArgs
    }
};
info.FileName = "java";
clientProcess.StartInfo = info;
clientProcess.Start();
clientProcess.WaitForExit();   
int code = clientProcess.ExitCode;
AbandonedCrypt
  • 187
  • 1
  • 12
  • Not a .NET guy, but isn't it better to fill the `ArgumentList` property in order not to get into the unescaped strings hell? – terrorrussia-keeps-killing Jan 22 '21 at 09:49
  • @fluffy by adding the @ in front of a string you mark it as verbatim and therefore tell it to ignore any ecape sequences. – AbandonedCrypt Jan 22 '21 at 09:52
  • Its works thanks for the help man have a good night. :) – MIthrilDragon Jan 22 '21 at 09:53
  • I mean what would happen if the `jarPath` contains spaces, or if the `argumentsFortheJarFile` contains multiple arguments one of which should contain a whitespace? – terrorrussia-keeps-killing Jan 22 '21 at 09:53
  • @fluffy interesting thought,i was under the impression java interprets file paths up until the ".jar" and only takes arguments after the file name and afaik java arguments can't have whitespaces. You got me thinking now, though and I can't say 100% for sure to be honest. – AbandonedCrypt Jan 22 '21 at 09:57
  • I will upvote your answer if you remove `Arguments` in favor of `ArgumentList` with two `.Add(...)`s for `"-jar"`, `jarPath`, and (if I get .NET correctly) `.AddRange(...)` for the Java application arguments (assuming it's an enumerable containing all Java-app arguments, not a single string with ambiguous whitespaces). – terrorrussia-keeps-killing Jan 22 '21 at 10:00
  • btw: only `@"-jar "` is verbatim here. https://dotnetfiddle.net/sIGnvD – Fildor Jan 22 '21 at 10:09
  • @fluffy That would be overkill, I will edit in an optional way of using ArgumentList, however using a list entry for every argument is not necessary and would result in redundant list operations. According to oracle docs, CL-args are separated by space, hence a single argument can not have a space in it anyways – AbandonedCrypt Jan 22 '21 at 10:17
  • @Fildor I assume jarPath/Args initialization to use verbatim literal aswell. – AbandonedCrypt Jan 22 '21 at 10:18
  • @AbandonedCrypt 1) That is not an overkill: the `ArgumentList` is safe comparing to `Arguments` because the latter is not a constant and you can't tell if it won't break the arguments containing spaces. Performance is nothing here. 2) Next, the `main` method in `java -jar sayhello.jar "John Doe"` will accept a single string, `"John Doe"` (see the spaces right?), so "can not have a space in it" is merely false. 3) You simply copy/pasted the linked answer (I missed it), rather that linking a duplicate. – terrorrussia-keeps-killing Jan 22 '21 at 10:21
  • @fluffy Of course "John Doe" would work, as they are enclosed in "" telling java to treat them as if they didnt contain a space. By nature, command-line arguments do not accept spaces (if not specifically told to by enclosing them in ""), which is a direct conclusion of what oracle writes in their docs: "This is because the space character separates command-line arguments" (https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html) 3) I linked the original specifically stating it is taken from there when i created this answer. – AbandonedCrypt Jan 22 '21 at 10:27
  • @AbandonedCrypt No, no and one more time no: this is just wrong. Java does NOT parse enclosing quotes itself: quotes are handled by a command line processor or a shell (correct for both Windows `cmd` (probably PowerShell) and UNIX systems (miriads shells like `bash`, `sh`, `zsh`, etc)), so when you start the command above, your command line parser _parses_ it and then runs the command similarly to what I've suggested above. Java does not parse itself as JVM has a ready-to-use arguments table before JVM even starts. – terrorrussia-keeps-killing Jan 22 '21 at 10:31
  • @fluffy If so, being quotation marks not being parsed, then I don't see the problem, since `Arguments` corresponds to a space-separated string of `ArgumentList` members. (https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-5.0#examples) and should not make a difference if initializing strings verbatim. – AbandonedCrypt Jan 22 '21 at 10:38
  • @AbandonedCrypt Additionally, if I recall correctly my .NET past, `public System.Collections.ObjectModel.Collection ArgumentList { get; }` means that you cannot assign a list to a read-only property, and you can only add to it. So you didn't even bother to check what you publish. And you don't seem to realize what shells do to make quotes work, and why it will not work for your case. Again, too much wasted time. – terrorrussia-keeps-killing Jan 22 '21 at 10:46
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227686/discussion-between-abandonedcrypt-and-fluffy). – AbandonedCrypt Jan 22 '21 at 11:26
-2

Here are some options for you to check out. Also similar question with a working result: here

Paraphrasing from links:

In order to get it to work, the file name needs to be "java" and contain the file location in the arguments.

System.Diagnostics.Process clientProcess = new Process();
clientProcess.StartInfo.FileName = "java";
clientProcess.StartInfo.Arguments = @"-jar "+ jarPath +" " + argumentsFortheJarFile;
clientProcess.Start();
clientProcess.WaitForExit();   
int code = clientProcess.ExitCode;
AbandonedCrypt
  • 187
  • 1
  • 12
  • Just tried it no luck. – MIthrilDragon Jan 22 '21 at 09:32
  • @MIthrilDragon please check out the sources I linked for examples of other people getting it working. – AbandonedCrypt Jan 22 '21 at 09:34
  • Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. See [here](https://meta.stackexchange.com/a/94027/285661) for instructions how to write *better* "link-based" answers. – GhostCat Jan 22 '21 at 09:36