Visio AddAdvice Throws an Exception - c#

I'm trying to handle an event when elements are added into a diagram, however AddAdvice() throws an unhandled COM exception:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Visio = Microsoft.Office.Interop.Visio;
namespace VisioAddAdviceWinForms
{
public partial class Form1 : Form
{
private EventSink eventSink = null;
public Form1()
{
InitializeComponent();
this.eventSink = new EventSink();
unchecked
{
axDrawingControl1.Window.EventList.AddAdvise(((short)Visio.VisEventCodes.visEvtAdd + (short)Visio.VisEventCodes.visEvtShape), this.eventSink, "", "");
}
}
}
public class EventSink : Visio.IVisEventProc
{
object Visio.IVisEventProc.VisEventProc(
short eventCode,
object source,
int eventID,
int eventSeqNum,
object subject,
object moreInfo)
{
Visio.IVApplication app = null;
Visio.IVDocument doc = null;
Visio.IVShape shape;
try
{
if (source is Visio.IVApplication)
{
app = (Visio.Application)source;
}
else if (source is Visio.IVDocument)
{
doc = (Visio.Document)source;
}
switch (eventCode)
{
case unchecked((short)Visio.VisEventCodes.visEvtAdd) +
(short)Visio.VisEventCodes.visEvtShape:
shape = (Visio.Shape)subject;
MessageBox.Show("added");
break;
case (short)Visio.VisEventCodes.visEvtApp +
(short)Visio.VisEventCodes.visEvtNonePending:
MessageBox.Show("pending");
break;
case (short)Visio.VisEventCodes.visEvtDel + (short)
Visio.VisEventCodes.visEvtShape:
shape = (Visio.Shape)subject;
MessageBox.Show("deleted");
break;
default:
break;
}
}
catch (Exception err)
{
MessageBox.Show("Exception in IVisEventProc.VisEventProc: "
+ err.Message);
}
return null;
}
}
}

Not sure about the exception you're seeing with AddAdvise, but why not bypass AddAdvise and use the managed event wrappers provided by Visio's interop layer? Is there a reason to use AddAdvise instead of the Visio Primary Interop Assembly?
Can you simply add a handler for the ShapeAdded event directly on the control itself? Or, if not on the control, then certainly on the Visio.Document contained inside the control.
See also the sample code in this forum post:
http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/c80df85f-4e97-4f4c-8563-52cb40786b13/
And the answer to this other stackoverflow question:
C# - Is there any OnShapeMoved or OnShapeDeleted event in Visio?

Add this:
using System.Runtime.InteropServices;
And where you have this:
public class EventSink : Visio.IVisEventProc{
Put this:
[ComVisible(true)]
public class EventSink : Microsoft.Office.Interop.Visio.IVisEventProc{

Related

COM object that has been separated from its underlying RCW cannot be used while testing

I'm doing some test using the .NET 4.5 TestTools and Visual Studio 2010. I m testing a singleton class that creates an COM Instance somewhere during construction/initialization, so the classes state will be keep the same in all tests. The Problem is, each test runs for itself, running all test will give a strange result - the first test succeeds, all other fail
"System.Runtime.InteropServices.InvalidComObjectException: COM object
that has been separated from its underlying RCW cannot be used.."
result of a corrupted COM reference (see myComInstance below).
Not quite sure if i explained the problem correctly. Below is my singleton class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace APITestTrial3
{
public partial class frmMbxControl : Form
{
private frmMbxControl()
{
InitializeComponent();
Connect("abhishek281mbx","PCMBXsrv.281","appmat1.bsd.com");
}
private static frmMbxControl g_Mbx;
public static frmMbxControl GetMbx()
{
if (g_Mbx == null)
{
g_Mbx = new frmMbxControl();
}
return g_Mbx;
}
private string Connect(string mbxName, string serverName, string hostName)
{
// frmControls frm = new frmControls();
mbx.HostName = hostName;
mbx.MbxName = mbxName;
mbx.ServerName = serverName;
mbx.replybox = "replyBox";
if (mbx.Status != 0)
{
if (mbx.Connect())
{
Console.WriteLine("Connected");
return ("Connected");
}
else
{
return ("Not Connected");
}
}
return ("Connected");
}
public String Send(String txnName, String txn)
{
String msgReply = "";
String rep = "";
//mbx.Send(txnName, txn);
mbx.Open("ReplyBox1","c");
mbx.SendAndReply(txnName, txn, "ReplyBox1");
if (mbx.WaitForMsg("ReplyBox1", 0, ref msgReply, ref rep) == CwMboxLib.CwWaitResult.CwWaitOk)
{
rep = msgReply;
mbx.Close("ReplyBox1");
}
return msgReply;
}
private void frmMbxControl_Load(object sender, EventArgs e)
{
}
}
}
Another class uses GetMbx() and Send() method of above class.

Exception Handling in a Windows Forms Application

I'm doing a program for serial communications. To centralize the process of access to serial, created a class.
I am having problem when an exception is lançanda within the class leaves the locked program.
example:
When trying aberir the serial port, can give error and the system is at that point to burst memory.
How should I handle errors?
Put try and catch?
Add another routine?
Error point:
portSerial.Open();
Program
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PortSerial.Lib;
namespace ProgramPortSerial
{
public partial class Form1 : Form {
public static LibPortaSerial portSerial = new LibPortSerial();
public Form1()
{
InitializeComponent();
portSerial.LineReceived += new LineReceivedEventHandler(sp1_LineReceived);
portSerial.Init(
ref cmbPortas,
ref cmbVelocidade,
ref cmbBitsDeDados,
ref cmbPariedade,
ref cmbBitsDeParada,
ref cmbControleDeFluxo);
}
void sp1_LineReceived(object sender, LineReceivedEventArgs Args)
{
// Tem que ser em uma nova thread para não travar
Invoke(new Action(() =>
{
memDadosRecebidos.Text += "\r\n" + Args.Resposta;
}));
}
private void btnAbrirPorta_Click(object sender, EventArgs e)
{
portSerial.Open();
}
}
}
Class PortSerial
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Forms;
namespace PortSerial.Lib
{
public class LibPortSerial : IDisposable
{
public SerialPort portSerial;
public LibPortSerial()
{
portSerial = new SerialPort();
}
public void Dispose()
{
if (portSerial != null)
portSerial.Dispose();
}
public void Open(
string port,
int veloc,
int bitsData,
string pariedade,
string bitsStop,
string control)
{
portSerial.PortName = port;
portSerial.BaudRate = veloc;
portSerial.DataBits = bitsData;
portSerial.Parity = SetPariedade(pariedade);
portSerial.StopBits = SetBitsStop(bitsStop);
portSerial.Handshake = Setcontrol(control);
portSerial.Open(); // ==> Erro this point
}
}
}
You should write it as:
public void Open(
string port,
int veloc,
int bitsData,
string pariedade,
string bitsStop,
string control)
{
portSerial.PortName = port;
portSerial.BaudRate = veloc;
portSerial.DataBits = bitsData;
portSerial.Parity = SetPariedade(pariedade);
portSerial.StopBits = SetBitsStop(bitsStop);
portSerial.Handshake = Setcontrol(control);
try
{
portSerial.Open(); // ==> Erro this point
}
catch(IOException exp)
{
return exp.Message;
}
}

Object reference is required for non-static field, method or property

working on a login method, using Mdi, and MVC. The Class structure is very elaborate, so constant references between classes is required. However, when I try to change the Main Menu view, I get the "object reference is required for non-static field, method or property".
I am still only an amateur, started 2 months ago and self-taught, so I am still fuzzy on what the error is actually referring to and what it means.
Here is the Menu View Class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DCIM_With_Test.User;
namespace DCIM_With_Test.Menu
{
public partial class Menu_View : Form
{
public static int btnUser;
public Menu_View()
{
InitializeComponent(); //runs the Main Menu form
User_Controller CreateLoginView = new User_Controller(); //opens the Show_Login method in the User_Controller
CreateLoginView.Show_Login(this); //sets the Mdi Parent container
}
public void SetMenuView()
{
switch (Db_Facade.ACCESS)
{
case 1:
plantAreaCodeToolStripMenuItem.Visible = true;
cableIDToolStripMenuItem.Visible = true;
logOutToolStripMenuItem.Visible = true;
createNewUserToolStripMenuItem.Visible = true;
editUserToolStripMenuItem.Visible = true;
break;
default:
plantAreaCodeToolStripMenuItem.Visible = false;
cableIDToolStripMenuItem.Visible = false;
logOutToolStripMenuItem.Visible = false;
createNewUserToolStripMenuItem.Visible = false;
editUserToolStripMenuItem.Visible = false;
break;
}
}
The User Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DCIM_With_Test.Menu;
namespace DCIM_With_Test.User
{
class User_Controller
{
public void Show_Login(Menu_View Main_Menu)
{
User_Login_View LoginView = new User_Login_View(); // Creates an object of the User_Login_View.
LoginView.MdiParent = Main_Menu; // Set the Parent Form of the Child window.
LoginView.Show(); // Display the new form.
}
public void Show_User(Menu_View Main_Menu)
{
User_Edit_View EditUserView = new User_Edit_View(); // Creates an objet of the User_View.
EditUserView.MdiParent = Main_Menu; // Set the Parent Form of the Child window.
EditUserView.Show(); // Display the new form.
}
public static void Compare_Login(User_Login_View Login_View)
{
User_Model getACCESS = new User_Model();
getACCESS.uName = Login_View.txtUsername.Text;
getACCESS.uPwd = Login_View.txtPassword.Text;
Db_Facade.ACCESS = 1;
if (Db_Facade.ACCESS > 0)
{
Login_View.Close();
}
else
{
Login_View.lblError.Visible = true;
}
Menu_View.SetMenuView(); //here is where the error occurs
}
}
}
The Db_Facade Class is currently just a collection of Variables, hence why ACCESS is set to 1 in the User_Controller
Your problem occurs because you don't have a reference to the Menu_View object inside your function, so it tries to reference the Menu_View class, which doesn't have any static members assigned. It looks like what you want to do is call Login_View.MdiParent.SetMenuView()
EDIT
You probably need to cast your call, as you are saving Main_Menu into LoginView.MdiParent which stores it as it's base class Form. Try: (Main_Menu)Login_View.MdiParent.SetMenuView()
If casting the object isn't possible, then what you can do is create a Property to access the object directly.
In your User_Login_View, create a new property public Menu_View Menu {get;set;}. Then, in your Show_Login function, add a line to set the Menu object LoginView Menu = Main_Menu;. Now, you can reference LoginView.Menu.SetMenuView(); without needing a cast.

Selenium Nunit addin install exception

I don't have enough rep to comment, so I am posting a question here. I read this question Get list of failing tests from Nunit. I am trying to implement the nunit addin, I used this code:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using NUnit.Core.Extensibility;
namespace NunitAddin
{
[NUnitAddinAttribute(Type = ExtensionType.Core,
Name = "addin",
Description = "addin")]
public class NunitAddin : IAddin
{
public bool Install(IExtensionHost host)
{
IExtensionPoint listeners = host.GetExtensionPoint("EventListeners");
if (listeners == null)
return false;
listeners.Install(this);
return true;
}
public void TestStarted(NUnit.Core.TestName testName)
{
}
public void TestFinished(NUnit.Core.TestResult result)
{
}
public void RunStarted(NUnit.Core.TestName testName)
{
}
public void RunFinished(NUnit.Core.TestResult result)
{
}
public void UnhandledException(Exception exception)
{
}
public void TestOutput(NUnit.Core.TestOutput testOutput)
{
}
}
}
But when I call it using
var addin = new NunitAddin.NunitAddin();
var a = addin.Install(CoreExtensions.Host);
I get an error
NunitAddin.NunitAddin is not {0} extension point
on
listeners.Install(this);
Does anyone know how to solve this problem?
Never mind, issue solved. Just a stupid mistake, I had NunitAddin : IAddin instead of NunitAddin : IAddin; EventListener

Checking if custom control is already added to form

I'm creating a custom C# control (form's title bar). One form can have only one title bar, and that's why i'm wondering something: When user (programmer) adds my title bar to his form, is there ANY way i can check if ParentForm already contains my title bar, and if so can i cancel adding another instance of my control?
I know how to perform check to see types of controls ParentForm contains, but what event is raised when my control is dropped from toolbox to form, and how to "cancel" layout of my control if necessary?
You should read in-depth about the designer technologies available in .NET, because these are not what I would call production-ready examples. However, this gives you a solid start and both code snippets do what you are asking.
For design time, you can override the designer site in your control and do the following:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Diagnostics;
namespace WindowsFormsControlLibrary1 {
public partial class DebugControl : UserControl {
public DebugControl() {
InitializeComponent();
}
public override ISite Site
{
get
{
return base.Site;
}
set
{
base.Site = value;
IComponentChangeService service = (IComponentChangeService)GetService(typeof(IComponentChangeService));
service.ComponentAdding += (sender, e) => {
IDesignerHost host = (IDesignerHost)value.Container;
Component component = (Component)host.RootComponent;
if (component as Form != null)
{
Form form = (Form)component;
foreach (Control c in form.Controls)
{
if (c.GetType() == this.GetType())
{
throw new System.ArgumentException("You cannot add two of these controls to a form!");
}
}
}
};
}
}
}
}
For runtime in your form you can override OnControlAdded and do the following:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using WindowsFormsControlLibrary1;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected override void OnShown(EventArgs e)
{
Controls.Add(new DebugControl());
}
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
if (e.Control.GetType() == typeof(DebugControl))
{
int count = 0;
foreach (Control c in Controls)
{
if (c is DebugControl)
{
count++;
}
}
if (count > 1)
{
Controls.Remove(e.Control);
Debug.Assert(false, "Cannot add two of these controls!");
}
}
}
}
}
There are more than one way to do this, but these are rough examples, mind you. Read up on design-time support that the .NET framework, it is very rich and there are extensive documentation on it. Another method is to implement custom designers and implement CanBeParentedTo and CanParent, but mind you CanBeParentedTo is not called when your control is drug from the ToolBox to your form.
You may use Controls collection of the active form.
Handle the ParentChanged event, check the parent's Controls, and throw an exception if necessary.

Categories

Resources