0

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?

Ilya Volodin
  • 10,929
  • 2
  • 45
  • 48

4 Answers4

1

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
  • 106,783
  • 21
  • 203
  • 265
  • 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 Apr 08 '09 at 21:25
  • 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 Apr 08 '09 at 22:19
1

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);
      }
    }
  }
pero
  • 4,169
  • 26
  • 27
  • is there a good reason to have a static string rather than changing the signature of the ctor to take the args ? – abe Sep 28 '10 at 16:33
  • 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. – pero Sep 29 '10 at 12:59
0

Have you tried Environment.GetCommandLineArgs()?

Greg D
  • 43,259
  • 14
  • 84
  • 117
  • 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 Apr 08 '09 at 02:50
  • 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: 2 Number of Args is just args.Length, number of Env. Args is Environment.GetCommandLineArgs().Length – Ilya Volodin Apr 08 '09 at 03:22
0

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.

cjk
  • 45,739
  • 9
  • 81
  • 112