C# Command Line arguments problem in Release build - c#

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?

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).

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);
}
}
}

Have you tried Environment.GetCommandLineArgs()?

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.

Related

FolderBrowserDialog won't show in a single .cs file without Form

I am trying to code a program which is executed when a file is right clicked in windows, and then a context menu feature named 'Move to' executes a file in the windows registry HKEY ClASSES. It ought to parse in "%1" as argument when it executes, so that my program knows where the file is located. However, when I compile my single .cs file, the FolderBrowserDialog won't show. I am suspecting that it is because I haven't initialized some kind of form before I call it. Is it possible in some way to choose a folder from a single c# file without including Forms?
using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
public class MoveTo : Form
{
public static string current_file_path;
public static string new_file_path;
public static string file_name;
public static void Main(string[] args){
if (args.Length > 0)
{
current_file_path = (string) args[0];
file_name = (string) current_file_path.Replace(Path.GetDirectoryName(Environment.GetCommandLineArgs()[1]), "");
var browser = new FolderBrowserDialog();
if (browser.ShowDialog()==DialogResult.OK)
{
new_file_path = browser.SelectedPath + file_name;
}else
{
Environment.Exit(1);
}
try
{
File.Move(current_file_path, new_file_path);
}catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
If you bypass the argument check and try to show the FBD in a debugger, with this exact code, you will see System.Threading.ThreadStateException: 'Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.'
As per the error message, this exception won't be raised if no debugger is attached. Put an [STAThread] attribute on your Main method, like you normally see in any windows forms app:
[STAThread]
public static void Main(string[] args)
{
...
I also recommend you add an else for your outer if, to show an error if no arguments are passed (otherwise your app will exit silently

Passing Arguments to another WPF Application doesn't work

i got a problem when passing two arguments from one WPF App to another WPF App.
I publish the second WPF App to my Desktop and i want to start it with my first WPF App.
First-Program:
public MainWindow()
{
InitializeComponent();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"C:\Users\User\Desktop\Work.application";
startInfo.Arguments = "test 1234";
Process.Start(startInfo);
}
To get the arguments in the second program i tried the following code
1.Get Arguments in Mainwindow with Environment.GetCommandLineArgs() => doesn't work
public MainWindowSecondProgram()
{
InitializeComponent();
string[] args = Environment.GetCommandLineArgs();
foreach (String element in args)
{
MessageBox.Show(element);
}
}
2.Get Arguments in App by using startup function => doesn't work
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
foreach (string element in e.Args)
{
MessageBox.Show(element);
}
}
}
Now if i copy the Work.exe (not Work.application) from my Visual Studio Project folder to my Desktop and change the path from
#"C:\Users\User\Desktop\Work.application" to
#"C:\Users\User\Desktop\Work.exe"
and run my first program again, it works perfect with
the first function and the second function.
So why is it working with the EXE but not with the published application?
Edit:
I tested both functions by passing two arguments threw the debugger and it works, but not by passing it to the published application, only EXE works.
For a Windows Store App, you need to use Application.OnLaunched. Try this code:
public partial class App : Application
{
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
MessageBox.Show(args.Arguments);
}
}
Note that you'll have to turn that string into an array yourself.
To read arguments in a ClickOnce application, use:
AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData
You can read more here.
Also, not sure, but you may need to run the ClickOnce app via the .appref-ms shortcut as opposed to the .application file itself.

developer command prompt for VS2013--- " "is not recognized as an internal or external command operable program or batch file

I want to run it with command prompt---CLDemo one two three
using System;
class CLDemo
{
static void Main(string[] args)
{
Console.WriteLine(args.Length );
for(int i=0; i < args.Length; i++)
Console.WriteLine(args[i]);
}
}
Right click on your project in Solution Explorer, select Properties. There, in Debug tab, is a place for entering command line arguments when debugging.
Source: https://msdn.microsoft.com/en-us/library/vstudio/1ktzfy9w(v=vs.100).aspx

Get path+filename of file that was opened with my application

I'm an amateur at c# and I've been unable to locate the answer to this.
Perhaps I am not aware of the correct terms to use.
When a video file is dragged onto my exe application, I would like the application to know that it was launched with a file and be able to know the path and filename of that file. This way, the user does not have to use the file>open menu.
Hope that makes sense.
Thanks
You can check the command line arguments which were used to launch the application.
If your application was started by dropping a file on the .exe file, there will be a single command line argument with the path of the file.
string[] args = System.Environment.GetCommandLineArgs();
if(args.Length == 1)
{
// make sure it is a file and not some other command-line argument
if(System.IO.File.Exists(args[0])
{
string filePath = args[0];
// open file etc.
}
}
As your question title states, you want the path and the file name. You can get the file name using:
System.IO.Path.GetFileName(filePath); // returns file.ext
When you drag a file into a C# application, it will goes as an command-line argument to that application. Like console applications, you can catch it on the Main method on the Program class.
I'll explain it using Windows Forms application.
Open your Program class on the solution. Your program class should look like this.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
By default, when you create Windows Forms applications, they don't treat command line arguments. You have to make a tiny change on the signature of the Main method, so it can receive arguments:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
Now you can handle file name argument passed to the application. By default, Windows will put the file name as the first argument. Just do something like this:
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Before Application.Run method, treat the argument passed.
// I created an overload of the constructor of my Form1, so
// it can receive the File Name and load the file on some TextBox.
string fileName = null;
if (args != null && args.Length > 0)
fileName = args[0];
Application.Run(new Form1(fileName));
}
In case you want to know the constructor overload of my Form1, here it is. Hope it helps!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Form1(string fileName) : this()
{
if (fileName == null)
return;
if (!File.Exists(fileName))
{
MessageBox.Show("Invalid file name.");
return;
}
textBox1.Text = File.ReadAllText(fileName);
}
}
You need your application's command-line arguments. When you drop a file on your application in Explorer, Explorer opens the application with the file you dropped on it. You can select as many files as you want, drop them on your application and using this line of code, files will be an array of those command line arguments.
string[] files = Environment.GetCommandLineArgs();

C# Pass a file via command line

My Programm is supposed to read the file and count the number of vowels and consonants in it. So, the fileName must be passed as a command line argument. This is part of my code:
class FileDetails
{
static void Main(string[] args)
{
Console.WriteLine(args.Length);
foreach (string arg in args)
{
Console.WriteLine(arg);
}
}
}
After compilation of this file, I run it via command line and pass some arguments to the Main function:
C:\Users\StepN\Desktop\FILEDETAILS>filedetails abc def xyz
The result of programm looks like this:
3
abc
def
xyz
So, the root of the problem is that I need to pass as a command line argument the filename, but I don't know, how to do it.
Thanks in advance for any help!
The only problem you can have is file name with white spaces. If your file has name abc def xyz then you should pass it wrapped in double quotes:
C:\Users\StepN\Desktop\FILEDETAILS>filedetails "abc def xyz"
If you are using spaces in one command line argument then enclose it with double quotes. That is how you should give arguments to your executable:
C:\Users\StepN\Desktop\FILEDETAILS>filedetails.exe "C:\file name.txt"
In Code access filename:
class FileDetails
{
static void Main(string[] args)
{
if(args.Length > 0 )
{
string filePath = args[0];
//read the file using System.IO namespace
}
}
}
class Program
{
static void Main(string[] args)
{
if (args.Length == 0){
Console.WriteLine("Please pass command line arguments.");
return;
}
string fileName = args[0];
}
}
There is a way to do.
1) Open Notepad and write your code and save it.
2) MOST IMPORTANT: Open visual studio command prompt and compile the code as follow:
(i) Set current path, where your program is saved.
(ii) Compile it with csc FileName.cs
3) Now execute the program using following command line argument:
(a) FileName arg1 arg2
If you aren't comfortable doing this then create a batch file and pass write your arguments. Then run your .bat file which will trigger your C# program. I mean that this might trigger the .exe in your bin folder.

Categories

Resources