How to find if Visio file is open using C#

Started by DGR2017, June 01, 2018, 07:25:59 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

DGR2017

Hi,
Can some one help with C# code to find out from an office application like Powerpoint, Excel or Word if Visio file is open. I was to write this code in these office applications and be able to find out if an instance of Visio is open. Thank you in advance.

Paul Herber

Do you want to find out if a particular file is open or just to see if Visio is open?
Electronic and Electrical engineering, business and software stencils for Visio -

https://www.paulherber.co.uk/

DGR2017

Hi,

I would first like to know programmatically using C# via an addin in Powerpoint, Word or Excel, if Visio file is open. If Visio file is open, then want to add a page to it. Hope this clarifies. Thank you.

Paul Herber

First add Visio to the list of assemblies. Use the Reference Manager for this.
Add
using Visio= Microsoft.Office.Interop.Visio

var visioApp = new Visio.Application();
// Make the object visible.
visioApp.Visible = true;

Then you can access the number of documents open, find the one you want and add a page.
Electronic and Electrical engineering, business and software stencils for Visio -

https://www.paulherber.co.uk/

Nikolay

#4
If you mean, "if a file is currently opened in Visio application" (that is not controlled by you at the moment), then in C#, that would be Marshal.GetActiveObject("Visio.Application") to get a running Visio instance, and then use app.Documents to get its document list. Like this:

var app = (Visio.Application) Marshal.GetActiveObject("Visio.Application");
var openDocuments = app.Documents;


That might get tricky if you care about multiple Visio instances running at the same time, however.
In this case, the things can get quite nasty, but still technically possible, all the open files are actually listed in ROT (running object table)
The link below explains how to list and get objects from the ROT (copied from the Stackoverflow topic... maybe there is a better one, but not sure)

https://dotnet-snippets.de/snippet/laufende-com-objekte-abfragen/526

Nikolay

#5
Did some lifting :)
The code below is adapted for Visio to iterate over open documents (opened in Visio instances, running on the local computer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Visio = Microsoft.Office.Interop.Visio;
class Program
{
    static void Main(string[] args)
    {
        string[] visioExtensions = { ".vsd", ".vsdx", ".vdx" };

        var docs = GetOpenDocuments(visioExtensions);

        foreach (Visio.Document doc in docs)
        {
            // ... do something about the document...
            //
            // doc.Pages.Add();
            // Console.WriteLine(doc.Name);
        }
    }

    [DllImport("ole32.dll")]
    static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

    [DllImport("ole32.dll")]
    public static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

    // Get all running instance by querying ROT
    private static List<object> GetOpenDocuments(string[] extensions)
    {
        // get Running Object Table ...
        IRunningObjectTable Rot;
        GetRunningObjectTable(0, out Rot);
        if (Rot == null)
            return null;

        // get enumerator for ROT entries
        IEnumMoniker monikerEnumerator = null;
        Rot.EnumRunning(out monikerEnumerator);

        if (monikerEnumerator == null)
            return null;

        monikerEnumerator.Reset();

        List<object> instances = new List<object>();

        IntPtr pNumFetched = new IntPtr();
        IMoniker[] monikers = new IMoniker[1];

        // go through all entries and identifies app instances
        while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0)
        {
            IBindCtx bindCtx;
            CreateBindCtx(0, out bindCtx);
            if (bindCtx == null)
                continue;

            string displayName;
            monikers[0].GetDisplayName(bindCtx, null, out displayName);

            // displayName is basically file path. Should have one of specified extensions
            if (extensions.Any(extension => displayName.EndsWith(extension)))
            {
                object ComObject;
                Rot.GetObject(monikers[0], out ComObject);

                if (ComObject != null)
                    instances.Add(ComObject);
            }
        }

        return instances;
    }

}