Revit session Id

Revit session Id

egarden_fenestrapro_com
Contributor Contributor
1,240 Views
6 Replies
Message 1 of 7

Revit session Id

egarden_fenestrapro_com
Contributor
Contributor

Hello there people.

 

Question first & then context:

Does Revit have something like an Application Session Id number?

 

I have a modeless add-in & I'm trying to prevent it being opened twice in a session (that is, to stop a user starting up two or more instances of the add-in).

 

At the moment I'm saving a 'WindowIsOpen' bool to Properties.Settings, but I'm pretty sure it's slow & I know it's not foolproof or elegant.

 

I'm struggling to get hold of my add-in's WPF window via .net. I can find Revit's window details, but that's it.

 

So, what I was wondering is whether Revit has something like an Application Session Id that I can check against? And is there access via the API? 

 

Also, if there's a .net solution I'd be grateful for a nod in the right direction..

 

Thanks in advance for your time!

Edwin

0 Likes
Accepted solutions (2)
1,241 Views
6 Replies
Replies (6)
Message 2 of 7

arnostlobel
Alumni
Alumni
Accepted solution
Hello Edwin,

I am trying to understand your goal, but I am possibly missing some information.

Let me first state the most important comment - add-ins cannot be loaded twice no matter what the end user (or a programmer does). Thus I assume that what you actually meant by your statement was to "prevent the end user from launching my modeless form twice." Is that correct? If so, I do not think you need anything special form Revit. I assume you let the user launch your modeless form somehow, perhaps via an external command? Then it should be completely in your hands to prevent the form from being instantiated twice. Certainly you must remember it somewhere in your code that you've done it already and have a handle of the form stored in some variable somewhere. Then you can always test whether the handle is still valid and whether the form is still open or not, no?

Oh, by the way - there is no Session ID available in Revit, as there is no real need for it (well, so far.)

Thank you
Arnošt Löbel
Message 3 of 7

egarden_fenestrapro_com
Contributor
Contributor

Hello Arnošt and thanks for your reply.

 

Yes, you're right. I'm trying to find the best way prevent a second form/window being launched from our add-in's Ribbon Button.

 

At the moment I am saving a marker in the user's Properties.Settings, but that's really not great.

 

Thanks for the advice about using the Window handle. I had looked at it before, but the Handle property was always zero. I'd missed the EnsureHandle() method for the add-in window, so now I get a handle number work with. I should be able to build something a bit more elegant now.

 

Thanks again for your direction!

Edwin

0 Likes
Message 4 of 7

arnostlobel
Alumni
Alumni
Edwin,

When I wrote handle, I did not mean a windows handle as in HWND. I meant like .NET handle to an object - a tracking pointer (that is actually not a pointer.)

I assume that somewhere in your application you have something like myForm = new MyModelessForm(args). When you do that, you instantiate a variable myForm which will not be null. I also assume you do keep the variable around somewhere. So, next time a request comes from the end-user (via an External commands I also still assume) your application will see that your myForm is not null, thus you do not instantiate it again. Instead, you switch to it (display it if it is hidden, put it on top of Revit if it is bellow, etc.)
Arnošt Löbel
0 Likes
Message 5 of 7

egarden_fenestrapro_com
Contributor
Contributor

Hello Arnošt & thanks for the clarification.

 

First off, yes, the add-in is launched as an External Command.

 

Unfortunately, I must be missing something very obvious here, as I wasn't able to construct a scenario where the WPF Window itself or an IntPtr didn't start off as null when the end-user pressed the Ribbon pushbutton again. So each time a new Window is created & shown, blissfully unaware of it's older sibling..

 

Not much time for beard-stroking on this one, so I've disabled the add-in pushbutton in the Ribbon while the add-in is running. 

 

I appreciate your time on this. It's going to bother me that I couldn't get it working, as testing a tracking pointer for null would still be the most elegant solution.. So I'll be coming back to this when time allows.

 

Have a good day there,

Edwin

 

 

0 Likes
Message 6 of 7

arnostlobel
Alumni
Alumni
Accepted solution

Edwin,

 

It may still be the case that I do not completely understand your approach, but I'll try to show you something. I suggest you take a look at the ModelessDialog samples in the SDK. They do, in a way, what you seem to be wanting. Here I show some snippets of the code just to illustrate what I mean (and meant in my previous post.)

 

If you look into the same, you will see the following method in the Application.cs (am an abbreviating the code here):

        public Result OnShutdown(UIControlledApplication application)
        {
            if (m_MyForm != null && m_MyForm.Visible)
            {
                m_MyForm.Close();
            }

            return Result.Succeeded;
        }

        public Result OnStartup(UIControlledApplication application)
        {
            m_MyForm = null;   // no dialog needed yet; the command will bring it
            thisApp = this;  // static access to this application instance

            return Result.Succeeded;
        }

        public void ShowForm(UIApplication uiapp)
        {
            // If we do not have a dialog yet, create and show it
            if (m_MyForm == null || m_MyForm.IsDisposed)
            {
                // A new handler to handle request posting by the dialog
                RequestHandler handler = new RequestHandler();

                // External Event for the dialog to use (to post requests)
                ExternalEvent exEvent = ExternalEvent.Create(handler);

                // We give the objects to the new dialog;
                // The dialog becomes the owner responsible fore disposing them, eventually.
                m_MyForm = new ModelessForm(exEvent, handler);
                m_MyForm.Show();
            }
        }

As you can see, the Application has a variable m_MyForm, which is initially NULL. When a request comes (from other part of the add-in) to show the dialog, I check if it does not exist yet, and if that is the case I instantiate it and show it.

 

The request to show the dialog comes from an External command, just like in your case:

        public virtual Result Execute(ExternalCommandData commandData
            , ref string message, ElementSet elements)
        {
            try
            {
                Application.thisApp.ShowForm(commandData.Application);

                return Result.Succeeded;
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return Result.Failed;
            }
        }

The command does nothing but ask the Application to show the dialog, which will create it ans show it if it is not present yet. If the dialog already exists, the code does nothing.

 

Isn't this basically what you want?

Arnošt Löbel
Message 7 of 7

egarden_fenestrapro_com
Contributor
Contributor

Thanks very much Arnošt!

 

Yes, that is what I want. Should have checked the samples..

 

I see that I need to abstract my Window into a MyWindow class & then set it up as you've shown. I've been instantiating a base WPF Window object straight in the app class housing the Execute() method.

 

I'll see how I get on dupllicating this approach with a WPF Window instead of a Form & if there are significant changes I'll post them here.

 

Thanks again. I appreciate your time & patience!

Edwin

0 Likes