tags:

views:

696

answers:

4

I have what seems to be a simple problem that I can't solve myself. I have a WinForm app, with main method modified to accept command line arguments like this:

    [STAThread]
    static void Main(String[] args)
    {
        int argCount = args.Length;
    }

This code works fine and argCount is equals to 2 when compiled in debug mode with the following execution line: program.exe -file test.txt. However as soon as I compile the program in release mode, argCount is now 1 with the same command line arguments. The only argument contains "-file test.txt". More than that it only happens if I run the compiled executable from obj/Release folder, but not from bin/Release. Unfortunately setup project takes executables from obj/Release so I can't change that. Is this a known issue and is there a way around this problem?

A: 

Have you tried Environment.GetCommandLineArgs()?

Greg D
Thanks! I'll try that, however, it will require significant change in my code, since the first argument is the name of the program. Seems like there should be a way around existing problem with release build.
Ilya Volodin
Tried it, still doesn't work:-( Output from custom log file: First Key=[-file C:\Temp\test.dpk] Number of Args: 1 Number of Environment Args: 2Number of Args is just args.Length, number of Env. Args is Environment.GetCommandLineArgs().Length
Ilya Volodin
+1  A: 

The command line processing should be the same, therefore something else is going on. When I try this:

class Program {
    [STAThread]
    static void Main(String[] args) {
        Console.WriteLine("Have {0} arguments", args.Length);
        for (int i = 0; i < args.Length; ++i) {
            Console.WriteLine("{0}: {1}", i, args[i]);
        }
    }
}

and then it from the various locations I get 100% consistent results, the only way of getting arguments "merged" is to enclose them in quotes on the command line (which is specifically there to allow you do have arguments containing a space, see the last example below):

PS C:\...\bin\Debug> .\ConsoleApplication1.exe one two three
Have 3 arguments
0: one
1: two
2: three
PS C:\...\bin\Debug> pushd ..\release
PS C:\...\bin\Release> .\ConsoleApplication1.exe one two three
Have 3 arguments
0: one
1: two
2: three
PS C:\...\bin\Release> pushd ..\..\obj\debug
PS C:\...\obj\Debug> .\ConsoleApplication1.exe one two three
Have 3 arguments
0: one
1: two
2: three
PS C:\...\obj\Debug> pushd ..\release
PS C:\...\obj\Release> .\ConsoleApplication1.exe one two three
Have 3 arguments
0: one
1: two
2: three
PS C:\...\obj\Release> .\ConsoleApplication1.exe -file test.txt
Have 2 arguments
0: -file
1: test.txt
PS C:\...\obj\Release> .\ConsoleApplication1.exe "-file test.txt"
Have 1 arguments
0: -file test.txt

Additional While launching from a command prompt makes it easy to see what is being passed it can be hard to check when another application launches yours. However tools like Process Explorer will show the command line used to start a program (double click on a process and look at the image tab).

Richard
My bad, I'm an idiot:-) I just noticed that my installer's open command for file format was "-file {0}" and all I had to do is remove quotes....
Ilya Volodin
Oops... easy to do and hard to spot... will add a note on ways to check actually what is being passed if not directly executed.
Richard
+1  A: 

This works for me from bin/Debug, bin/Release, obj/Debug and obj/Release:

static class Program {
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main(string[] args) {
    FormMain.Args = args;

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new FormMain());
  }
}

  public partial class FormMain: Form {
    public static string[] Args;

    public FormMain() {
      InitializeComponent();
    }

    private void FormMain_Shown(object sender, EventArgs e) {
      foreach (string s in Args) {
        MessageBox.Show(s);
      }
    }
  }
Petar Repac
is there a good reason to have a static string rather than changing the signature of the ctor to take the args ?
Dara
No, there is not. I used static string for brevity of answer. As you can see I declared Args as public field. In real code I'd never do that. In this case where we store our arguments is not so important, we are solving another kind of problem.
Petar Repac
A: 

Your problem (as Richard points out within his code) is that your arguments when you are running the release version are all enclosed in one set of quotes. Remove the quotes and it will work.

ck