Passing parameters from one app to the other - c#

Following on from this thread Starting application before target application
I have an application which gets passed a parameter (a filename) and does some registry work before opening Microsoft InfoPath.
I need to open InfoPath with the parameter that was passed to the original application.
Here is how I open InfoPath
System.Diagnostics.Process prc = new System.Diagnostics.Process();
prc.StartInfo.Arguments = ConvertArrayToString(Constants.Arguments);
//prc.StartInfo.Arguments = "hello";
prc.StartInfo.FileName = Constants.PathToInfoPath;
prc.Start();
Note that when I set the Arguments to "hello" InfoPath pops up a message saying cannot find file "hello" however when I set it Constants.Arguments I get an error and Windows asks me if I want to debug or close the applicatiion.
Here is how I set Constants.Arguments in the Main(string[] args)
static void Main(string[] args)
{
Constants.Arguments = args;
//...
}
And here is ConvertArrayToString
private string ConvertArrayToString(string[] arr)
{
string rtn = "";
foreach (string s in arr)
{
rtn += s;
}
return rtn;
}
I suppose the format of the parameter is causing the error, any idea why?
The value of Arguments after being stringed is
c:\users\accountname\Desktop\HSE-000403.xml
Edit:
Thanks to N K's answer.
The issue is in order for my application to open when InfoPath files are opened, I have changed the name of INFOPATH.EXE to INFOPATH0.EXE and my application is called INFOPATH.EXE and is in the InfoPath folder, so when files are opened my application opens.
Now when I do not change the name (eg I leave it as INFOPATH.EXE) it works as expected, however if it is called anything other than that then I get the error.
Unfortunately I need my application to open first.

I tried the below and it's works fine. Let me know what you get with this. (Don't forget to change path to files)
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Process prc = new System.Diagnostics.Process();
prc.StartInfo.Arguments = string.Join("", Constants.Arguments);
prc.StartInfo.FileName = Constants.PathToInfoPath;
prc.Start();
}
}
public class Constants
{
public static string PathToInfoPath = #"C:\Program Files (x86)\Microsoft Office\Office14\INFOPATH.EXE";
public static string[] Arguments = new string[] { #"c:\users\accountname\Desktop\HSE-000403.xml" };
}

Related

Multiple command line inputs

I am having a bit of trouble running multiple conditions through a command line argument. I have a program that makes XML files based on information found in Excel files. The main issue i am having is that when i run the program through an auto scheduling tool it reads each file as a one whole string, instead of "File 1" "File 2" it is reading it as "File1File2". This is the code for the command line:
public static void Main(string[] args)
{
string input = "";
string output = "";
if (args.Length > 0)
{
foreach (string s in args)
{
Console.WriteLine(s);
}
input = args[0];
output = args[1];
}
}
I wondered if there was a way, im aware of methods such as split string but the implementation is what i am fuzzy on

Set a process name in C#

I write an application that starts a 3rd party program that downloads a media stream from a tv channel on my program. The program I am using is rtmpdump.exe. They run as independent processes like this:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = path + rtmpdump;
startInfo.Arguments = rtmpdump_argument;
startInfo.WorkingDirectory = path;
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
Process p = Process.Start(startInfo);
But I would like to name these processes, so if my program crashes or has to be restarted, then I can check the names of the current processes to see if for example there is one called "BBC World - News at 7". Something like that to identify which has already been started and is currently running. Is it possible? I can't find a way to set a friendly name.
Extending what Alexei said - you could create a Dictionary< int, string > to keep track of the process ID / descriptive name that you create. Maybe you should write this out to a file in case your program crashes - but you'd need some special startup handling to deal with processes exiting.
On startup you'd want to read in the file, and check current processes to see if they match with what you have, and remove any processes that no longer exist (wrong process id or exe name). You might want to do that every time you create a new process and write to the file.
You can't change process names, but instead you can:
use Process.Id to identify processes (Id: "...system-generated unique identifier of the process...")
get process command line and see if there anything interesting (may need some PInvoke / WMI for that - How to read command line arguments of another process in C#?).
Here is some code that you could use.
public class ProcessTracker {
public Dictionary<int, string> Processes { get; set; }
public ProcessTracker() {
Processes = new Dictionary<int, string>();
}
public void AddProcess(Process process, string name) {
Processes.Add(process.Id, name);
}
//Check if what processes are still open after crash.
public void UpdateProcesses() {
List<Process> runningProcesses =
Process.GetProcesses().ToList();
Processes = Processes
.Where(pair => runningProcesses
.Any(process => process.Id == pair.Key))
.ToDictionary(pair => pair.Key, pair => pair.Value);
}
//Use this to see if you have to restart a process.
public bool HasProcess(string name) {
return Processes.Any(pair => pair.Value != name);
}
//Write the file on crash.
public void ReadFile(string path) {
if (!(new FileInfo(path).Exists))
return;
using (StreamReader reader = new StreamReader(path)) {
foreach (string line in reader.ReadToEnd()
.Split(new[] {"\n"}, StringSplitOptions.RemoveEmptyEntries)) {
string[] keyPair = line.Split(',');
Processes.Add(int.Parse(keyPair[0]), keyPair[1]);
}
}
}
//Read the file on startup.
public void SaveFile(string path) {
using (StreamWriter writer = new StreamWriter(path, false)) {
foreach (KeyValuePair<int, string> process in Processes) {
writer.WriteLine("{0},{1}",
process.Key, process.Value);
}
}
}
}
Writing the process information to a file (or a memory mapped file) might be the way to go;
However, you could also look into windows messaging. i.e. send a message to each process; and have them reply with their "internal name".
Basically you have everything listen in on that queue; You first send a command that orders the other process to report their internal name, which they then dump into the message queue along with their own process id;
See MSMQ
I had the same question to myself, for my solution created a new class -
MyProcess which inherits from Process and added a property - ProcessId.
In my case I store the ProcessId on a db which is acossiated to other data. Based on the status of the other data I decide to kill the process.
Then I store process on a dictionary which can be passed to other classes if needed where can be access to kill a process.
So when I decide to kill a process, I pull the process from the dictionary by ProcessId and then kill it.
Sample below:
public class Program
{
private static Dictionary<string, MyProcess> _processes;
private static void Main()
{
// can store this to file or db
var processId = Guid.NewGuid().ToString();
var myProcess = new MyProcess
{
StartInfo = { FileName = #"C:\HelloWorld.exe" },
ProcessId = processId
};
_processes = new Dictionary<string, MyProcess> {{processId, myProcess}};
myProcess.Start();
Thread.Sleep(5000);
// read id from file or db or another
var pr = _processes[processId];
pr.Kill();
Console.ReadKey();
}
}
public class MyProcess : Process
{
public string ProcessId { get; set; }
}

Running C# with batch parameters

In java you can pass parameters to the program through batch. How can I do that in C#?
Like if I needed the program to receive a file name how can I get it to the program?
Supposing you have created a C# console application (exe), it will be created with a main static method that receives an array of strings. Those strings will be the arguments passed to the program.
For example:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(string.Join("\n", args));
}
}
If your console application is named "MyApp.exe", you could pass parameters is this way:
MyApp.exe "first arg" second
And you should get this output:
The Main() routine in your application receives an array of strings which contain the arguments which were passed in on the command line.
static void Main(string[] args)
{
foreach (string s in args)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
Outside of Main you can use Environment.GetCommandLineArgs().
string[] args = Environment.GetCommandLineArgs();
If you are trying to read the output from *.bat files this will help you..`
Process thisProcess = new Process();
thisProcess.StartInfo.CreateNoWindow = true;
thisProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
thisProcess.StartInfo.WorkingDirectory = #"C:\Users\My User Name\Documents";
thisProcess.StartInfo.FileName = "ipconfig";
thisProcess.StartInfo.Arguments = "/h";
thisProcess.StartInfo.UseShellExecute = false;
thisProcess.StartInfo.RedirectStandardOutput = true;
thisProcess.Start();
thisProcess.WaitForExit();
//Output from the batch file
string myOutput = thisProcess.StandardOutput.ReadToEnd();

Getting an index outside bound of an array in C#

This program is supposed to show the path of a directory and the directory if its exists then it should also show the files inside with the following extensions (i.e .doc, .pdf, .jpg, .jpeg) but I'm getting an error
*Index was outside the bounds of the array.
on this line of code
string directoryPath = args[0];
This is the code in the main function
class Program
{
static void Main(string[] args)
{
string directoryPath = args[0];
string[] filesList, filesListTmp;
IFileOperation[] opList = { new FileProcNameAfter10(),
new FileProcEnc(),
new FileProcByExt("jpeg"),
new FileProcByExt("jpg"),
new FileProcByExt("doc"),
new FileProcByExt("pdf"),
new FileProcByExt("djvu")
};
if (Directory.Exists(directoryPath))
{
filesList = Directory.GetFiles(directoryPath);
while (true)
{
Thread.Sleep(500);
filesListTmp = Directory.GetFiles(directoryPath);
foreach (var elem in Enumerable.Except<string>(filesListTmp, filesList))
{
Console.WriteLine(elem);
foreach (var op in opList)
{
if (op.Accept(elem)) op.Process(elem);
}
}
filesList = filesListTmp;
if (Console.KeyAvailable == true && Console.ReadKey(true).Key == ConsoleKey.Escape) break;
}
}
else
{
Console.WriteLine("There is no such directory.");
}
}
}
How can I handle this error it seems to be common but it happens id different ways
You need to pass the necessary arguments to the program when running it. You can either do this by running the program from the command line, or else when running Visual Studio by doing the following:
Right click on project
Properties
Debug tag
Enter arguments under Start Options -> Command line arguments
You might want to pass the arguments into the program from command line.
like this:
> yourProgram.exe directoryName
Also, to avoid such problems in the code,
if(args.Length > 0){
string directoryPath = args[0];
}else{
//print a help message and exit, or do something like set the
//default directoryPath to current directory
}
Do you want the user to enter a path when the program starts or when they start the program? If it's the first, then you should add a Console.Read() method that asks for the path.
If it's the latter, then you need to pass the path as an argument when starting the program. You should also do a check against the args array before reading from it to check that it contains data and that data is a valid path.
Something like:
if(args.Length > 0 && Directory.Exists(args[0]))
{
// Do Something.
}

How do you open a local html file in a web browser when the path contains an url fragment

I am trying to open a web browser via the following methods. However, when the browser opens the url / file path, the fragment piece gets mangled (from "#anchorName" to "%23anchorName") which does not seem to get processed. So basically, the file opens but does not jump to the appropriate location in the document. Does anyone know how to open the file and have the fragment processed? Any help on this would be greatly appreciated.
an example path to open would be "c:\MyFile.Html#middle"
// calls out to the registry to get the default browser
private static string GetDefaultBrowserPath()
{
string key = #"HTTP\shell\open\command";
using(RegistryKey registrykey = Registry.ClassesRoot.OpenSubKey(key, false))
{
return ((string)registrykey.GetValue(null, null)).Split('"')[1];
}
}
// creates a process and passes the url as an argument to the process
private static void Navigate(string url)
{
Process p = new Process();
p.StartInfo.FileName = GetDefaultBrowserPath();
p.StartInfo.Arguments = url;
p.Start();
}
Thanks to all that tried to help me with this issue. I have since found a solution that works. I have posted it below. All you need to do is call navigate with a local file path containing a fragment. Cheers!
private static string GetDefaultBrowserPath()
{
string key = #"HTTP\shell\open\command";
using(RegistryKey registrykey = Registry.ClassesRoot.OpenSubKey(key, false))
{
return ((string)registrykey.GetValue(null, null)).Split('"')[1];
}
}
private static void Navigate(string url)
{
Process.Start(GetDefaultBrowserPath(), "file:///{0}".FormatWith(url));
}
All you need is:
System.Diagnostics.Process.Start(url);
Try relying on the system to resolve things correctly:
static void Main(string[] args)
{
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = "http://stackoverflow.com/questions/tagged/c%23?sort=newest&pagesize=50";
p.StartInfo.Verb = "Open";
p.Start();
}
I am not a C# programmer, but in PHP I would do a urlencode. When I did a Google search on C# and urlencode it gave this page here at StackOverflow... url encoding using C#

Categories