FolderBrowserDialog crashes the application - c#

Whenever I call folderbrowserdialog.showDialog() my application crashes.
I'm using the code that worked before for me, so it CAN NOT be the code.
try
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.RootFolder = Environment.SpecialFolder.Desktop;
if (fbd.ShowDialog() == DialogResult.OK)
{
// this.Minecraft.Text = fbd.SelectedPath;
}
}
catch
{
}
It does not throw any error, no exception, there just pops up the little loading circle, then the app is gone, I noticed it with a different .NET app before too!
btw: will reinstalling .net 4 work?

Try adding this to your application (at the start of the Main() method, preferably). See if the exceptions.txt file has any exceptions logged into it when you reach your freezing point.
AppDomain.CurrentDomain.FirstChanceException += (sender, e) =>
{
if ((e == null) || (e.Exception == null))
{
return;
}
using (var sw = File.AppendText(#".\exceptions.txt"))
{
sw.WriteLine(e.ExceptionObject);
}
};
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
if ((e == null) || (e.ExceptionObject == null))
{
return;
}
using (var sw = File.AppendText(#".\exceptions.txt"))
{
sw.WriteLine(e.ExceptionObject);
}
};

I had just the same problem with FolderBrowserDialog and found the source of evilness. Comment / uncomment [STAThread] and see the difference:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
//[STAThread]
static void Main()
{
new FolderBrowserDialog().ShowDialog();
}
}
}

Another thing that you should know about FolderBrowserDialog, SaveFileDialog, OpenFileDialog is that they don't work if you "Disable visual themes" on the compatibility tab from the executable file properties.

Hope this helps somebody - i actually had this problem, and turns out I had accidentally assigned a DialogResult to the button that was launching by FolderBrowserDialog! Therefore, whenever the code was finished executing, it was returning the DialogResult of 'Cancel' to the CLR and terminating my program. Check the 'DialogResult' property in Visual Studio for the button you have assigned to open the dialog - make sure it is set to None.

Related

C# Trying to make another form open when a certain application is open

Here is my code below
using System.Diagnostics;
while (Process.GetProcessesByName("Your Program").Length == 0);
{
if (Checkbox.Checked)
{
form2.Visible = true;
}
else
{
form2.Visible = false;
}
}
My problem is when "Your Program" is not open and the checkbox is checked it does not check and causes the application to freeze. I want the program to be able to check/uncheck regardless but only open the second form when the program is running.
Another problem I had was when "Your Program" was closed the form would still show which caused more issues like trying to uncheck the checkbox but ultimately leading to more freezing of the program until I had to kill it.
Here is my solution this seemed to work a lot better then the while loop
Process[] pname = Process.GetProcessesByName("Your Program");
if (!checkbox.Checked || (pname.Length == 0))
{
form2.Visible = false;
}
else
{
form2.Visible = true;
}
Doing this removed the error I had which works wonders for my code. Hopefully this helps someone and thanks everyone for your help :)

Unable to handle a button click event in SAP B1 UI API

I'm starting with SAP B1 UI API (9.0) and I'm trying to handle a button click without any luck so far. This is how I'm doing it (removing unnecessary to make it shorter):
static void Main(string[] args)
{
SetApplication(args);
var cParams = (FormCreationParams)App.CreateObject(BoCreatableObjectType.cot_FormCreationParams);
cParams.UniqueID = "MainForm_";
cParams.BorderStyle = BoFormBorderStyle.fbs_Sizable;
_form = App.Forms.AddEx(cParams);
/*Setting form's title, left, top, width and height*/
// Button
var item = _form.Items.Add("BtnClickMe", BoFormItemTypes.it_BUTTON);
/*Setting button's left, top, width and height*/
var btn = (Button)item.Specific;
btn.Caption = "Click Me";
_form.VisibleEx = true;
App.ItemEvent += new _IApplicationEvents_ItemEventEventHandler(App_ItemEvent);
}
private static void SetApplication(string[] args)
{
string connectionString = args[0];
int appId = -1;
try
{
var guiApi = new SboGuiApi();
guiApi.Connect(connectionString);
App = guiApi.GetApplication(appId);
}
catch (Exception e)
{ /*Notify error and exit*/ }
}
private static void App_ItemEvent(string FormUID, ref ItemEvent pVal, out bool BubbleEvent)
{
BubbleEvent = true;
if (FormUID == "MainForm_" && pVal.EventType == BoEventTypes.et_CLICK &&
pVal.BeforeAction && pVal.ItemUID == "BtnClickMe")
{
App.MessageBox("You just click on me!");
}
}
When I click the button nothing happens, is this the way to go? I've made so many variations in the handler method but nothing yet. Another detail is that the visual studio's debugger terminates as soon as the addon is started (maybe this has something to do with my problem).
I hope you can help me. Thanks in advance.
David.
Since the application stops running there are two possible answers to this question depending on what you prefer to use.
If you are using the SAPbouiCOM library you need a way to keep the application running, the way I use is the System.Windows.Forms.Application.Run(); from the windows forms assembly.
If you are using the SAPBusinessOneSDK and SAPbouiCOM.Framework as a reference you can use the App.Run();.
Both of these need to be invoked as soon as your setup code has run.

How to know the input buffer of the serial port has information, in C#?

I am building a program in C# to be used in one of my course at a college to demonstrate how Asynchronous connections work using RS-232 and two computers connected together. My course is not about programming, but data networks, so the connectivity is what I am looking for.
picture 1 - sample layout of GUI using Visual Studio 2015
One of the features I want to implement in my program is to show how a Master-slave, simplex connection works (i.e. the program can choose between been a master to send input from the keyboard; or slave to only receive information and print it on a textbox).
What I have already is the capability of initializing the serial port with specific characteristics (baud rate, data bits, stop bits, etc). This features are selected using combo boxes from the GUI, and assigned to the port when the user clicks a button to "open the port".
What I don't know is how to create the "slave" part of the program. My idea of what I could do is, after you choose the program to be "slave", you open the port waiting for some sort of flag or event to trigger when the input buffer has data stored.
I've been reading several forums and I can't find anything similar to what I need. I have, however, tested multiple alternatives that I believed would bring me closer to what I need with little to no result. I come to ask for an idea of what I could be doing wrong, or suggestions on how to tackle this problem. The problematic lines are bolded (or 2 stars ( * ) ):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialCommTester
{
public partial class frmSerialComm : Form
{
static SerialPort _PuertoSerial;
public frmSerialComm()
{
InitializeComponent();
getAvailablePorts();
}
//---------------------------------my functions--------------------------------------
void getAvailablePorts()
{
string[] ports = SerialPort.GetPortNames();
cmbPortList.Items.AddRange(ports);
}
void activatePort()
{
//Note that all the combo boxes are named somewhat accordingly to what the information they are meant to display.
if (cmbPortList.Text != "" && cmbBaudRate.Text != "" && cmbParity.Text != "" && cmbStopBits.Text != "")
{
_PuertoSerial.PortName = cmbPortList.Text;
_PuertoSerial.BaudRate = Convert.ToInt32(cmbBaudRate.Text);
_PuertoSerial.RtsEnable = true;
_PuertoSerial.DtrEnable = true;
_PuertoSerial.DataBits = Convert.ToInt32(cmbDataBits.Text);
if (cmbParity.Text == "Even") { _PuertoSerial.Parity = Parity.Even; }
else if (cmbParity.Text == "Odd") { _PuertoSerial.Parity = Parity.Odd; }
else if (cmbParity.Text == "Space") { _PuertoSerial.Parity = Parity.Space; }
else if (cmbParity.Text == "Mark") { _PuertoSerial.Parity = Parity.Mark; }
else { _PuertoSerial.Parity = Parity.None; }
if (cmbStopBits.Text =="2") { _PuertoSerial.StopBits = StopBits.Two; }
else if (cmbStopBits.Text == "1.5") { _PuertoSerial.StopBits = StopBits.OnePointFive; }
else { _PuertoSerial.StopBits = StopBits.One; }
if (cmbHandShake.Text == "Software Flow Control") { _PuertoSerial.Handshake = Handshake.XOnXOff; }
else if (cmbHandShake.Text == "Hardware Flow Control") { _PuertoSerial.Handshake = Handshake.RequestToSend; }
else { _PuertoSerial.Handshake = Handshake.None; }
_PuertoSerial.ReadTimeout = 500;
_PuertoSerial.WriteTimeout = 500;
_PuertoSerial.Open();
//in my understanding, this line of code is needed to handle data being received. Does it trigger a flag or something?
**_PuertoSerial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);**
}
else
{
txtRecieve.Text = "Input selection missing 1 or more characteristics";
}
}
**
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort testing = (SerialPort)sender;
txtRecieve.AppendText(testing.ReadExisting()); //txtRecieve cannot be reached within this function. It indicates the following error: "An object reference is required for the non-static field, method, or property 'frmSerialComm.txtRecieve'
}
**
void enableDisableGUI(bool[] input)
{
grpConnection.Enabled = input[0];
grpCharacteristics.Enabled = input[1];
btnOpenPort.Enabled = input[2];
btnClosePort.Enabled = input[3];
txtSend.Enabled = ((cmbControlMasterSlave.Text == "Slave") ? false : true);
}
//----------------------------C# objects / functions--------------------------------------
private void btnOpenPort_Click(object sender, EventArgs e)
{
try
{
_PuertoSerial = new SerialPort();
activatePort();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Message ", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
bool[] format = { false, false, false, true};
enableDisableGUI(format);
}
private void btnClosePort_Click(object sender, EventArgs e)
{
_PuertoSerial.Close();
bool[] format = { true, true, true, false};
enableDisableGUI(format);
}
private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
{
_PuertoSerial.Write(e.KeyChar.ToString()); //this is how I send data through the serial port.
}
private void btnClearTxts_Click(object sender, EventArgs e)
{
txtRecieve.Clear();
txtSend.Clear();
}
} //class closes
} //program closes
I am not an experienced programmer, I just want to create something useful for my students. Any constructive criticism will be highly appreciated.
I don't have any definitive answers for you. You code looks like it should provide what you need once you get past the two possible glitches.
I think you should attach your SerialDataReceivedEventHandler BEFORE
you call _PuertoSerial.Open().
It may have no effect since event handlers can normally be enabled/disabled dynamically, but I base the advice on the following comment taken from the .Net source code for SerialPort on MSDN.
// all the magic happens in the call to the instance's .Open() method.
// Internally, the SerialStream constructor opens the file handle, sets the device control block and associated Win32 structures, and begins the event-watching cycle.
The "object reference" error might be resolved by removing the
static modifier from your DataReceivedHandler. If not, or if that
static modifier is necessary for some reason, then perhaps the
txtRecieve control has a private modifier which needs to be changed
to internal or public. You should be able to use Visual Studio in
debug mode to step into the InitializeComponent() method and see
where txtRecieve is being instantiated.
Well, I believe that I needed to read more. This is how I solved the problem (if this is not the real solution, at least is working for now):
I moved the "SerialDataReceivedEventHandler" line before the _PuertoSerial.open();
I followed the suggestions from this article:
https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(EHInvalidOperation.WinForms.IllegalCrossThreadCall);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
So my funtions (one existings + a new one) look like this:
void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
printReceivedText(_PuertoSerial.ReadExisting());
}
private void printReceivedText(string text)
{
if (this.txtSend.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(printReceivedText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtRecieve.AppendText(text);
_PuertoSerial.DiscardInBuffer();
}
}
For now seems to be working fine. The final testing will come when I connect another terminal and see the program interacting with each other.

Opening an exe(windows app) as modal while opening an office document from hard drive

I have an requirement if the user open any office document from his/her hard drive it's should open an an exe(win form application) as a modal window to capture details about the document.
For that I have developed an console app which runs under the client machine, to monitor if any office document file is opening or not. Please find the below code
static void Main(string[] args)
{
var UIAEventHandler = new AutomationEventHandler(OnUIAEvent);
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement,
TreeScope.Children, UIAEventHandler);
Console.ReadLine();
Automation.RemoveAllEventHandlers();
}
public static void OnUIAEvent(object src, AutomationEventArgs args)
{
AutomationElement element;
try
{
element = src as AutomationElement;
}
catch
{
return;
}
string name = "";
if (element == null)
name = "null";
else
{
name = element.GetCurrentPropertyValue(
AutomationElement.NameProperty) as string;
}
if (name.Length == 0) name = "< NoName >";
string guid = Guid.NewGuid().ToString("N");
string str = string.Format("{0} : {1}", name, args.EventId.Id);
if ((element.Current.ClassName.Equals("XLMAIN", StringComparison.InvariantCultureIgnoreCase) == true && name.Contains(".xlsx")) || (element.Current.ClassName.Equals("OpusApp", StringComparison.InvariantCultureIgnoreCase) == true && name.Contains(".docx")))
{
Process.Start(#"E:\experiment\TestingWindowsService\UserInfomation\bin\Debug\UserInfomation.exe", element.Current.Name);
//Automation.AddAutomationEventHandler(
// WindowPattern.WindowClosedEvent,
// element, TreeScope.Element, (s, e) => UIAEventHandler1(s, e, guid, name));
Console.WriteLine(guid + " : " + name);
// Environment.Exit(1234);
}
}
if you see in the OnUIAEvent event handler I am using Process.Start to open an exe.It's working as expected. But I want the exe should open as modal to the opened document.The below code is the form load of the exe.
private void Form1_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.CenterToScreen();
}
Is it possible to open the windows application to open as modal to the opened document?
Unless the external application has been coded taken into account your requirement, it will be difficult.
If you have access to the code (which you seem to have), you can include the Form in your console application (see here how to run a winform from console application?).
The easiest option is to start a windows forms project, then change
the output-type to Console Application. Alternatively, just add a
reference to System.Windows.Forms.dll, and start coding:
using System.Windows.Forms;
[STAThread] static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form()); // or whatever
}
The important bit is the [STAThread] on your Main() method, required for full COM support.
You can override the Creator, and add parameters matching the document, or whatever you need to log/monitor.

Making the second and third OpenFileDialog appear above the console in .NET/C#?

I'm writing a console program that can accept 1 to 3 files. I'm using OpenFileDialog three times to accept the files, but the second and third time the file dialog is behind the console window, making it hard to notice. Any way to get it to appear above?
An image of the problem:
The relevant code is:
static bool loadFile(ref List<string> ls)
{
OpenFileDialog f = new OpenFileDialog();
if (f.ShowDialog() == DialogResult.OK)
{
Console.WriteLine("Loaded file {0}", f.FileName);
ls.Add(f.FileName);
return true;
}
else
{
return false;
}
}
[STAThread]
static void Main(string[] args)
{
// sanity check
if (args.Length > 3)
{
Console.WriteLine("Sorry, this program currently supports a maximum of three different reports to analyze at a time.");
return;
}
else if (args.Length == 0)
{
List<string> fL = new List<string>();
for (int k = 0; k < 3; k++)
{
if (!loadFile(ref fL)) break;
}
if (fL.Count == 0)
{
InfoDisplay.HelpMessage();
return;
}
else
{
args = fL.ToArray();
}
}
// main program
...
}
I know this doesn't directly answer the question, but the OpenFileDialog has a property called "MultiSelect" which indicates whether or not the user can select more than one file. Once the user does select the file(s), the property FileNames (string[]) gets populated with all the file names. You can then just do a check like this:
if(dialog.FileNames.Length > 3)
{
//only 3 are allowed
}
I encountered the same problem in a console application.
OpenFileDialog.ShowDialog can be called with a "parent window" handle argument. I create a dummy Form and use that as parent window argument (the dummy form is invisible, since I don't call Show() on it).
The following code works for me:
Form dummyForm = new System.Windows.Forms.Form();
OpenFileDialog myOpenFileDialog1 = new OpenFileDialog();
if (myOpenFileDialog1.ShowDialog(dummyForm) == DialogResult.OK) {
fileName1 = myOpenFileDialog1.FileName;
}
OpenFileDialog myOpenFileDialog2 = new OpenFileDialog();
if (myOpenFileDialog2.ShowDialog(dummyForm) == DialogResult.OK) {
fileName2 = myOpenFileDialog2.FileName;
}
For me, dummy forms and label still didn't solve the problem. CodeProject has a partial solution at http://www.codeproject.com/KB/WPF/MessageBox.aspx
You can then use Process.GetCurrent.Process.MainWindowHandle in the constructor to the class in the article above, then pass the instance to the file dialog, and it seems to work well (for me at least).
Process p = Process.GetCurrentProcess();
WindowWrapper w = new WindowWrapper(p.MainWindowHandle);
OpenFileDialog ofd = new OpenFileDialog();
var ret = ofd.ShowDialog(w);
...
Found a similar post here. Not tested, but give it a shot and let me know.
foreach(Process p in Process.GetProcesses)
{
if(p.MainWindowTitle = <the main UI form caption>)
{
if(IsIconic(p.MainWindowHandle.ToInt32) != 0)
{
ShowWindow(p.MainWindowHandle.ToInt32, &H1);
ShowWindow(f.Handle.ToInt32, &H1);
}
else
{
SetForegroundWindow(p.MainWindowHandle.ToInt32);
SetForegroundWindow(f.Handle.ToInt32);
}
}
}
OpenFileDialog.ShowDialog can be
called with a "parent window" handle
argument. I create a dummy Form and
use that as parent window argument
(the dummy form is invisible, since I
don't call Show() on it).
The Form is a bit heavy-weight, perhaps a label instead, since it just takes a IWin32Window?
OpenFileDialog.ShowDialog(new Label());
It seems to work.
If someone could come up with a reasonable solution to this (now-) resurrected question, that would be great.
Aaron

Categories