Hi all,
I was wondering if it was possible to "register" your own created c# program for OLE automation This would be the equivalent of accessing something in Excel via OLE. Like:
Dim ExcelApp As Object
ExcelApp = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
Edit: and just to clarify, I understand how the GetActiveObject works (by looking up the object in the Running Object Table). I guess I need to know if it is possible to register a program with the Running Object Table.

Possible to register a C# program to the R.O.T. for OLE automation?
Ramanujam Sampath
http://www.codeproject.com/dotnet/cominterop.asp
Yours,
Alois Kraus
dvh
Thank you again for all of your help. The article you linked helped some, but I am having issues with grabbing the interface of an already running object. I can use
objTypeNameVett = Type.GetTypeFromProgID("NameVett.MyForm1");
objNameVettLateBound = Activator.CreateInstance(objTypeNameVett);
status=(int)(objTypeNameVett.InvokeMember("getStatus",System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, objNameVettLateBound, inputParams));
and the code technically works. But, the result returned is incorrect, as the code creates an instance, when I need the already running instance. I tried using
objNameVettLateBound = Activator.GetObject(objTypeNameVett,"http://myip");
status=(int)(objTypeNameVett.InvokeMember("getStatus",System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, objNameVettLateBound, inputParams));
but the program crashes with this error:
I cannot tell if the error is being thrown by the C# application who's method I'm invoking or not. I am sure it has to do with me using the wrong method.
I am also not sure whether I should go ahead and create another thread about this or not, as you answered my original question.
g e o r g e
monikers[0].BindToObject(ibc, monikers[0], ref guid, out myProgObject);
now, when I run this command I get this error:
Michell Cronberg
http://msdn2.microsoft.com/en-us/library/tzat5yw6(vs.80).aspx
Yours,
Alois Kraus
Maheswar
Ok, now I've got it showing the methods within the interface. Now I just need to know how to use them.
Codeme
Corey
mrpu
With .NET you can create for all public classes of your managed dll COM wrappers by calling
TlbExp AssemblyName [Options]
which will create a type library which can be consumed by unmanaged C++ clients via the #import statement.
To register your public C# classes of your assembly you can call simply regasm /codebase <yourassembly> to register them as normal COM objects.
A managed (e.g. C#) interface can be registerd into the ROT by calling UCOMIRunningObjectTable.Register. The Running Object Table interface can be retrieved quite easily by calling the folling function via PInvoke:
[DllImport("ole32.dll")]
static extern int GetRunningObjectTable(uint reserved,
out System.Runtime.InteropServices.ComTypes.IRunningObjectTable pprot);
You can call Register with a moniker which you need to create befor you can use it. Then you should be able to get the COM interface from any running process you would like to.
This article should give you some insight into C# and Monikers:
http://www.codeproject.com/csharp/automatingvisualstudio.asp
Hope this helps,
Alois Kraus
george_v
You could simply create a new application where you do in the Add Reference Dialog select the COM tab where you select your previously registered managed COM object.
Now you can create with
new YourInterOpNS.YourClassNameClass();
a instance of your COM object. If this does work you know for sure that the object is correctly registered.
Yours,
Alois Kraus
rathlar
Did you run regasm /codebase YouAssembly successfully After this your objects should show up in the COM tab with some prefix which is not always easy to guess but they should be definitely show up then.
Janny
private const int ROTFLAGS_REGISTRATIONKEEPSALIVE = 1;
private const int ROTFLAGS_ALLOWANYCLIENT = 2;
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
private static extern UCOMIRunningObjectTable GetRunningObjectTable(
int reserved);
[DllImport("ole32.dll", CharSet=CharSet.Unicode,
ExactSpelling=true, PreserveSig=false)]
private static extern UCOMIMoniker CreateItemMoniker(
[In] string lpszDelim, [In] string lpszItem);
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
public static extern UCOMIBindCtx CreateBindCtx(int reserved);
public event MsgEventHandler MsgEvent;
bool myIsDisposed = false;
public bool IsDisposed
{
get { return myIsDisposed; }
}
int myCookie = 0;
public FormData()
{
MsgEvent = null;
AddToROT();
}
public IFormData GetActiveObject()
{
IFormData formdata = null;
UCOMIRunningObjectTable runningObjectTable;
UCOMIEnumMoniker monikerEnumerator;
UCOMIMoniker[] monikers = new UCOMIMoniker[1];
runningObjectTable = GetRunningObjectTable(0);
runningObjectTable.EnumRunning(out monikerEnumerator);
monikerEnumerator.Reset();
int numFetched = 0;
while (monikerEnumerator.Next(1, monikers, out numFetched) == 0)
{
UCOMIBindCtx ctx;
ctx = CreateBindCtx(0);
string runningObjectName;
monikers[0].GetDisplayName(ctx, null, out runningObjectName);
if( runningObjectName.StartsWith("!IFormData") )
{
object runningObjectVal;
runningObjectTable.GetObject( monikers[0], out runningObjectVal);
formdata = runningObjectVal as IFormData;
}
}
return formdata;
}
public void AddToROT()
{
UCOMIRunningObjectTable rot = null;
UCOMIMoniker moniker = null;
try
{
// Get the ROT
rot = GetRunningObjectTable(0);
// Create a moniker for the graph
moniker = CreateItemMoniker("!", item);
// Registers the graph in the running object table
int cookieValue;
// ROTFLAGS_ALLOWANYCLIENT|
rot.Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, (IFormData)this,
moniker, out cookieValue);
myCookie = cookieValue;
}
finally
{
// Releases the COM objects
if (moniker != null)
while(Marshal.ReleaseComObject(moniker)>0);
if (rot != null) while(Marshal.ReleaseComObject(rot)>0);
}
}
public void RemoveFromROT()
{
if (myCookie != 0 )
{
UCOMIRunningObjectTable rot = null;
try
{
// Get the running object table and revoke the cookie
rot = GetRunningObjectTable(0);
rot.Revoke(myCookie);
myCookie = 0;
}
finally
{
if (rot != null) while(Marshal.ReleaseComObject(rot)>0);
}
}
}
Yours,
Alois Kraus
lrryklly
JohnCP
If it is an access problem you could try the value ROTFLAGS_ALLOWANYCLIENT during registration to allow processes of other users to see your COM object.
Without further information it is quite difficult to diagnose your exact problem. Can you create an instance of your COM obect via C# without taking it from the ROT This test would ensure that nothing is wrong with your COM registration.
Please mark the answer to this question as answered if you think that it has solved your problem.
Yours,
Alois Kraus
Ampers
That does help a lot, thank you. Do you have a link actually showing an example of how to register a running object I found http://www.developmentnow.com/g/21_2004_5_0_0_105861/Register-an-Object-in-the-ROT.htm but I'm not seeing how I would tie my C# program into it. Thanks again.
Corey
Edit: I *think* my only problem is how do I create a moniker for my program
Edit2: Alright, I'm making progress. I've create the moniker and managed to implement it via
IRunningObjectTable table;
IMoniker moniker;
GetRunningObjectTable(0, out table);
CreateItemMoniker("!", "NameVett", out moniker);
table.Register(0, this, moniker);
now my next problem is when it registers the object, there is no name specified for it.(I want it to show "NameVett") How do I solve this issue I should also note that changing the second parameter is only changing the Hash Value of the object in the ROT.
Mark-Edgerton
Corey
Edit: I modified my code to:
[ComVisible(true)]
[Guid("{6C3CCB0E-8968-4724-A7F3-5C7CB3A2FD6E}")]
public interface _Form1
{
[DispId(0)]
int getStatus(String id);
}
[ComVisible(true)]
[ProgId("NameVett.Form1")]
[Guid("{7E1421B0-F480-4d59-A944-478D40E0ACE2}")]
[ClassInterface(ClassInterfaceType.None)]
public partial class Form1 : Form,_Form1
But it is still not appearing. I have also selected under the build options to make the assembly COM-Visible....the weird thing though is it requires yet another GUID there.