C# Passing Arguments Through Context Menu - c#

so I made a program that creates a registry key on the pc, that adds an option to push your file to your device. (The program itself pushes files to your Android sd card.)
Everything works well, or at least should, once I figure out this issue. When I right-click on an item and choose my command (which is to open up with my program) my program just opens up, but no arguments are passed.
A month ago, I designed a program that opens when the user double clicks (just double click, not right-clicking through context menu) a file, it opened the specific program, and from there I was able to grab the arguments.
Why can't I from the context menu?
Thanks, sorry for lengthy post.
And here's part of my code:
private void Form1_Load(object sender, EventArgs e)
{
string c = textBox3.Text;
string[] args = System.Environment.GetCommandLineArgs();
try
{
string location = args[1];
MessageBox.Show(location);
//For testing purposes only
Properties.Settings.Default.thinglocation = location;
Properties.Settings.Default.Save();
Process();
}
catch
{
}
Here's the registry code. BTw string c is "C:\File push.exe" the location of my program.
string MenuName = "*\\shell\\NewMenuOption";
string Command = "*\\shell\\NewMenuOption\\command";
RegistryKey regmenu = null;
RegistryKey regcmd = null;
try
{
regmenu = Registry.ClassesRoot.CreateSubKey(MenuName);
if (regmenu != null)
regmenu.SetValue("", "Push to Android");
regcmd = Registry.ClassesRoot.CreateSubKey(Command);
if (regcmd != null)
regcmd.SetValue("", c +"%1");
}
catch (Exception ex)
{
MessageBox.Show(this, ex.ToString());
}
finally
{
if (regmenu != null)
regmenu.Close();
if (regcmd != null)
regcmd.Close();

I assume that you have created a registry entry which creates the context menu item which you are using to launch your program. Likelihood is that you need to add ' %1' after the name of the exe you want to launch. In the context menu registry entries %1 represents the selected file, so adding this should launch your program and provide the name of the selected file as the single argument.
the reason why it worked before with the double click is that windows will launch the default program for the file double clicked, with the double clicked file as the argument.

Did you try looking in the sender or the EventArgs parameters? I would think their might be something in there. That's just a guess though. If its just a double click then why would there be any arguments? Maybe I am just misunderstanding that point. Anyways, maybe that helps. If not maybe you could clarify a little bit where the arguments are supposed to come from.
Erik

Related

Can the Help.ShowHelp API be modified to simply invoke the CHM file?

This is my primary way for displaying help topics from within my WinForm button click handlers:
Handler:
private void buttonHelp_Click(object sender, EventArgs e)
{
CutTools.DisplayHelpTopic(this, "create-new-viewport.htm");
}
Base method:
public static void DisplayHelpTopic(Control parent, string topic)
{
try
{
// Use an empty form as the parent so that the help file will not block the CAD software
Form mHelpParent = new Form();
// Use location of this DLL file
System.Reflection.Module mod = parent.GetType().Module;
string path = Path.GetDirectoryName(mod.FullyQualifiedName);
Help.ShowHelp(mHelpParent,
Path.Combine(path, "cut-tools-help.chm"), HelpNavigator.Topic, topic);
}
catch (System.Exception ex)
{
_AcAp.Application.ShowAlertDialog(
string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace));
}
}
The forms are displaid inside AutoCAD, BricsCAD or ZWCAD. The about is fine and great. But if I want to simply display the CHM file itself (so no actual form is available) I have to do this:
[CommandMethod("TS_DisplayHelp")]
public void TS_DisplayHelp()
{
// Use location of this DLL file
System.Reflection.Module mod = GetType().Module;
System.Diagnostics.Process.Start(
Path.Combine(Path.GetDirectoryName(mod.FullyQualifiedName), "cut-tools-help.chm"));
}
It works but has one drawback. It spawns a new instance of the help and does not use the same instance.
For example:
You start one of the other commands and show the help via button click. You cancel.
You start a different command and show the help via button click. Help.ShowHelp uses same instance.
You can command and start help via TS_DISPLAYHELP and it starts new instance.
Given the context of TS_DISPLAYHELP I can't work out how to directly use Help.ShowHelp as I can in my button click handlers.
At the moment I have managed to get around this issue by duplicating the DisplayHelpTopic code directly in the command TS_DISPLAYHELP method:
[CommandMethod("TS_DisplayHelp")]
public void TS_DisplayHelp()
{
try
{
// Use an empty form as the parent so that the help file will not block the CAD software
Form mHelpParent = new Form();
// Use location of this DLL file
System.Reflection.Module mod = GetType().Module;
string path = Path.GetDirectoryName(mod.FullyQualifiedName);
Help.ShowHelp(mHelpParent,
Path.Combine(path, "cut-tools-help.chm"), HelpNavigator.Topic, "command-index.htm");
}
catch (System.Exception ex)
{
_AcAp.Application.ShowAlertDialog(
string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace));
}
}
I know that my default topic is "command-index.htm".
I am happy with the above resolution.

Passing arguments to run application

Looking for help on this project, I am new and might not know all terms so please bare with me.
Project contains multiple winforms panels. Start one is my dashboard then I have others that do specific functions/features. What I need to be able to do is call up the separate winforms from an outside bat file that comes from a third party software (I have no control over them).
So what I would like to do is this programname.exe runs the dashboard programname.exe -a runs a different winform with in my program. I am not sure what this is called to do this.
Any help would be great even if a place to go and look it up.
namespace Versi_Send_Email
{
public partial class DashBoard : Form
{
public DashBoard()
{
InitializeComponent();
}
private void DashBoard_Load(object sender, EventArgs e)
{
INIFile inif = new INIFile(#"c:\test\mailsettings.ini");
sitetxtbox.Text = inif.Read("Properties", "site");
emailtotxtbox.Text = inif.Read("Properties", "personto");
cctotxtbox.Text = inif.Read("Properties", "ccto");
bcctextbox.Text = inif.Read("Properties", "bcto");
}
This could be a switch statement or a simple if-else statement. In WinForms application and in the main form loaded event, you can read the command line arguments like this
string[] args = Environment.GetCommandLineArgs();
foreach(string arg in args){
if (arg=="EmployeeForm")
{
EmployeeForm.ShowDialog()
else if (arg=="Department")
Department.ShowDialog()
}
//after all arguments are read, you can simply kill the application and main window will never appear
Application.Current.Shutdown();
return;

Storing value from try for use in second try C#

Good day fellow helpers, i have following problem:
(running MS Visual Community Edition 2015)
private void button4_Click(object sender, EventArgs e) // Senden
{
serialPort2.WriteLine("SR,00,002\r\n");
textBox1.Text = "gesendet";
textBox3.Text = "";
try
{
System.IO.StreamReader file = new System.IO.StreamReader("C:\\blub.txt");
String line = file.ReadToEnd();
string Hallo = line; \\in the beginning there is "0" in the file
file.Close();
decimal counter = Convert.ToDecimal(Hallo); \\just for testing
counter++;
string b = serialPort2.ReadLine();
string[] b1 = Regex.Split(b, "SR,00,002,"); \\cuts off unwanted input from device
decimal b2 = decimal.Parse(b1[1]); \\number like -3000
System.IO.StreamWriter test = new System.IO.StreamWriter("C:\\blub.txt");
test.WriteLine(counter);
test.Close();
textBox7.Text = "Das ist counter:" + counter;
}
catch (TimeoutException)
{
textBox3.Text = "Timeout";
throw;
}
}
Now, the Serialport is a device that returns a lengthmeasurment. As it is a bit weird, or just the way its build it start with a negitve number (between -5000 and -3370). Now as i want to get measurement on the screen that is realistic i want to set the value to 0 and calculate the difference.
Means: I start the programm - press send - get a value (say -3000) - press send again (after pushing the seonsor in) and get the value that its been pushed in > 0 by adding the difference to 0.
I only learned to store values externally when i had a C course a year back like i did within my programm. Is there a way to store the value from the first measurement in the programm so i can use it on the next send/try?
The counter was just for testing and I would exchange it for the "decimal b2"
I hope there is an easy fix for that, not really a pro with C# yet but i'm eager to learn. I thank the willing helpers in advance, MfG, Chris
OK, I will simplify this in order to show concept so it will not have all the code you are actually using.
So, what you want is to click on button, get some values and store them for next click.
Value is stored in variable. If you have variable in function that is handler for click event, as soon as function completes execution, value will be destroyed.
So, what you need is to create variable in outer scope (class level). Your function is already in class of the form so let's get to code:
class Form1
{
string BetweenClickStorage;
private void button4_Click(object sender, EventArgs e)
{
//Load data here
BetweenClickStorage = LoadedData;
}
}
After this, when you click again on the button, value will still be in BetweenClickStorage. It will be also available to all other buttons click handlers and other code in that form.
If I'm understanding your question correctly, the answer is simply to declare a variable outside the try/catch:
//declare variable //
var measurement;
// TRY #1 //
try
{
//assign value to the variable here
}
catch
{
}
// TRY #2 //
try
{
// reference variable here
}
catch
{
}

C# Process.start opening multiple PDFs unexpectedly

I have a program that scans in document bar codes and then allows for the user to click on a link which will open up a PDF associated with that bar code. My program works fine however I am running into a bug(?) in my code where every so often instead of opening the PDF once, the system will open it multiple times (5+) and it doesn't seem to be consistent. I'm hesitant to rewrite the code completely since it is actually working, it is simply inconvenient to have to close multiple windows. The method that I believe is causing the problem is below. Any help would be greatly appreciated as I am not sure where to start.
private void dgDisplay_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
id = (int)comboBox1.SelectedValue;
string ImagePath = getImagePath(id);
string filename = "";
if (e.ColumnIndex == 1)
{
filename = dgDisplay[e.ColumnIndex, e.RowIndex].Value.ToString();
filename = #ImagePath + filename + ".tif";
if (File.Exists(filename))
{
Process.Start(filename);
}
else
{
MessageBox.Show(filename);
}
}
}

C# Settings.Default.Save() not saving? [duplicate]

This question already has answers here:
Why are my application settings not getting persisted?
(5 answers)
Closed 5 years ago.
this bug is pretty unusual. Basically my code will change the Settings.Default.Example then save and restart the program. Then when it loads, it shows a message box. However oddly, it shows a empty value when the form loads.
Here is my code:
Main.cs
private void Button1_Click(object sender, EventArgs e)
{
Settings.Default.Example = "Somevalue"; //Sets a value to the settings
Settings.Default.Save(); // Save it
MessageBox.Show(Settings.Default.Example); //Confirming it has been saved
Application.Restart();
}
private void Main_Load(object sender, EventArgs e)
{
MessageBox.Show(Settings.Default.Example); // Here is the weird part, it shows empty.
}
The MessageBox will show "Somevalue" when the button was clicked then the applcation restarts and the MessageBox that showed was empty. However repeating the process by clicking the button once more and restarting it does show the "Somevalue" MessageBox. Please help! Many Thanks!
Maybe you ran the same mistake as I did: setting the setting's scope to Application. Those kind of settings are not saved.
Set it to User to solve the problem.
rene is correct - you need to call Default.Reload after calling the Save method:
Settings.Default.Save();
Settings.Default.Reload();
Possibly a bug - ?
Posting as a reply to increase visibility -
If your AssemblyInfo.cs file has a * in Assembly Version then it's refreshing the file every build so you won't see persistence or reliability until you change that to a hard number and rebuild all, then retest everything.
After a full day of researching and studying the subject, I was able to solve this by putting the Configuration to the user:
Using System.Configuration;
Properties.Settings.Default.strinconn = txt_stringconn.Text;
Properties.Settings.Default.Save ();
Properties.Settings.Default.Upgrade ();
MessageBox.Show ("Saved Settings");
Application.Restart ();
Using Visual Studio 2013 - there is nothing I could do to make it work reliably, I would call Save and it did not save.
Save and then immediately Reload and it still would not retain the values on subsequent runs (probably related to when I stopped debugging could not identify the root cause) - very frustrating, likely there is an underlying bug but I cannot prove it.
To avoid getting crazy with this I decided to use the registry - the most fundamental way to keep app settings for an app.
Recommended for you all. Here is the code:
public static class RegistrySettings
{
private static RegistryKey baseRegistryKey = Registry.CurrentUser;
private static string _SubKey = string.Empty;
public static string SubRoot
{
set
{ _SubKey = value; }
}
public static string Read(string KeyName, string DefaultValue)
{
// Opening the registry key
RegistryKey rk = baseRegistryKey;
// Open a subKey as read-only
RegistryKey sk1 = rk.OpenSubKey(_SubKey);
// If the RegistrySubKey doesn't exist return default value
if (sk1 == null)
{
return DefaultValue;
}
else
{
try
{
// If the RegistryKey exists I get its value
// or null is returned.
return (string)sk1.GetValue(KeyName);
}
catch (Exception e)
{
ShowErrorMessage(e, String.Format("Reading registry {0}", KeyName.ToUpper()));
return null;
}
}
}
public static bool Write(string KeyName, object Value)
{
try
{
// Setting
RegistryKey rk = baseRegistryKey;
// I have to use CreateSubKey
// (create or open it if already exits),
// 'cause OpenSubKey open a subKey as read-only
RegistryKey sk1 = rk.CreateSubKey(_SubKey);
// Save the value
sk1.SetValue(KeyName, Value);
return true;
}
catch (Exception e)
{
ShowErrorMessage(e, String.Format("Writing registry {0}", KeyName.ToUpper()));
return false;
}
}
private static void ShowErrorMessage(Exception e, string Title)
{
if (ShowError == true)
MessageBox.Show(e.Message,
Title
, MessageBoxButtons.OK
, MessageBoxIcon.Error);
}
}
Usage:
private void LoadDefaults()
{
RegistrySettings.SubRoot = "Software\\Company\\App";
textBoxInputFile.Text = RegistrySettings.Read("InputFileName");
}
private void SaveDefaults()
{
RegistrySettings.SubRoot = "Software\\Company\\App";
RegistrySettings.Write("InputFileName", textBoxInputFile.Text);
}
Beware of calling
Settings.Default.Reload();
after each
Settings.Default.Save();
Save() function actually saves your changes to the file but it is not reflected to your running code. Thus, your code keeps the copy of the previous version of the file.
When you call Save() at another location in your code, it writes over your first change, effectively reverting your first change back to original value.
Very hard to pin down even when debugging.
Please have a look at this Question
Especially, try out the following code from an answer there:
using System.Configuration; // Add a reference to System.Configuration.dll
...
var path = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath;
Also, check out this overview, perhaps you ran into some limitation which is not easy to tell from your question.
This codeproject article might be of some help.
did you try calling ConfigurationManager.RefreshSection before checking that it got saved ad you could try it again after the reload
If you need to test your application how actually working in this case better to run the exe file. When you run on visual studio on debug mode when those settings saving it will take some time. Go to debug folder and run the exe you will get the messages as expected.
I had the same problem.
To sort out the problem.
Go to the custom class in Visual Studio.
Open the class and Check whether the constructor method.
If you have a constructor method, it should be parameterless.
If you have a constructor with parameters, don;t worry. Create another constructor class without an parameters.
Repeat this for all sub classes within the class.
Rebuild and run. Now your settings should save.

Categories

Resources