Why does presentation.SaveAs() return a COMException?

Hey Comm-unity,
I’m working on a small challenge for myself in which I am trying to make a powerpoint from c# code. Everything works until my code tries to save the powerpoint, and then it throws the following error:

COMException
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (Int32 errorCode) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs:1031)
(wrapper cominterop) Microsoft.Office.Interop.PowerPoint._Presentation:get_Slides ()
(wrapper cominterop-invoke) Microsoft.Office.Interop.PowerPoint._Presentation:get_Slides ()
PowerpointCreator.CreateNewSlide () (at Assets/Scripts/PowerpointCreator.cs:31)
PowerpointCreator.CreateBamPresentation () (at Assets/Scripts/PowerpointCreator.cs:106)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:137)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:601)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:743)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()

And here’s the code that throws the error:

public class PowerpointCreator : MonoBehaviour 
{
	p.TextRange objText;
	p.Application app;
	p.Presentation pre;
	p.CustomLayout c;
	p.Slides slides;
	p._Slide slide;
	int slide_id = 1;
	public int font_Size = 16;
	public string font_Style = "Arial";
	public string temp_save_path = "C:\\Users\\James\\Documents";

	void Start()
	{
		app = new p.Application ();
		pre = app.Presentations.Add (MsoTriState.msoTrue);

		c = pre.SlideMaster.CustomLayouts [p.PpSlideLayout.ppLayoutText];

	}

	void CreateNewSlide()
	{
		slides = pre.Slides;
		slide = slides.AddSlide (slide_id, c);
		slide_id++;
	}

	void CreateHeader(string header, int fontSize, string font)
	{
		objText = slide.Shapes [1].TextFrame.TextRange;
		objText.Text = header;
		objText.Font.Name = font;
		objText.Font.Size = fontSize;
	}

	void AddText(string text)
	{
		objText = slide.Shapes [2].TextFrame.TextRange;
		objText.Text = text;
	}

	void ModifyTextBox(string text, int id)
	{
		objText = slide.Shapes[id].TextFrame.TextRange;
		objText.Text = text;
	}

	void Add_Shape(MsoAutoShapeType type, float top, float left, float width, float height)
	{
		slide.Shapes.AddShape (type, left, top, width, height);
	}

	void Save()
	{
		pre.SaveAs (temp_save_path + "myPresentation.ppt");
	}

	void AddTextBox(float top, float left, float width, float height)
	{
		slide.Shapes.AddTextbox (MsoTextOrientation.msoTextOrientationHorizontal, left, top, width, height);
	}

	void CloseAndQuit()
	{
		pre.Close ();
		app.Quit ();
	}

	public void CreatePresentation()
	{
		CreateNewSlide ();

		CreateHeader ("Header", font_Size, font_Style);
		AddText("Text");
		AddTextBox(50.0f, 450.0f, 250.0f, 100.0f);
		ModifyTextBox("Text Box", 3);
		Add_Shape(MsoAutoShapeType.msoShapeRectangle, 50.0f, 150.0f, 250.0f, 100.0f);
		AddTextBox(500.0f, 150.0f, 250.0f, 100.0f);
		ModifyTextBox("Text Box Number Two", 4);
		Save ();
		CloseAndQuit ();
	}
}

Thanks everyone!

  • tiger27

First of all this question is kinda off-topic. You have problems with pur COM interop between Mono and Microsoft’s office interfaces. Next thing is, why do you think the problem is when you try to “save” it? The stacktrace clearly shows that it’s the very first thing you try to “get”. So it’s this line:

slides = pre.Slides;

inside “CreateNewSlide” which throws the exception. So it simply doesn’t work at all. That could be because you do something wrong (forget to initialize something properly) or that the assembly simply is’t compatible with Mono. Keep in mind that “Microsoft.Office” is a .NET assembly which is just a managed wrapper for the COM interface that Office provides.

And I am officially tired. I just realized that in my save path, I forgot the slashes at the end, and so it was saving it in a different folder than it was supposed to. Apparently, it would work the first time, and I just wouldn’t see it, and then it wouldn’t work the second time, since the file already existed. The fix: add an if statement checking to see if the file already exists. Thanks for all of your help, I am going to fall asleep before I make another silly mistake like that. Thanks everyone!

  • Tiger27

P.S I also changed the API compatibility to .NET 2.0 Subset, as per @Bunny83’s suggestion. Thanks once again everyone!