Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 294
  • Last Modified:

Accessing a Word or Excel document through a proxy causes deadlock

Hi,

I have an Office add-in that tracks documents open in various instances
of Word and Excel. This "tracker" object is a Singleton Well-Known
object registered with .Net remoting.

I use a MarshalByRefObject-derived proxy class that has an internal
reference to the document object. This proxy is used to "send" the
document over remoting. The problem appears when the "tracker" calls a
method on the proxy which in turn accesses a property (FileName or
something) on the document object. What happens is that it simply locks.

I tried creating a separate STA thread for this, with no effect. What
should I do? Colud it be that the document object gets confused when
called inside a remoting context? Maybe this call should have been
dispatched to the UI's primary thread (no idea how to do this with
office)? Any ideas?

Thanks in advance!
0
pedja11
Asked:
pedja11
  • 5
  • 4
1 Solution
 
eekjCommented:
>>What happens is that it simply locks.
please post the code that accessed the document object
0
 
pedja11Author Commented:
Server:

IDictionary h_Table;
h_Table = new Hashtable();
h_Table["port"] = 9932;
BinaryServerFormatterSinkProvider obj_FormatProvider = new BinaryServerFormatterSinkProvider();
obj_FormatProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
ServChannel = new TcpServerChannel(h_Table, obj_FormatProvider);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(GlobalData) , "GlobalData" , WellKnownObjectMode.Singleton);

Client:

TcpClientChannel tc = new TcpClientChannel();
ChannelServices.RegisterChannel(tc);
GlobData = (GlobalData)Activator.GetObject(typeof(GlobalData) , "tcp://localhost:9932/GlobalData");

******************************************************

Microsoft.Office.Interop.Excel.Workbook wbb = (Microsoft.Office.Interop.Excel.Application)app.ActiveWorkbook;
GlobalData gd = new GlobalData();
gd.SetExcelDoc(wbb);
GlobData.SetExcelDocWithGlobalData(gd);                  
GlobData.DoSomething();
*******************************************************
public class GlobalData:System.MarshalByRefObject
{
   public Microsoft.Office.Interop.Excel.Workbook ExcelDoc;
   public void SetExcelDocWithGlobalData(GlobalData gd)
   {
       ExcelDoc = gd.ExcelDoc;
   }
   public void SetExcelDoc(Microsoft.Office.Interop.Excel.Workbook wb)
   {
     ExcelDoc = wb;
   }

   public void DoSomething()
   {
      Thread wt = new Thread(new ThreadStart(Something));
      wt.ApartmentState = ApartmentState.STA;
      wt.Start();
      wt.Join();
   }

   public Something()
   {
    //Some code that uses ExcelDoc
   }

   public GlobalData()
   {
   }
}

0
 
eekjCommented:
So the client is opening a document and your remoting service is tracking that. What I dont get is why you're doing this on the client side:

GlobalData gd = new GlobalData();
gd.SetExcelDoc(wbb);
GlobData.SetExcelDocWithGlobalData(gd);              

it looks like you've created a proxy already using this code on the client:
GlobData = (GlobalData)Activator.GetObject(typeof(GlobalData) , "tcp://localhost:9932/GlobalData");

but then the client creates another remoting service on the client using:
GlobalData gd = new GlobalData();
... and then passes this back to the proxy.

If you want to activate the object from the client you should use:
RemotingConfiguration.RegisterWellKnownClientType(typeof(GlobalData), "tcp://localhost:9932/GlobalData");
GlobalData gd = new GlobalData();
gd.SetExcelDoc(wbb);

But also I don't understand what this is doing:
GlobData.SetExcelDocWithGlobalData(gd);              

Just one more thing Im confused about - should this be Singleton? Singleton creates a single server-side instance for everybody that accesses your service, for all calls.

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
pedja11Author Commented:
That is all because I wanted to send an object not inherited from MarshalByRefObject. I want server to work something with ExcelDocument.

It should be singleton.
0
 
eekjCommented:
ok cool but what does this do?

   public void SetExcelDocWithGlobalData(GlobalData gd)
   {
       ExcelDoc = gd.ExcelDoc;
   }
0
 
pedja11Author Commented:
I'm using MarshalByRefObject to send Excel Document object which is not MarshalByRefObject.
0
 
eekjCommented:
A MarshalByRefObject is a remote object that runs on the server and accepts method calls from the client. You cant really use it like that. You probably need to serialise the excel document to xml then pass it to the MarshalByRefObject and deserialize it on the server then process it (in your thread or wherever)
0
 
pedja11Author Commented:
If I use some other object, instance of the class I created and which is not MarshalByRefObject, not the excel document, I don't have a problem.
And I am doing all this to avoid serialization.
0
 
eekjCommented:
Its never going to work like that. When you create an excel "document" in code youre only creating an instance of a class that interfaces with Microsoft Excel (the program itself), not the actual excel document or anything like that. When you do anything with Excel - creating a new workbook or whatever - what happens is the ExcelDoc object would send a command to the copy of Microsoft Office installed on your local machine telling it to do that task for you.

The only project I know of that reads and writes excel documents directly and bypasses the Microsoft Office API is Jakarta POI, but thats in java. You won't be able to 'send' your file to the server to process it the way you've tried. I would suggest doing your processing client-side, its going to be much easier.

If you HAVE to pass the excel document to the server to do some processing on it you'll need to convert it to XML and send the document itself (not ExcelDoc) that way. Otherwise you could send the file as a byte stream then save it on the server and then send it back when you've finished ... but thats the hard way. Do it client side and save yourself the trouble.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now