1

I am having problems saving a PowerPoint file in an add-in I am writing.

Basically, I need to save the currently open presentation as a wmv and then FTP it to an external server... sounds easy eh?

I have worked out how to save the currently open presentation as a wmv.

I have also got code to check if a file is open so I can tell when the "save" process is complete.

But the code just goes into an infinite loop. The wmv starts for get written but never goes beyond 0kb.

If I remove the line

checkfile(exportPath, exportName);

it works just fine... otherwise it just stays in a loop.

This is the code I have so far...

using System;
using System.Windows.Forms;
using Office = Microsoft.Office.Core;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using System.IO;

namespace PowerPointAddIn2
{
public partial class LoginPanel : UserControl
{
    public LoginPanel()
    {
        InitializeComponent();
    }

    private void LoginPanel_Load(object sender, EventArgs e)
    {

    }

    private void btnLogin_Click(object sender, EventArgs e)
    {

        string exportName = "video_of_presentation";
        string exportPath = @"C:\{0}.wmv";

        // Export the currently open presentation
        PowerPoint.Application ppApplication = null;
        ppApplication = new PowerPoint.Application();
        ppApplication.Activate();
        ppApplication.ActivePresentation.SaveAs(String.Format(exportPath, exportName), PowerPoint.PpSaveAsFileType.ppSaveAsWMV, Office.MsoTriState.msoTrue);

        checkfile(exportPath, exportName);

        MessageBox.Show("Finished");

    }

    protected void checkfile(string exportPath, string exportName)
    {
        FileInfo f = new FileInfo(String.Format(exportPath, exportName));
        while (IsFileLocked(f) == true) { System.Threading.Thread.Sleep(5000); }
        MessageBox.Show("Finished");
    }

    protected virtual bool IsFileLocked(FileInfo file)
    {
        FileStream stream = null;

        try
        {
            stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
        }
        catch (IOException)
        {
            //the file is unavailable because it is:
            //still being written to
            //or being processed by another thread
            //or does not exist (has already been processed)
            return true;
        }
        finally
        {
            if (stream != null)
                stream.Close();
        }

        //file is not locked
        return false;
    }

}

}

Based on a previous thread I posted I also tried Thread.Join() to see if I could simply wait for the save thread to finish before I continued but it didn't pause at all while the file was being saved so I ended up with the same result.

Any help/pointers would be very much appreciated.

Thanks

Trevor Daniel
  • 3,785
  • 12
  • 53
  • 89
  • Since there's not much to the checkfile function itself, I'm guessing the problem is in the IsFileLocked function (assuming it returns true repeatedly even after saving is done). Are you getting (and catching) an IOException every time? If so, which exception is it and does the exception change when the saving process is done? – Tim Jul 12 '13 at 15:48
  • @Tim yes, the IsFileLocked function consistently returns True. I can see a file has been created on the file system but it stays at 0kb and never gets any bigger. Almost like the SaveAs is being interrupted somehow. If I take the IsFileLocked out the file is created perfectly – Trevor Daniel Jul 12 '13 at 15:54
  • Ah ok, I see what you're saying now. the actual creation of the WMV file is getting interrupted by the checks - its not so much that the check is returning true improperly... its that the file isn't really being created (and then released)? – Tim Jul 12 '13 at 15:56
  • @tim yes, I think that's what happening... because when I take the IsFileLocked out it works perfectly. If I leave it in there the file starts to be created (can see a okb file on my disk) but I never completes the save – Trevor Daniel Jul 12 '13 at 16:07
  • Interesting... so I guess it is `stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);` that is interrupting the file writing. A quick glance tells me there's no good method for checking whether a file is locked. Maybe you could do something like check the last modified time on the file and if it is further away from Now than some pre-set value, you assume it is done writing? – Tim Jul 12 '13 at 16:12
  • its almost as if the save is called but it won't actually start running until the btnLogin_Click code has completely run... does that make sense? – Trevor Daniel Jul 12 '13 at 16:25
  • Ah, actually I see more now. its the same thread that is calling `SaveAs` as is doing the loop with the `checkfile`. Perhaps you could move the `checkfile` to a background thread and see if that helps? – Tim Jul 12 '13 at 16:27
  • @Tim thanks Tim - your help was very much appreciated. I did use a background task in the end and it works perfectly! – Trevor Daniel Jul 13 '13 at 11:24

1 Answers1

1

The PowerPoint Application object has a ppMediaTaskStatus property that should return the info you need for this. You can get the various values using the Object Browser in the PPT VBA IDE .

Steve Rindsberg
  • 14,442
  • 1
  • 29
  • 34
  • brilliant! - I started a background thread and waited for ppApplication.ActivePresentation.CreateVideoStatus == PowerPoint.PpMediaTaskStatus.ppMediaTaskStatusDone and it works perfectly - thank you so much! – Trevor Daniel Jul 13 '13 at 11:23
  • Thanks for confirming that it works as expected. I honestly wasn't sure whether it would or not. – Steve Rindsberg Jul 13 '13 at 13:49