Pass arguments given to an already open instance of the same program - c#

I'm currently learning C#, and I'm trying to make a program that puts an already open instance of it on top but makes it pass the arguments it was given to the open instance before closing.
I understand how to make it close if an instance of it is running already, but is there any way to pass arguments to an already running instance?
The code:
using System;
using System.Windows.Forms;
using System.Web;
namespace foo
{
public static class Program
{
[STAThread]
public static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form form = new Form();
TextBox label = new TextBox();
label.Location = new System.Drawing.Point(0, 0);
label.Size = new System.Drawing.Size(500, 50);
if (args.Length == 0)
{
label.Text = "no args";
} else
{
args[0] = args[0].Substring(4);
if (args[0] == "") {
label.Text = "args are empty";
} else
{
label.Text = HttpUtility.UrlDecode(args[0]);
}
}
form.Controls.Add(label);
Application.Run(form);
}
}
}

If the program is already running, then the short answer is "no", at least - not as exe arguments; you do have some limited options, however:
if your program started it, it can redirect stdin/stdout and use that as a comms channel
otherwise, you're in IPC territory, so: sockets, named pipes, or similar as a comms channel (perhaps using gRPC, WCF or similar so you don't have to deal with all the details)

Related

Run forms Application through command prompt and send commands to it

I have a windows forms tool in VB that i have been working on for a while now.
Now i would like to be able to access all of the controls and return values through the command prompt so that i am able to play with it through Azure and basically make the application a black box.
So this is how i went about thinking i should do it.
1 - In my project, i created a second solution, a C# Windows Command line framework.
2 - i than added the following script to that second project in order to run the win forms
using EnabledTest;
using System;
using System.Windows.Forms;
namespace Command_lineStartup
{
internal class Program
{
private static frmMain MainForm;
[STAThread]
private static void Main(string[] args)
{
if (args.Length > 0)
{
// Command line given, display console
}
else
{
AllocConsole();
ConsoleMain(args);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(MainForm = new frmMain());
GUI();
}
}
private static void ConsoleMain(string[] args)
{
Console.WriteLine("Command line = {0}", Environment.CommandLine);
for (int ix = 0; ix < args.Length; ++ix)
Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
// Console.ReadLine();
}
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
public static void GUI()
{
Console.WriteLine("Testing version 1 :");
Console.WriteLine("Enter Project File path to open, Project must be a .mmp file");
string Path = Console.ReadLine();
MainForm.LoadProject(Path);
}
}
}
However, I do not think this is the right way. When i run the console application through CMD using C:\TFS\Enabled Test\Command-lineStartup\bin\Debug\Command-lineStartup.exe"
I does not behave how i want it to work.
So my question is.
Am i going about this the right way? if so what am i doing wrong here
is there an easier way?
So i found a way in the end. When running the application through CMD, the arguments that are supplied can be accessed using
Dim cla As String() = Environment.GetCommandLineArgs()
then for each of the arguments provided u can do something with it.
For example,
If cla.Length > 1 Then
'cla(0) is the executable path.
'cla(1) is the Path to the project
If Not IsIDE() Then WCLicenseIsLicensed("Application", True)
Me.Text = Application.ProductName
mblnLoaded = True
LoadProject(cla(1))
TreeVieuwSystem.Nodes(cla(2)).Expand()
TreeVieuwSystem.SelectedNode = TreeVieuwSystem.Nodes(cla(2)).Nodes.Find(cla(2) & "\" & cla(3), True).First
NodeSelected()
If cla(2) = "Test Plans" Then
TheWindowThatAllowsYouToEditTheObject.RunTestPlan()
ElseIf cla(2) = "Tests" Then
TheWindowThatAllowsYouToEditTheObject.RunTest(False)
End If
Else

How to use CommandLineParser in a WinForms Project? How to build a custom Help MessageBox?

I'm trying to use the CommandLineParser Library in Version 2.5.0 in a WinForms application.
It works great except for a help screen (MessageBox in that case).
I already figured out that I need to create a own parser and set at least the HelpWriter property to null to create a custom Help Screen.
But when the application is called with --help argument my "Error handler" just get one error instance with a Tag of type CommandLine.ErrorType and a Value of HelpRequestedError
Now how to build the custom Help Screen?
https://github.com/commandlineparser/commandline/wiki/Generating-Help-and-Usage-information
This site suggests to use the Types in CommandLine.Text Namespace but how? There are zero examples how to do it.
Anyone here did something like this?
I have the following code:
namespace myWorkspace
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Forms;
using CommandLine;
using DevExpress.XtraEditors;
using Options;
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
internal static int Main(string[] args)
{
AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = "bin";
WindowsFormsSettings.EnableFormSkins();
WindowsFormsSettings.EnableMdiFormSkins();
WindowsFormsSettings.ForceDirectXPaint();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var parser = new Parser(config =>
{
config.AutoHelp = true;
config.AutoVersion = true;
config.CaseInsensitiveEnumValues = false;
config.CaseSensitive = false;
config.EnableDashDash = true;
config.HelpWriter = null;
config.IgnoreUnknownArguments = true;
//config.MaximumDisplayWidth
config.ParsingCulture = CultureInfo.InvariantCulture;
});
return Parser.Default.ParseArguments<RunOptions>(args)
.MapResult(
RunRunAndReturnExitCode,
RunParsingFailedAndReturnExitCode);
}
private static int RunRunAndReturnExitCode(RunOptions opts)
{
try
{
Application.Run(new MainForm());
}
catch
{
return -1;
}
return 0;
}
private static int RunParsingFailedAndReturnExitCode(IEnumerable<Error> errs)
{
foreach (var err in errs)
{
var locErr = err;
}
return 1;
}
}
}
And on Line var locErr = err; i don't know what to do to get a help screen message i can show in a MessageBox or the like.
CommandLineParser seems to support console output out-of-the-box for help or --help but I have no console app here.
Ok i now figured out a way to do it. Does not seem to be the best way but it works.
I create a StringBuilder instance and put it into a StringWriter instance
private static StringBuilder helpTextBuilder = new StringBuilder();
private static StringWriter helpTextWriter = new StringWriter(helpTextBuilder);
Then I create a new Parser with (at least this) Option(s):
var parser = new Parser(config =>
{
config.HelpWriter = helpTextWriter;
});
In the case of error I can now use what is written into the helpTextBuilder to show a message box.
private static int RunParsingFailedAndReturnExitCode(IEnumerable<Error> errs)
{
MessageBox.Show(helpTextBuilder.ToString());
return 1;
}
So this is now working for me.

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

RaceOnRCWCleanup when running console app for speech recognition

I don't know either we can create a console app or not for speech recognition(searched for the same but didn't find any answer)and tried this code.
I have this code working in winforms app
but when trying to create this app in console visual studio is giving a very strange error mscorelib.pdb not found.And transferring to a page mscorelib.pdb
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Speech;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.Threading;
namespace ConsoleApplication2
{
public class Program
{
public static void Main(string[] args)
{
tester tst = new tester();
tst.DoWorks();
}
}
public class tester
{
SpeechSynthesizer ss = new SpeechSynthesizer();
SpeechRecognitionEngine sre = new SpeechRecognitionEngine();
PromptBuilder pb = new PromptBuilder();
Choices clist = new Choices();
public void DoWorks()
{
clist.Add(new string[] { "how are you", "what is the current time", "open chrome", "hello" });
Grammar gr = new Grammar(new GrammarBuilder(clist));
sre.RequestRecognizerUpdate();
sre.LoadGrammar(gr);
sre.SetInputToDefaultAudioDevice();
sre.SpeechRecognized += sre_recognised;
sre.RecognizeAsync(RecognizeMode.Multiple);
}
public void sre_recognised(object sender, SpeechRecognizedEventArgs e)
{
switch (e.Result.Text.ToString())
{
case "hello":ss.SpeakAsync("Hello shekar");
break;
case "how are you": ss.SpeakAsync("I am fine and what about you");
break;
case "what is the time":ss.SpeakAsync("current time is: " + DateTime.Now.ToString());
break;
case "open chrome":System.Diagnostics.Process.Start("chrome", "wwe.google.com");
break;
default: ss.SpeakAsync("thank you");
break;
}
Console.WriteLine(e.Result.Text.ToString());
}
}
}
here is the snapshot of the error page
I also loaded the given option "Microsoft.symbol.Server", but it is still giving the same output.
EDIT
HERE is the output window
Outputs are of big lengths ,so not being able to show all the outputs ,captured some relevant parts (regret).
You're seeing the debugger issuing a RaceOnRCWCleanup. The reason may be that you are instantiating but not properly cleaning up COM objects created under the hood by SpeechSynthesizer and/or SpeechRecognitionEngine.
At the same time, a Console application is not automatically 'kept alive'. You need to specifically add code to prevent it from exiting immediately.
You need to do 2 things:
Ensure your application stays alive long enough (for example, by adding a Console.ReadLine() statement in the Main method
Make sure that resources are properly cleaned up. Both SpeechRecognitionEngine and SpeechSynthesizer implement IDisposable, so they should be disposed when no longer needed. To do this properly, implement IDisposable in your tester class:
Example:
public class Tester
{
SpeechSynthesizer ss = new SpeechSynthesizer();
SpeechRecognitionEngine sre = new SpeechRecognitionEngine();
public void Dispose()
{
ss.Dispose();
sre.Dispose();
}
}

How do I programmatically close an InfoPath form in C#?

Is it possible to close an InfoPath form programmatically? I know that it can be configured as a form rule / action but I want to close the form via code.
Use the ApplicationClass.XDocuments.Close method and pass it your document object:
using System;
using Microsoft.Office.Interop.InfoPath;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var app = new ApplicationClass();
var uri = #".\form1.xml";
var doc = app.XDocuments.Open(uri, 0);
app.XDocuments.Close(doc);
}
}
}

Categories

Resources