Getting active SDBApplication COM object

Post a reply

Smilies
:D :) :( :o :-? 8) :lol: :x :P :oops: :cry: :evil: :roll: :wink:

BBCode is ON
[img] is ON
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Getting active SDBApplication COM object

Re: Getting active SDBApplication COM object

by Melloware » Sun Aug 15, 2010 9:19 am

Just to chime in my two cents I never got this working from C# .NET.

I can create new instance if it is not running of course. And I used the Stax's MonkeyToys source code example to create a small plugin that injects the running SDBApplication into my own C# Application at runtime.

Re: Getting active SDBApplication COM object

by Agent_9191 » Fri Aug 13, 2010 10:02 pm

In a way I'm glad to see I'm not the only one running into the COM issue. Since it happens in both .NET and VBScript, it's definitely the underlying cause (well, besides the obvious error message, but just wanted to rule out interop issues). It would be nice if somebody would update the development wiki and remove the obviously incorrect line about a second call to the SDBApplication returning the currently running instance. But it looks like signing up for an account on the wiki is broken, so can't go in to edit it. :x

While Steggy's approach makes sense if it's a long running application, it doesn't work for one-shot type apps that just need to do a single purpose and then end (but be run multiple times a day). For what I'm looking to do with MM I don't necessarily need the UI, but trying to go directly against the database has some issues since they customized the SQLite stuff. Not trying to hijack the thread, but it some dev's may be able to forgo the UI and go directly against the DB if anybody knows of a good way to work with their customizations. I'll keep digging through the forums, but any suggestions?

Re: Getting active SDBApplication COM object

by mayberg » Thu Aug 12, 2010 1:08 pm

Steegy_ wrote:For my WebSourcesTagger I used this code:

Code: Select all

        private static SongsDB.SDBApplicationClass sdb;
        private static SongsDB.SDBApplicationClass SDB
        {
            get {
                if (sdb == null)
                {
                    sdb = new SongsDB.SDBApplicationClass();

                    while (!sdb.IsRunning) { System.Threading.Thread.Sleep(500); }

                    sdb.ShutdownAfterDisconnect = false;
                }
                return sdb;
            }
        }
Som basically it connects to the MM COM object. If MM is already running, the property returns quickly. If MM still has to start, the property-get keeps waiting for 0.5s until MM's isRunning becomes True, i.e. it's running, at least enough for COM interaction to start.

While COM connection with MediaMonkey wasn't always 100% stable, most of the times it worked perfectly. It worked both if MM was or wasn't running before.

Cheers,
Steegy
Hi Steegy,

thanks for the reply. Unfortunatly it doesn't really help. What happens on your system, when you start the program a second time, reusing the instance which was created on the first call? On my system I get an exception:

Code: Select all

Creating MediaMonkey COM Appliation Object...
Failed to create MediaMonkey COM Appliation Object.
Retrieving the COM class factory for component with CLSID {148F7BB6-4943-4C53-8E
30-0F9115D30283} failed due to the following error: 80080005 Starten des Servers
 fehlgeschlagen (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOn
ly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Bo
olean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipChec
kThis, Boolean fillCache)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean s
kipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at TestMediaMonkeyComConnect.ComTests.ConnectOrCreateMediaMonkey() in D:\Benu
tzer\markus\documents\visual studio 2010\Projects\CopyPlaylistsWithFiles\TestMed
iaMonkeyComConnect\ComTests.cs:line 24
Press any key to continue.
- First start: Everything seems to be fine.
- Second start (reuse instance created on first start): Exception.

The curious thing is that when calling this "sdb = new SongsDB.SDBApplicationClass();" twice or more times during one program execution it works. Once the application is restarted the problem shows up.

Re: Getting active SDBApplication COM object

by Steegy_ » Thu Aug 12, 2010 12:28 pm

For my WebSourcesTagger I used this code:

Code: Select all

        private static SongsDB.SDBApplicationClass sdb;
        private static SongsDB.SDBApplicationClass SDB
        {
            get {
                if (sdb == null)
                {
                    sdb = new SongsDB.SDBApplicationClass();

                    while (!sdb.IsRunning) { System.Threading.Thread.Sleep(500); }

                    sdb.ShutdownAfterDisconnect = false;
                }
                return sdb;
            }
        }
Som basically it connects to the MM COM object. If MM is already running, the property returns quickly. If MM still has to start, the property-get keeps waiting for 0.5s until MM's isRunning becomes True, i.e. it's running, at least enough for COM interaction to start.

While COM connection with MediaMonkey wasn't always 100% stable, most of the times it worked perfectly. It worked both if MM was or wasn't running before.

Cheers,
Steegy

Re: Getting active SDBApplication COM object

by mayberg » Tue Aug 10, 2010 4:28 pm

After some more tries, I reinstalled MM and then checked the "Start MediaMonkey after Setup" checkbox at the end of the setup. This seems to help as far as the the call

Code: Select all

SongsDB.SDBApplication SDB = new SongsDB.SDBApplication();
does work now. Another variant that does work identically is:

Code: Select all

SongsDB.SDBApplication SDB = (SongsDB.SDBApplication)Microsoft.VisualBasic.Interaction.GetObject("", "SongsDB.SDBApplication");
Both calls create the COM-Object, if it is not running.

The Wiki instructs to use:

Code: Select all

SDB.ShutdownAfterDisconnect = false;
which is the default behaviour. This causes trouble:
- Stop MediaMonkey
- Run a program that calls "new SongsDB.SDBApplication();". This will create the COM-Server.
- Run the program again. It will try to connect to the COM-Server without success:

Code: Select all

Connecting to MediaMonkey COM Appliation Object...
Failed to connect to MediaMonkey COM Appliation Object.
Retrieving the COM class factory for component with CLSID {148F7BB6-4943-4C53-8E
30-0F9115D30283} failed due to the following error: 80080005 Starten des Servers
 fehlgeschlagen (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOn
ly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Bo
olean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipChec
kThis, Boolean fillCache)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean s
kipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at TestMediaMonkeyComConnect.ComTests.ConnectOrCreateMediaMonkey() in D:\Benu
tzer\markus\documents\visual studio 2010\Projects\CopyPlaylistsWithFiles\TestMed
iaMonkeyComConnect\ComTests.cs:line 24
If the MM-COM-Object is created by the code it behaves different as if it is created by the user.

Finally - the only variant that really works for me is:

Code: Select all

SongsDB.SDBApplication SDB = new SongsDB.SDBApplication();
SDB.ShutdownAfterDisconnect = true;

Re: Getting active SDBApplication COM object

by mayberg » Sun Aug 08, 2010 7:12 am

I have the same problem. If MediaMonkey is not running yet, I can create a new instance by calling "new SongsDB.SDBApplication();" and everything works fine. But if Media Monkey is already running, I cannot connect to the COM-Server. There seems to be no way to connect to a running instance.

Some C# code that demonstrates the problem:

Code: Select all

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            ConnectToMediaMonkeyViaMarshalGetActiveObject();
            ConnectToMediaMonkeyViaNativeCall();
            ConnectOrCreateMediaMonkey();
        }

        public static void ConnectOrCreateMediaMonkey()
        {
            try
            {
                Console.Out.WriteLine("Creating MediaMonkey COM Appliation Object...");
                SongsDB.SDBApplication SDB = new SongsDB.SDBApplication();
                Console.Out.WriteLine("MediaMonkey COM Appliation Object created.");
            }
            catch (COMException ex)
            {
                Console.Out.WriteLine("Failed to create MediaMonkey COM Appliation Object.");
                Console.Out.WriteLine(ex.Message);
                Console.Out.WriteLine(ex.StackTrace);
            }

            Console.Out.WriteLine("Press any key to continue.");
            Console.ReadKey();
        }

        public static void ConnectToMediaMonkeyViaMarshalGetActiveObject()
        {
            try
            {
                Console.Out.WriteLine("Connecting to MediaMonkey COM Appliation Object via Marshal.GetActiveObject...");
                SongsDB.SDBApplication SDB = (SongsDB.SDBApplication)Marshal.GetActiveObject("SongsDB.SDBApplication");
                Console.Out.WriteLine("MediaMonkey COM Appliation Object connected.");
            }
            catch (COMException ex)
            {
                Console.Out.WriteLine("Failed to connect to MediaMonkey COM Appliation Object.");
                Console.Out.WriteLine(ex.Message);
                Console.Out.WriteLine(ex.StackTrace);
            }

            Console.Out.WriteLine("Press any key to continue.");
            Console.ReadKey();
        }

        public static void ConnectToMediaMonkeyViaNativeCall()
        {
            try
            {
                Console.Out.WriteLine("Connecting to MediaMonkey COM Appliation Object via native call...");
                Guid guid = Marshal.GenerateGuidForType(typeof(SongsDB.ISDBApplication));
                object obj;
                GetActiveObject(ref guid, IntPtr.Zero, out obj);
                SongsDB.SDBApplication SDB = (SongsDB.SDBApplication)obj;
                Console.Out.WriteLine("MediaMonkey COM Appliation Object connected.");
            }
            catch (COMException ex)
            {
                Console.Out.WriteLine("Failed to connect to MediaMonkey COM Appliation Object.");
                Console.Out.WriteLine(ex.Message);
                Console.Out.WriteLine(ex.StackTrace);
            }

            Console.Out.WriteLine("Press any key to continue.");
            Console.ReadKey();
        }

        [DllImport("oleaut32.dll", PreserveSig = false)]
        static extern void GetActiveObject(ref Guid rclsid, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out Object ppunk);
    }
}
Results with the following output, if MM is already running:

Code: Select all

Connecting to MediaMonkey COM Appliation Object via Marshal.GetActiveObject...
Failed to connect to MediaMonkey COM Appliation Object.
Vorgang nicht verfgbar. (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
   at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid& rclsid, IntPtr reserved, Object& ppunk)
   at System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)
   at CopyPlaylistsWithFiles.Program.ConnectToMediaMonkeyViaMarshalGetActiveObject() in D:\Benutzer\markus\documents\visual studio 2010\Projects\CopyPlaylistsWithFiles\CopyPlaylistsWithFiles\Program.cs:line 41
Press any key to continue.
Connecting to MediaMonkey COM Appliation Object via native call...
Failed to connect to MediaMonkey COM Appliation Object.
Vorgang nicht verfgbar. (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
   at CopyPlaylistsWithFiles.Program.GetActiveObject(Guid& rclsid, IntPtr pvReserved, Object& ppunk)
   at CopyPlaylistsWithFiles.Program.ConnectToMediaMonkeyViaNativeCall() in D:\Benutzer\markus\documents\visual studio 2010\Projects\CopyPlaylistsWithFiles\CopyPlaylistsWithFiles\Program.cs:line 62
Press any key to continue.
Creating MediaMonkey COM Appliation Object...
Failed to create MediaMonkey COM Appliation Object.
Retrieving the COM class factory for component with CLSID {148F7BB6-4943-4C53-8E30-0F9115D30283} failed due to the following error: 80080005 Starten des Servers fehlgeschlagen (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at CopyPlaylistsWithFiles.Program.ConnectOrCreateMediaMonkey() in D:\Benutzer\markus\documents\visual studio 2010\Projects\CopyPlaylistsWithFiles\CopyPlaylistsWithFiles\Program.cs:line 22
Press any key to continue.
If it is not running the method ConnectOrCreateMediaMonkey starts MM.

Re: Getting active SDBApplication COM object

by mistresso » Sat Feb 21, 2009 12:42 am

FindWindow is actually old VB6 era code :-)

With .Net it seems you're supposed to now use the Interop libraries or Reflection libraries to get direct access to pointers and running assemblies. Or even Process.GetProcessesByName().

However, with this and other newer languages, the recommendation seems to be to stick to just calling "new SongsDB.SDBApplication" command rather than file handles, since it's supposed to return a reference to the MM COM object either way.

In my case the erratic behavior was caused by stupidly naming my test application MediaMonkey (which was the test project name/folder), thereby causing mass confusion when it came to differentiating between processes. So kids, don't try this at home.

As far as talking to MM without starting it up ... do you mean talking to the API without MM actually -running- in the background?

Re: Getting active SDBApplication COM object

by Peke » Mon Feb 16, 2009 7:53 pm

I'm re reading this and as I'm not .NET dev I wonder what may cause your issues. Are you closing COM object Correctly each time prior to creating new one?
FindWindow Fixes all problems
Skinned version = Findwindow('TFMainWindow','MediaMonkey');
NON-Skinned Version = Findwindow('TFMainWindow.UnicodeClass','MediaMonkey');

Re: Getting active SDBApplication COM object

by flashk » Mon Feb 16, 2009 4:45 pm

mistresso wrote:Old post somewhat, but I wonder if anyone has an answer on this? In my recent .Net experiments, I have the exact same problem. To wit, if MM is not running when I start my app, when it gets to the "SongsDB.SDBApplication SDB = new SongsDB.SDBApplication();" line it will make a call to startup MediaMonkey and exit back to the .Net app just fine. BUT... if MM is already up ... I get a COM error, specifically 80080005 - which is a permissions error.

This isn't yet another VISTA issue either - I am running on XP SP3, and have not accessed any web browser windows. This is a simple matter of just talking to the SongsDB COM object. I know the "easy workaround" is just to shut down MM before running the app (or throw in a kludge like ignoring the exception), but there should be an easy answer to this.
I guess the easy answer is that this is not currently possible with MM. I've wanted the same behavior, but it seems that MM does not register itself with the global COM ROT (Running Object Table). As far as I know, that would be the only way to get a handle to the MM COM server without starting it up. Maybe one of the MM developers can shed some light on this issue?

Re: Getting active SDBApplication COM object

by mistresso » Fri Feb 13, 2009 9:12 pm

Old post somewhat, but I wonder if anyone has an answer on this? In my recent .Net experiments, I have the exact same problem. To wit, if MM is not running when I start my app, when it gets to the "SongsDB.SDBApplication SDB = new SongsDB.SDBApplication();" line it will make a call to startup MediaMonkey and exit back to the .Net app just fine. BUT... if MM is already up ... I get a COM error, specifically 80080005 - which is a permissions error.

This isn't yet another VISTA issue either - I am running on XP SP3, and have not accessed any web browser windows. This is a simple matter of just talking to the SongsDB COM object. I know the "easy workaround" is just to shut down MM before running the app (or throw in a kludge like ignoring the exception), but there should be an easy answer to this.

by jimbo11883 » Thu Jun 21, 2007 11:58 am

Steegy wrote:Why not use the ease of early binding (ok, it's an extra dll...). When you don't find MediaMonkey using FindWindow(), then nothing has to happen.
When you do find the window, you can instantiate a new SDBApplication Class object.

Apart from this, do you think that using late binding with MediaMonkey would enable .NET to properly catch the MM events?
I DO NOT want to create a new one, as it causes problems.
What kind of problems are these?

I'm just curious, because just like darchangel, I want to learn how to decently interact with MM through .NET.
I can't use early binding as it causes problems when the user doesn't have MM installed. As far as MM events go, I never used them before, so I don't know about problems with them. I don't want to use CreateObject() because that causes my app to freeze for some reason when MM is running before my app is.

by Steegy » Thu Jun 21, 2007 11:22 am

Stax, are you still around?

by darchangel » Thu Jun 21, 2007 10:29 am

@jimbo11883: Whatever you do/find with regard to this matter, PLEASE continue to report on it here. The MM+.NET knowledge here is thin. Aside from you, there's me, Steegy, and 1 or 2 other forum users who post about these issues. And some issues are still as of yet unsolved. If you figure out how to accomplish your above goal, it could help out some other pending issues sometimes discussed around here.

by Steegy » Thu Jun 21, 2007 9:39 am

Why not use the ease of early binding (ok, it's an extra dll...). When you don't find MediaMonkey using FindWindow(), then nothing has to happen.
When you do find the window, you can instantiate a new SDBApplication Class object.

Apart from this, do you think that using late binding with MediaMonkey would enable .NET to properly catch the MM events?
I DO NOT want to create a new one, as it causes problems.
What kind of problems are these?

I'm just curious, because just like darchangel, I want to learn how to decently interact with MM through .NET.

by jimbo11883 » Thu Jun 21, 2007 8:00 am

I've already tried all that. I specifically want support for the GetObject() way of getting an existing SDBApplication object. I DO NOT want to create a new one, as it causes problems. The app needs to be able to run on systems where MM is not installed.

Top