Do you think I could just leave this part blank and it'd be okay? We're just going to replace the whole thing with a header image anyway, right?
You are not logged in.
Pages: 1
I have tried to search in other places for how to catch an exception thrown from an EventHandler (PlayerIOClient.MessageReceivedEventHandler), but I've had no luck.
Here's the code which is supposed to catch an Exception thrown when the user isn't the world owner. But the Exception isn't caught by the "catch" block. It doesn't even throw an un-handled exception box. But it can change the Connect button text to "Test", making it look like the Exception wasn't thrown.
using PlayerIOClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EEWorldSaver {
public partial class Main : Form {
public static Client cli;
public static Connection con;
public Main () { InitializeComponent (); }
private void OnMessage (object sender, PlayerIOClient.Message e) {
switch (e.Type) {
case "init":
if ((e.GetString (13) != e.GetString (0)) || !e.GetBoolean (12)) {
button1.Text = "Test";
throw new Exception ("You must be the world owner to use this bot.");
} else con.Send ("init2");
break;
case "init2":
button1.Text = "Disconnect";
button1.Enabled = true;
break;
}
}
private void button1_Click (object sender, EventArgs e) {
try {
panel1.Enabled = false;
button1.Enabled = false;
if (string.IsNullOrWhiteSpace (textBox1.Text) || string.IsNullOrWhiteSpace (textBox2.Text) || string.IsNullOrWhiteSpace (textBox3.Text)) throw new Exception ("One or more fields were empty.");
else if (textBox1.Text == "guest") throw new Exception ("You may not use this bot as guest.");
else if (textBox3.Text.StartsWith ("OW")) throw new Exception ("This bot may not be used in open worlds.");
else if ((!textBox3.Text.StartsWith ("BW") && !textBox3.Text.StartsWith ("PW")) || !textBox3.Text.EndsWith ("I")) throw new Exception ("Invalid world ID. A valid world ID starts with PW/BW and ends with I.");
cli = PlayerIO.QuickConnect.SimpleConnect ("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text, null);
con = cli.Multiplayer.CreateJoinRoom (textBox3.Text, (textBox3.Text.StartsWith ("BW") ? "Beta" : "Everybodyedits") + cli.BigDB.Load ("config", "config")["version"], true, null, null);
con.Send ("init");
con.OnMessage += new MessageReceivedEventHandler (OnMessage);
} catch (Exception ex) {
MessageBox.Show (this, ex.Message, "Error", 0, MessageBoxIcon.Error);
panel1.Enabled = true;
button1.Enabled = true;
}
}
}
}
Offline
Hmm. Given how you're using the exception, could you instead call some MessageOutput function and then just couple that with a return statement?
The way I figure, creating an event handler is all that happens in your button1_click; I would be surprised if for some reason we passed the error back somehow. Say you had multiple event handlers... wouldn't that get somewhat messy to make that connection that 'this' handler has 'this' exception handling that's rather distant from the one line used to set it up?
on another note, these would be on different threads anyway, so even if your code did meander its way back to that frame, you'd be doing illegal cross-thread calls.
I don't think I helped you solve anything, but food for thought
Offline
As mentioned in IRC, the issue is from WinForms (as it's utterly disgusting and has quirky threading), so the only solution I can think of is subscribing to 'Application.ThreadException' and 'AppDomain.CurrentDomain.UnhandledException'.
*u stinky*
Offline
I'm not really answering the question, but why throw an exception in that scenario when you could just display an error in a message box and disconnect the bot?
You just seem to be making life difficult for yourself.
One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.
Offline
I'm not really answering the question, but why throw an exception in that scenario when you could just display an error in a message box and disconnect the bot?
You just seem to be making life difficult for yourself.
Besides his spaghetti code, it is a valid issue for those that still use WinForms, for whatever god forsaken reason.
*u stinky*
Offline
As mentioned in IRC, the issue is from WinForms (as it's utterly disgusting and has quirky threading), so the only solution I can think of is subscribing to 'Application.ThreadException' and 'AppDomain.CurrentDomain.UnhandledException'.
Once you understand it, how it works is actually quite sensible. This isnt a great solution, but its simple and (ive now tested it and it) works, so I would advise making these changes:
using PlayerIOClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EEWorldSaver {
public partial class Main : Form {
public static Client cli;
public static Connection con;
public static bool connected = false;
public static bool hasEdit = false;
public Main () { InitializeComponent (); }
private void OnMessage (object sender, PlayerIOClient.Message e) {
switch (e.Type) {
case "init":
hasEdit = e.GetBoolean(14); // Sets a hasEdit tag so it can be used later
connected = true; // Indicates that the bot has recieved, and finished processing the init message, which allowd the other thread to continue
break;
case "init2":
Invoke(new MethodInvoker(delegate // Need an invoke here, because this is running on a different thread
{
button1.Text = "Disconnect";
button1.Enabled = true;
}));
break;
}
}
private void button1_Click (object sender, EventArgs e) {
try {
panel1.Enabled = false;
button1.Enabled = false;
if (string.IsNullOrWhiteSpace (textBox1.Text) || string.IsNullOrWhiteSpace (textBox2.Text) || string.IsNullOrWhiteSpace (textBox3.Text)) throw new Exception ("One or more fields were empty.");
else if (textBox1.Text == "guest") throw new Exception ("You may not use this bot as guest.");
else if (textBox3.Text.StartsWith ("OW")) throw new Exception ("This bot may not be used in open worlds.");
else if ((!textBox3.Text.StartsWith ("BW") && !textBox3.Text.StartsWith ("PW")) || !textBox3.Text.EndsWith ("I")) throw new Exception ("Invalid world ID. A valid world ID starts with PW/BW and ends with I.");
cli = PlayerIO.QuickConnect.SimpleConnect ("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text, null);
con = cli.Multiplayer.CreateJoinRoom (textBox3.Text, (textBox3.Text.StartsWith ("BW") ? "Beta" : "Everybodyedits") + cli.BigDB.Load ("config", "config")["version"], true, null, null);
con.OnMessage += new MessageReceivedEventHandler (OnMessage); // Setting onmessage should be before init, otherwise theoretically you could recieve a message before the handler is set
con.Send ("init");
while (!connected) { } // Waits until the bot has connected to continue
if (!hasEdit) throw new Exception ("You must be the world owner to use this bot."); // Now the exception is thrown in the same thread as the form
else con.Send ("init2");
} catch (Exception ex) {
MessageBox.Show (this, ex.Message, "Error", 0, MessageBoxIcon.Error);
panel1.Enabled = true;
button1.Enabled = true;
// Check if connected, and disconnect if it is or whatever here
}
}
}
}
Also I have a library which might help with the saving, and parsing of init / load messages: WorldSaver
I'm not really answering the question, but why throw an exception in that scenario when you could just display an error in a message box and disconnect the bot?
You just seem to be making life difficult for yourself.
I dont think you could display the error message either, because that would also happen on the wrong thread (I might be wrong, I havent tried using message boxes from other threads)
Offline
@destroyer123: The while (!connected) loop will make the program get stuck until the bot receives "init". What if the bot doesn't receive "init"? You would have to close the process via the Task Manager.
Following Tomahawk's suggestion, I think I wrote a solution to the exception handling trouble, by not throwing exceptions.
using PlayerIOClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EEWorldSaver {
public partial class Main : Form {
public Client cli;
public Connection con;
public Main () { InitializeComponent (); }
private void RestoreControls () {
panel1.Enabled = true;
button1.Text = "Connect";
button1.Enabled = true;
}
private void OnMessage (object sender, PlayerIOClient.Message e) {
switch (e.Type) {
case "init":
if ((e.GetString (13) != e.GetString (0)) || !e.GetBoolean (15)) Disconnect ("You must be the world owner to use this bot.");
con.Send ("init2");
break;
case "init2":
button1.Text = "Disconnect";
button1.Enabled = true;
break;
}
}
private void Disconnect (string reason) {
if (reason != "User pressed the disconnect button") MessageBox.Show (this, reason, "Error", 0, MessageBoxIcon.Error);
con.Disconnect ();
}
private void button1_Click (object sender, EventArgs a) {
if (button1.Text == "Disconnect") Disconnect ("User pressed the disconnect button");
else {
try {
panel1.Enabled = false;
button1.Enabled = false;
if (string.IsNullOrWhiteSpace (textBox1.Text) || string.IsNullOrWhiteSpace (textBox2.Text) || string.IsNullOrWhiteSpace (textBox3.Text)) throw new Exception ("One or more fields were empty.");
else if (textBox1.Text == "guest") throw new Exception ("You may not use this bot as guest.");
else if (textBox3.Text.StartsWith ("OW")) throw new Exception ("This bot may not be used in open worlds.");
else if ((!textBox3.Text.StartsWith ("BW") && !textBox3.Text.StartsWith ("PW")) || !textBox3.Text.EndsWith ("I")) throw new Exception ("Invalid world ID. A valid world ID starts with PW/BW and ends with I.");
cli = PlayerIO.QuickConnect.SimpleConnect ("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text, null);
con = cli.Multiplayer.CreateJoinRoom (textBox3.Text, (textBox3.Text.StartsWith ("BW") ? "Beta" : "Everybodyedits") + cli.BigDB.Load ("config", "config")["version"], true, null, null);
con.OnMessage += new MessageReceivedEventHandler (OnMessage);
con.Send ("init");
con.OnDisconnect += (s, reason) => {
if (reason != "Disconnect") MessageBox.Show (this, "Lost connection to the world.", "Error", 0, MessageBoxIcon.Error);
RestoreControls ();
return;
};
} catch (Exception ex) {
MessageBox.Show (this, ex.Message, "Error", 0, MessageBoxIcon.Error);
RestoreControls ();
}
}
}
}
}
Offline
@destroyer123: The while (!connected) loop will make the program get stuck until the bot receives "init". What if the bot doesn't receive "init"? You would have to close the process via the Task Manager.
Following Tomahawk's suggestion, I think I wrote a solution to the exception handling trouble, by not throwing exceptions.
using PlayerIOClient; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace EEWorldSaver { public partial class Main : Form { public Client cli; public Connection con; public Main () { InitializeComponent (); } private void RestoreControls () { panel1.Enabled = true; button1.Text = "Connect"; button1.Enabled = true; } private void OnMessage (object sender, PlayerIOClient.Message e) { switch (e.Type) { case "init": if ((e.GetString (13) != e.GetString (0)) || !e.GetBoolean (15)) Disconnect ("You must be the world owner to use this bot."); con.Send ("init2"); break; case "init2": button1.Text = "Disconnect"; button1.Enabled = true; break; } } private void Disconnect (string reason) { if (reason != "User pressed the disconnect button") MessageBox.Show (this, reason, "Error", 0, MessageBoxIcon.Error); con.Disconnect (); } private void button1_Click (object sender, EventArgs a) { if (button1.Text == "Disconnect") Disconnect ("User pressed the disconnect button"); else { try { panel1.Enabled = false; button1.Enabled = false; if (string.IsNullOrWhiteSpace (textBox1.Text) || string.IsNullOrWhiteSpace (textBox2.Text) || string.IsNullOrWhiteSpace (textBox3.Text)) throw new Exception ("One or more fields were empty."); else if (textBox1.Text == "guest") throw new Exception ("You may not use this bot as guest."); else if (textBox3.Text.StartsWith ("OW")) throw new Exception ("This bot may not be used in open worlds."); else if ((!textBox3.Text.StartsWith ("BW") && !textBox3.Text.StartsWith ("PW")) || !textBox3.Text.EndsWith ("I")) throw new Exception ("Invalid world ID. A valid world ID starts with PW/BW and ends with I."); cli = PlayerIO.QuickConnect.SimpleConnect ("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text, null); con = cli.Multiplayer.CreateJoinRoom (textBox3.Text, (textBox3.Text.StartsWith ("BW") ? "Beta" : "Everybodyedits") + cli.BigDB.Load ("config", "config")["version"], true, null, null); con.OnMessage += new MessageReceivedEventHandler (OnMessage); con.Send ("init"); con.OnDisconnect += (s, reason) => { if (reason != "Disconnect") MessageBox.Show (this, "Lost connection to the world.", "Error", 0, MessageBoxIcon.Error); RestoreControls (); return; }; } catch (Exception ex) { MessageBox.Show (this, ex.Message, "Error", 0, MessageBoxIcon.Error); RestoreControls (); } } } } }
The problem with that is that I dont think it would prevent the other thread from running, which could cause a lot of problems when you actually start adding things.
If you are worried about not recieving the init message, you could do something like this:
using PlayerIOClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EEWorldSaver {
public partial class Main : Form {
public static Client cli;
public static Connection con;
public static bool connected = false;
public static bool hasEdit = false;
public Main () { InitializeComponent (); }
private void OnMessage (object sender, PlayerIOClient.Message e) {
switch (e.Type) {
case "init":
hasEdit = e.GetBoolean(14); // Sets a hasEdit tag so it can be used later
connected = true; // Indicates that the bot has recieved, and finished processing the init message, which allowd the other thread to continue
break;
case "init2":
Invoke(new MethodInvoker(delegate // Need an invoke here, because this is running on a different thread
{
button1.Text = "Disconnect";
button1.Enabled = true;
}));
break;
}
}
private void button1_Click (object sender, EventArgs e) {
try {
panel1.Enabled = false;
button1.Enabled = false;
if (string.IsNullOrWhiteSpace (textBox1.Text) || string.IsNullOrWhiteSpace (textBox2.Text) || string.IsNullOrWhiteSpace (textBox3.Text)) throw new Exception ("One or more fields were empty.");
else if (textBox1.Text == "guest") throw new Exception ("You may not use this bot as guest.");
else if (textBox3.Text.StartsWith ("OW")) throw new Exception ("This bot may not be used in open worlds.");
else if ((!textBox3.Text.StartsWith ("BW") && !textBox3.Text.StartsWith ("PW")) || !textBox3.Text.EndsWith ("I")) throw new Exception ("Invalid world ID. A valid world ID starts with PW/BW and ends with I.");
cli = PlayerIO.QuickConnect.SimpleConnect ("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text, null);
con = cli.Multiplayer.CreateJoinRoom (textBox3.Text, (textBox3.Text.StartsWith ("BW") ? "Beta" : "Everybodyedits") + cli.BigDB.Load ("config", "config")["version"], true, null, null);
con.OnMessage += new MessageReceivedEventHandler (OnMessage); // Setting onmessage should be before init, otherwise theoretically you could recieve a message before the handler is set
con.Send ("init");
long timeout = DateTime.Now.Millisecond + 1000;
while (!connected) // Waits until the bot has connected to continue
if (DateTime.Now.Millisecond > timeout) throw new Exception ("Could not connect to the world."); // Prevents losing connection from freezing the bot
if (!hasEdit) throw new Exception ("You must be the world owner to use this bot."); // Now the exception is thrown in the same thread as the form
else con.Send ("init2");
} catch (Exception ex) {
MessageBox.Show (this, ex.Message, "Error", 0, MessageBoxIcon.Error);
panel1.Enabled = true;
button1.Enabled = true;
// Check if connected, and disconnect if it is or whatever here
}
}
}
}
Offline
Pages: 1
[ Started around 1745241761.6695 - Generated in 0.203 seconds, 12 queries executed - Memory usage: 1.52 MiB (Peak: 1.69 MiB) ]