Ex: The server threw an exception. Ex from HRESULT: 0x80010105 RPC_E_SERVERFAULT

Started by rimohit, March 29, 2016, 09:44:25 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

rimohit

Within a BackgroundWorker do work handler I first open a vss-stencil, then iterate many vsd files and call shape.ReplaceShape() for given shapes.
But very often I get the Exception: The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)) when:

  • call shape.ReplaceShape()
  • document.Close()
  • ...

I noticed that there is something wrong with the state of the visio objects, but I don't know what.
Bellow are visual studio screenshots from the stencil object(targetStencil) state and from the state of the mastershape(targetMaster), which must be droped in replaceShape().

Also I  attached a screensot of the visual studio exception:
ex {"The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))"}
StackTrace = "   at Microsoft.Office.Interop.Visio.IVShape.ReplaceShape(Object MasterOrMasterShortcutToDrop, Int32 ReplaceFlags)\r\n   at Converter.MainWindow.<.ctor>b__3_1(Object o, DoWorkEventArgs e)


Please excuse the huge screenshots, I wanted to give more information.
This weird problem keeps me busy several hours and I really hope that someone has a solution for this.

Nikolay

I'm not sure what the problem can be, most probably some threading issue. Hard to tell without having the code.
It's best to avoid using in your background worker (second thread) Visio objects that were created in the main thread.

Note that Visio is STA (single-threaded), so you won't get any performance benefits by running stuff on a different thread,
all your Visio calls will be executed on the main thread anyways.

You can try to turn off UI updates while you process using Application.ScreenUpdating, and companions.

You can try async/await instead of BackgroundWorker, it has some goodies to deal smoothly with UI updates.

The easiest way out is IMO to start separate (invisible) Visio instance if you want background processing, and do the work there.

rimohit

Thank you  for your hints, bellow is my code.
Maybe it's my mistake, but I don't think  I create objects in different threads. The exception is raised when I call: s.ReplaceShape(targetMaster) 
  public MainWindow()
        {
            InitializeComponent();
            TextBoxOutputter outputter = new TextBoxOutputter(tbLogging);
            Console.SetOut(outputter);
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            worker.ProgressChanged += (o, e) => { progressBar.Value = e.ProgressPercentage; tbProgress.Text = e.UserState.ToString(); };
            this.worker.DoWork += (o, e) =>
            {
                BackgroundWorker worker = o as BackgroundWorker;
                int i = 0;
                while (worker.CancellationPending == false)
                {
                    Visio.InvisibleApp visio = default(Visio.InvisibleApp);                   
                        visioFilesFolder = Properties.Settings.Default.InputFolder;
                        DirectoryInfo[] visioFolders = Utils.GetFolders();
                        var foldersToBeProcessed = visioFolders.Count();
 
                        ShapeMappings mappings = Utils.DeserializeShapesMappingsFile();
                        visio = new Visio.InvisibleApp();
                        Visio.Document  = visio.Documents.OpenEx(Properties.Settings.Default.ShapeMappingFolder + "\\myStencil.vss",
                            (short)Visio.VisOpenSaveArgs.visOpenHidden +
                            (short)Visio.VisOpenSaveArgs.visOpenRO+ (short)Visio.VisOpenSaveArgs.visOpenNoWorkspace);

                        foreach (DirectoryInfo visFolder in visioFolders)
                        {
                            if (visio == null) visio = new Visio.InvisibleApp();
                            visio.ShowChanges = false;
                            visio.ShowProgress = 0;
                            FileInfo visiofileInfo = visFolder.GetFiles("*.vsd").FirstOrDefault();
                            string visiofilePath = visiofileInfo.FullName;
                            Visio.Documents docs = default(Visio.Documents);
                            Visio.Document doc = default(Visio.Document);

                                docs = visio.Documents;
                                doc = docs.OpenEx(visiofilePath, (short)Visio.VisOpenSaveArgs.visOpenHidden + (short)Visio.VisOpenSaveArgs.visOpenDeclineAutoRefresh + (short)Visio.VisOpenSaveArgs.visOpenNoWorkspace + (short)Visio.VisOpenSaveArgs.visOpenDontList + (short)Visio.VisOpenSaveArgs.visOpenMacrosDisabled + (short)Visio.VisOpenSaveArgs.visOpenRW);
                                var activePage = doc.Pages[1];                             
                                    foreach (ShapeMapping mapping in mappings.shapeMappings)
                                    {
                                        Visio.Master targetMaster = targetStencil.Masters.get_ItemU(mapping.targetMasterShapeName);
                                        foreach (Visio.Shape s in activePage.Shapes)
                                        {
                                            if (currentShapeMaster.Contains(mapping.sourceShapeName, StringComparison.OrdinalIgnoreCase))s.ReplaceShape(targetMaster);                                         
                                        }
                                    }                               
                                doc.Save();
                                doc.Close();
                                i++;
Directory.Move(visFolder.FullName, Properties.Settings.Default.OutputFolder + "\\" + visFolder.Name);

                                worker.ReportProgress((int)((float)i / (float)foldersToBeProcessed * 100), string.Format("File {0} / {1} complete.", i, foldersToBeProcessed));
                                if (worker.CancellationPending == true) return;
                         

                        }
                        targetStencil.Close();
           
                }
            };
            worker.RunWorkerCompleted += (o, e) => { btnProgressStop.Visibility = Visibility.Collapsed; btnProgressStart.Visibility = Visibility.Visible; };
        }

Nikolay

Generally the code looks okay..
Maybe it's shape specific (does ReplaceShape fail on some specific shapes?)

rimohit

Hi,
thank you very much that you read the code above!
The only thing I have noticed is that ReplaceShape() on Swimlane do not work and I then read, that Swilanes are
not supported in ReplaceShape(). For other shapes I didn't found any restrictions but I'm not 100% if there aren't. I will pursue this.

I have the suspicion that sometimes Document.Pages[1] doesn't refer to the page I need,
although my solution create only one page per vsd document. I don' know wheter  this could be the problem, the exception message is too general for me.   :-\


Nikolay

Seems to be a bug in Visio's ReplaceShape function..
If this is the case, I think there is little one can really do about it, except maybe finding a way to easily reproduce the problem, and then reporting it to MS.

Note that there may be other options - for example, Paul Herber's Super Utilities have "replace shape" function.
Not sure if that function can be called through automation though.

When working at Process4.biz, I've also implemented similar thing some years ago (updating shape on the drawing from the external stencil, while keeping shape's text, connections, formatting, and data intact, if those were modified in the shape), now it's a part of the P4B.

I think it could make sense for MS to provide this sort of functionality out of the box some day.

rimohit

Hi,

just for the record:
The problem wasin the way I open the stencil file, in other words the open flags  :o  :o :o  :-[

the "wrong way":
(short)Visio.VisOpenSaveArgs.visOpenHidden + (short)Visio.VisOpenSaveArgs.visOpenDeclineAutoRefresh + (short)Visio.VisOpenSaveArgs.visOpenNoWorkspace + (short)Visio.VisOpenSaveArgs.visOpenDontList + (short)Visio.VisOpenSaveArgs.visOpenMacrosDisabled + (short)Visio.VisOpenSaveArgs.visOpenRW);


the way whithout exception:  (short)VisOpenSaveArgs.visOpenHidden + (short)VisOpenSaveArgs.visOpenDocked