Getting active SDBApplication COM object
Moderators: Gurus, Addon Administrators
-
- Posts: 3
- Joined: Thu Jun 21, 2007 7:07 am
Getting active SDBApplication COM object
I'm developing an application with a feature that has simple playback controls for MM, and shows the current song and playback time, etc.
The way my app works, is that it will check for the MM main window by using FindWindow() API call. If the window is found, then it will obtain a reference to MM's SDBApplication object by using the GetObject() function built into VB.Net. This is called late binding. The reason I am using late binding is because it seems that referencing the type library means that the end user would have to already have MM installed on their computer to use my app. My application does much, much more than just work with MM. It also can control Foobar2000, Winamp, WiMP, for example.
To make a long story short, I need to be able to access the SongsDB.SDBApplication COM Object so that I can get information and send commands to MM. I need to be able to do this by using GetObject(). This method works fine with foobar2000 and the COM server plugin for it.
So can you make a SDBApplication instance available system-wide for use with GetObject() by creating the instance and adding it to the COM ROT?
Thanks.
The way my app works, is that it will check for the MM main window by using FindWindow() API call. If the window is found, then it will obtain a reference to MM's SDBApplication object by using the GetObject() function built into VB.Net. This is called late binding. The reason I am using late binding is because it seems that referencing the type library means that the end user would have to already have MM installed on their computer to use my app. My application does much, much more than just work with MM. It also can control Foobar2000, Winamp, WiMP, for example.
To make a long story short, I need to be able to access the SongsDB.SDBApplication COM Object so that I can get information and send commands to MM. I need to be able to do this by using GetObject(). This method works fine with foobar2000 and the COM server plugin for it.
So can you make a SDBApplication instance available system-wide for use with GetObject() by creating the instance and adding it to the COM ROT?
Thanks.
-
- Posts: 26
- Joined: Wed Nov 30, 2005 11:23 pm
I don't know how to do this with GetObject but it can be done with CreateObject: external scripts and applications
Right now I'm working on a .NET project very similar to yours. If you can figure out how to use a reference to MediaMonkey and not get a COM server warning when everything is shut down, please let me know. I can't figure out how to do so.
Also check out this thread. It may save you some headaches and you may be able to help with some of mine.
Right now I'm working on a .NET project very similar to yours. If you can figure out how to use a reference to MediaMonkey and not get a COM server warning when everything is shut down, please let me know. I can't figure out how to do so.
Also check out this thread. It may save you some headaches and you may be able to help with some of mine.
-
- Posts: 3
- Joined: Thu Jun 21, 2007 7:07 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'm just curious, because just like darchangel, I want to learn how to decently interact with MM through .NET.
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?
What kind of problems are these?I DO NOT want to create a new one, as it causes problems.
I'm just curious, because just like darchangel, I want to learn how to decently interact with MM through .NET.
Extensions: ExternalTools, ExtractFields, SongPreviewer, LinkedTracks, CleanImport, and some other scripts (Need Help with Addons > List of All Scripts).
-
- Posts: 26
- Joined: Wed Nov 30, 2005 11:23 pm
@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.
Stax, are you still around?
Extensions: ExternalTools, ExtractFields, SongPreviewer, LinkedTracks, CleanImport, and some other scripts (Need Help with Addons > List of All Scripts).
-
- Posts: 3
- Joined: Thu Jun 21, 2007 7:07 am
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.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?
What kind of problems are these?I DO NOT want to create a new one, as it causes problems.
I'm just curious, because just like darchangel, I want to learn how to decently interact with MM through .NET.
Re: Getting active SDBApplication COM object
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.
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.
Re: Getting active SDBApplication COM object
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?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.
Re: Getting active SDBApplication COM object
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');
FindWindow Fixes all problems
Skinned version = Findwindow('TFMainWindow','MediaMonkey');
NON-Skinned Version = Findwindow('TFMainWindow.UnicodeClass','MediaMonkey');
Best regards,
Peke
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
How to attach PICTURE/SCREENSHOTS to forum posts
Peke
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
How to attach PICTURE/SCREENSHOTS to forum posts
Re: Getting active SDBApplication COM object
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?
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
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:
Results with the following output, if MM is already running:
If it is not running the method ConnectOrCreateMediaMonkey starts MM.
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);
}
}
Code: Select all
Connecting to MediaMonkey COM Appliation Object via Marshal.GetActiveObject...
Failed to connect to MediaMonkey COM Appliation Object.
Vorgang nicht verfgbar. (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 verfgbar. (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.
Re: Getting active SDBApplication COM object
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
does work now. Another variant that does work identically is:
Both calls create the COM-Object, if it is not running.
The Wiki instructs to use:
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:
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();
Code: Select all
SongsDB.SDBApplication SDB = (SongsDB.SDBApplication)Microsoft.VisualBasic.Interaction.GetObject("", "SongsDB.SDBApplication");
The Wiki instructs to use:
Code: Select all
SDB.ShutdownAfterDisconnect = false;
- 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
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
For my WebSourcesTagger I used this code:
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
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;
}
}
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
Hi Steegy,Steegy_ wrote:For my WebSourcesTagger I used this code: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.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; } }
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
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.
- 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.