1

I have a block of code which reads powerpoint slides and creates xml for them.Everything is working fine on my local machine.but on server,when second slide is read.I Get the exception: EXCEPTION:The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER)) for Powerpoint Interop

Function Throwing Error:

public string AddPPTPages(long templateid, long pptFileId)
    {
        string strPptFilePath = "";
        string strSuccess = "";

        using (var dc = new DataContext())
        {
            var template = dc.Templates.GetByID(templateid);
            template.ExtendedData = "<template><pptfileid>" + pptFileId + "</pptfileid></template>";
            template.Save();
            dc.SubmitChanges();
            var file = dc.FileHandles.GetByID(Convert.ToInt64(pptFileId));
            file.EnsureUrlFiles();
            strPptFilePath = file.GetPhysicalPath(file.FileName);//get path of original ppt file 
        }
        try
        {
            using (new Impersonator(Installs.Current.PPTUser, null, Installs.Current.PPTPassword))
            {

                PowerPoint.Application PowerPoint_App = new PowerPoint.Application();//Open PowerPoint app/process
                PowerPoint.Presentation presentation = null;//initialize presentation to null
                try
                {
                    PowerPoint_App.Visible = MsoTriState.msoTrue;//set app visibility to true
                    presentation = PowerPoint_App.Presentations.Open(strPptFilePath, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoTrue);//open powerpoint presentation using path strPptFilePath

                    templateID = templateid;//required for readslide function

    /////////ERROR is THROWN FOR BELOW LINE//////////////////
                    for (int i = 0; i < presentation.Slides.Count; i++)
                    {
                        ReadSlides(presentation, i);//call to read current slide
                    }
                    using (var dc = new DataContext())
                    {
                        var template = dc.Templates.GetByID(templateID);
                        template.FixPageIndexes();
                        template.Save();
                        dc.SubmitChanges();
                    }
                    presentation.Close();//close presentation
                    PowerPoint_App.Quit();//quit opened powerpoint app/process
                }
                catch (Exception ex)
                {
                    strSuccess = ex.ToString();

                }
                finally
                {
                    while (Marshal.FinalReleaseComObject(presentation) != 0) { }
                    presentation = null;
                    while (Marshal.FinalReleaseComObject(PowerPoint_App) != 0) { }

                    PowerPoint_App = null;
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    KillPPTProcess();//find ppt process in taskmanager and kill it
                }
            }
        }
        catch (Exception e)
        {
            strSuccess = e.ToString();
            MindMatrix.Libraries.Entities.ExceptionMessage.HandleException(e, null);
            Loggers.HandleException2(e);
        }
        return strSuccess;
    }

private void ReadSlides(PowerPoint.Presentation presentation, int i)
    {
        try
        {
            string strPptXml = "";
            //get number of objects(text and image) present in current slide
            foreach (var item in presentation.Slides[i + 1].Shapes)
            {
                var shape = (PowerPoint.Shape)item;
                strPptXml += ReadShape(shape);//read object and add it to xml
            }
            int height = ConvertToPixel(presentation.Slides[i + 1].Master.Height);//get height of current slide
            int width = ConvertToPixel(presentation.Slides[i + 1].Master.Width);//get width of current slide

            strFileImage = Installs.Current.GetTempDirectory(DirectoryType.PPT);//get the temporary folder path for current loggedin user in machine

            if (System.IO.Directory.Exists(strFileImage) == false)
            {
                System.IO.Directory.CreateDirectory(strFileImage);
            }
            strFileImage = strFileImage + "\\" + (i + 1) + ".png";//create image path for slide snapshot
            presentation.Slides[i + 1].Export(strFileImage, "png", width, height);//create snapshot as png image to temp folder
            strPptXml = "<slides datasourceid='0' repeaterid = '0' id='" + presentation.Slides[i + 1].SlideID + "' >" + strPptXml + "</slides>";//create slide xml using slideid and ppt xml(contains text and image objects of slide)

            MemoryStream ms = new MemoryStream();
            System.Drawing.Image imageIn;
            imageIn = System.Drawing.Image.FromFile(strFileImage);//Creates an Image from location strFileImage.
            imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

            using (var dc = new DataContext())
            {
                var template = dc.Templates.GetByID(templateID);
                //template.createPptPage(strPptXml, height, width, ms);//call to create ppt page for current slide
                template.createPptPage(RemoveTroublesomeCharacters(strPptXml), height, width, ms);//call to create ppt page for current slide
                dc.SubmitChanges();
            }
        }
        catch (Exception e)
        {

            Loggers.HandleException2(e);
        }
    }

Any help guys??

Milind Anantwar
  • 81,290
  • 25
  • 94
  • 125
  • Error is thrown when you try and iterate through the loop? On the first iteration? – JMK Jul 08 '13 at 08:25
  • @JMK:No..it works properly for first time.i.e. it execute readslide for first time and create xml for it. But throws error when for loop condition is executed next time. – Milind Anantwar Jul 08 '13 at 08:52

3 Answers3

0

Have you tried setting DisplayAlert to false?

 PowerPoint_App.DisplayAlerts = Powerpoint.PpAlertLevel.ppAlertsNone

You normally get this exception when Office opens a dialogue, and your application is unable to continue.

SvenPam
  • 1
  • 1
  • There is no DisplayAlert for presentation – Milind Anantwar Jul 08 '13 at 08:54
  • That was more of an example, you will need to do it with your application as MSDN describes. I have updated my answer to use your code. I would advise assigning objects to your use of COM objects, see: http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects – SvenPam Jul 08 '13 at 10:31
0

My guess is that ReadSlides is changing the value of presentation.Slides.Count. This would happen if you were adding slides to, or removing slides from your presentation within ReadSlides.

I would pull this out into it's own variable and then use this variable in your for loop, like so:

var slideCount = presentation.Slides.Count;

for (int i = 0; i < slideCount; i++)
{
    //etc etc
JMK
  • 27,273
  • 52
  • 163
  • 280
0

Quoting from your question:

Everything is working fine on my local machine.but on server,when second slide is read.I Get the exception

If your app is truly running in an unattended server environment, be aware that Microsoft specifically does not support COM for Office. Their warnings are fairly explicit. Here's a snippet:

If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.

decaffeinated
  • 76
  • 1
  • 5