Running C# addon on background

J

Josef Meile

Hi,

finally I was able to create my own c# addon. But it was excecuted for a short
time. I saw the C++ addon wizard and it includes a class Vaddon, which keeps
your addon on memory and doesn't load a new instance each time that you
use it. But with an exe addon, you only have a normal application with a Main
function. The addon will excecute all on the main function and finally it
will exit.

In order to avoid that, I sent the main thread of my addon to sleep, so that
it
keeps listening to the visio events. I did something like this:

public class CExeAddon
{
private Visio.Application mVisioApp = null;
private Visio.IVisEventProc mEventHandler;

public Visio.Application VisioApp
{
get
{
return mVisioApp;
}
}

public void DemoAddAdvise(Visio.Application theApplication)
{
// Declare visEvtAdd as a 2-byte value to avoid a run-time overflow
// error.
const short visEvtAdd = -32768;

Visio.EventList eventsDocument;
Visio.EventList eventsApplication;
Visio.Document addedDocument;
try
{
this.mEventHandler = new CEventSink();
addedDocument = theApplication.Documents.Add("");
eventsApplication = theApplication.EventList;
eventsDocument = addedDocument.EventList;
eventsDocument.AddAdvise((short)Visio.
VisEventCodes.visEvtCodeQueryCancelSelDel,
this.mEventHandler, "", "");

eventsDocument.AddAdvise(((short)Visio.
VisEventCodes.visEvtDel + (short)
Visio.VisEventCodes.visEvtShape),
this.mEventHandler, "", "");

//I added more events here, but for
//space reasons I omited them.
//If you're interested on the rest,
//then see the AddAdvise demo of
//the sdk library

}
catch (Exception err)
{
System.Diagnostics.Debug.WriteLine(err.Message);
}
}

public CExeAddon()
{
if (this.mVisioApp == null)
{
try
{
//If visio is already running, then gets the
//application object asociated to it
this.mVisioApp = (Visio.Application) Marshal.GetActiveObject(
"Visio.Application");
}
catch (System.Runtime.InteropServices.COMException)
{
//There isn't a visio instance, so, the user
//started the addon by double clicking the
//exe file.
this.mVisioApp = new Visio.ApplicationClass();
}
//Here I append my event handler to the visio
//application
this.DemoAddAdvise(this.mVisioApp);
}
}

static void Main(string[] args)
{
CExeAddon myAddon=new CExeAddon();
//Here I send the main thread to sleep for an
//undefined time, so, it won't exit and it will
//keep listening to the visio events
Threading.Thread.Sleep(Threading.Timeout.Infinite);
}
}

I didn't include the CEventSink class code here since it is the demo
included with the SDK library. Basically, this demo listens for all visio
events and prints a message when he catches something.

It works quite good, the addon keeps listening to the visio events and
it shows a message whenever it catches an event. But each time that
you invoke the addon from a shape by using the RUNADDONWARGS
method, a new instance of the addon will be excecuted and the
addAdvise stuff will be done again. So, I first taught to get the previous
running instance with the following peace of code:

static void Main(string[] args)
{
Process currentProcess = Process.GetCurrentProcess();
Process [] localByName = Process.GetProcessesByName(
currentProcess.ProcessName);
//The addon was already started
if (localByName.Length>1)
{
foreach (Process processObj in localByName)
{
if (processObj.Id!=currentProcess.Id)
{
//Here you should somehow send the
//the main argumets of this process
//to the old instance of my addon,
//But I don't know what comes here
//This function doesn't realy exist;
//it is just an example of what I
//want to achieve.
sendMessage(processObj,args);

//This process will now be terminated
Environment.Exit(0);
}
}
}
CExeAddon myAddon=new CExeAddon();
Threading.Thread.Sleep(Threading.Timeout.Infinite);
}

The thing there is that I don't know how to send the arguments of the new
instance of my addon to the one that was already running. So, I came with
a sockets solution:

static void Main(string[] args)
{
System.Net.IPAddress [] hostAddresses = null;
string hostName = System.Net.Dns.GetHostName();
string message = "";

System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostByName(hostName);
hostAddresses = ipEntry.AddressList;
int appPort = 1234;
Socket appSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
System.Net.IPEndPoint ipEndPoint=new
System.Net.IPEndPoint(hostAddresses[0], appPort);
Process currentProcess = Process.GetCurrentProcess();
Process [] localByName = Process.GetProcessesByName(
currentProcess.ProcessName);

//There is already an addon running
if (localByName.Length>1)
{
//Connect to the socket opened by the previous instance
appSocket.Connect(ipEndPoint);

//Send the arguments
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(args);
appSocket.Send(buffer);

//Close the socket and exit
appSocket.Close();
Environment.Exit(0);
}

//This code will be only excecuted if no more
//running instances were found
CExeAddon myAddon=new CExeAddon();

//Create a socket to get the message of the
//instances started later
int numConnections = 1;
appSocket.Bind(ipEndPoint);
appSocket.Listen(numConnections);
appSocket.BeginAccept(new AsyncCallback(myAddon.receiveCommands),
appSocket);

//Send the main thread to sleep, so that it keeps
//listening the visio events
Threading.Thread.Sleep(Threading.Timeout.Infinite);
}

//When a socket event is detected, this method
//will be excecuted
public void receiveCommands(IAsyncResult result)
{
//Gets the server socket
Socket server = (Socket)result.AsyncState;
//Gets the socket of the connected client
Socket client = server.EndAccept(result);
//Starts receiving the data
byte[] buffer = new byte[1024];
int numBytes=client.Receive(buffer);
//Closes the client connection
client.Close();
//shows the commands on a dialog
string command = System.Text.Encoding.ASCII.GetString(buffer,0,numBytes);
MessageBox.Show(command);
//Sets again the socket callback method
server.BeginAccept(new AsyncCallback(this.receiveCommands),server);
}

It works, but I found it is complicated and maybe there
is an easier way of doing this. I haven't found much
documentation about exe addons, so, that was the only
solution that came to me. Does somebody knows a better
way?

Thanks in advanced,
Josef
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top