What is an OLE Automation object: wikipedia says:
is an inter-process communication
mechanism based on Component Object
Model (COM) that was intended for use
by scripting languages – originally
Visual Basic – but now are used by
languages run on Windows.[3] It
provides an infrastructure whereby
applications called automation
controllers can access and manipulate
(i.e. set properties off or call
methods on) shared automation objects
that are exported by other
applications. It supersedes Dynamic
Data Exchange (DDE), an older
mechanism for applications to control
one another.[4] As with DDE, in OLE
Automation the automation controller
is the "client" and the application
exporting the automation objects is
the "server".
My question is:
Is it possible to use a C# code, (seems only C++) (wich uses several other C# includes) and call a them in a Stored Proc.
Is it possible to read a table with these Object?
Is it possible to compute things with that object, with table data?
What would be the steps?
Well, if you're using MS SQL Server 2005 or later, you can set up what's called a "CLR Stored Procedure", basically written in C# and able to reference other .NET assemblies. This would remove any need to refer to a .NET assembly using COM. More info: http://msdn.microsoft.com/en-us/library/ms131094.aspx
AFAIK, COM's COM; the idea is that messages are passed at the OS level between the client code and server control, and the client doesn't have to know any specifics of the server implementation; just the "front door" interface. So, if you had to use COM, you should just be able to register your .NET assemblies for COM (the main change is just a switch in the Build tab of the project's Properties view in VS), and then use them as if they had been written in C/C++, VB, Delphi, or whatever.
Related
I'm building an add-on UI system in VB.NET (Visual Basic specifically) that uses data from a legacy Microsoft Access system (that will at least for some time needs to be useful via its old, internal UI). I can do pretty much everything I need to do from VB.net - work with the data tables, call Access functions that contain decent functionality, etc.
What I'm trying to figure out is if Microsoft Access can call back to VB.NET (e.g., perhaps allowing me to pass in a function reference to be invoked).
The specific motivation is that there are 2 or 3 time-consuming Microsoft Access functions that produce critical output data - if you were invoking them directly via the MS Access interface, you would see things like progress bars and the occasional text update on a form of the work phase, progress %, etc. I can modify the MS Access code not to do these things if called from VB.net, but I'd really rather have the MS Access code reach back into VB.net so that I can provide some progress feedback in the new interface.
An elegant solution would be, as alluded to above, have VB.NET pass in the function delegate for MS Access to call - but as these are entirely different memory spaces, etc., I would think some internal framework would be required to get such a thing to work - perhaps via a shared DLL in some manner. I could go the old "polling" route, wherein MS Access writes out status to a table, and the (asynchronous) VB.NET app polls that table and uses what's there. That seems like such an inelegant hack, unnecessarily wasteful in resources and potentially bug prone, that I hate to go that route. If I could build just one function that MS Access could use, something that just passes a status string back, I think that'd cover the vast majority of cases.
Any suggestions would be most welcome.
I often create COM objects in .net for use with Access. Thus in your access code you could MOST certainly have the process loop “call” the .net object to update the process.
However, you likely are automating a copy of Access, and thus would like Access to call a routine in the EXISTING automation client, not have an instance of Access call a custom .net object. However, I think building a custom .net object would be the least work and hassle. In other words, you flip your approach around. You launch Access first and it uses your .net application as a COM object. That way, any routine in your application would be useable and callable from Access VBA.
The ONLY reason why I would walk down the road of implementing a call back if the main .net app REALLY needs to receive messages from Access as opposed to Access simply calling + using a custom .net object to display the process information. (so VERY easy to build a .net object for showing progress).
So best bet is to adopt the idea of turning your existing application into a COM object to be consumed by Access. This is VERY easy.
Once you do above, then
Access is launched first and then creates the instance of your application. (and thus can call/use any .net sub or function expose in your .net application from VBA).
And even if you don’t launch Access first, Access on startup could grab a running instance of your application (just like you can pick up a running instance of Excel or Word in Access/VBA).
Last but not least;
You probably can implement call backs, but I simply don’t know if this is possible without having to create a .net COM object as a go-between. As such, likely best to have Access just pick up a running instance of your .net application anyway.
So I would expose your .net application as a COM instable object.
So least amount of work would be to create a separate .net COM object that access uses, but if you assume for future that VBA should be able to call any vb.net routine then I would thus just build your .net application as a consumable COM object.
I was searching MSDN and several other Access forums for creating custom Access API's, but didn't see anything related. Is this possible? Can custom ODBC's be created for Access?
Hum, this is confusing since it not clear if you are talking about building interfaces with Access to OTHER systems, or are you talking about a building an Access interface that other programs can use?
ODBC is a "driver" provided by vendors to allow use of their SQL database systems and is something that you don't create in Access or FoxPro or in VB for that matter. In fact I can't think of any data centric tool that would allow you to build your own ODBC driver. So this suggests some confusing here.
Extending Access.
Access for the last 20 years has had the ability to consume ActiveX (COM objects). So how one extends the ability of Access to communicate with other software and systems REMAINS the COM object choice. So for example one can use the MSXML library from Access (a COM object) and this allows one to consume web pages, and specify XML which opens the door to consuming web services. In fact I used MSXML to consume SharePoint web services for example.
However for consuming web services it is usually far better to build COM object with tools that can "already" consume web services. So one would use vb.net to create a COM object and THEN reference that COM object from MS Access (so just like we set a reference to outlook or word from Access, such COM objects are not limited to applications you purchase, but you are most free to create your own COM objects VB6, vb.net, c# or whatever).
Access does NOT have the ability to create ActiveX (com objects), but it certainly can consume ones you build in other languages.
NOTE: I am using the term ActiveX and "COM object" interchangeability here – they are the same basic technology.
So if you ever used a desktop computer and any windows development tool, you find that "COM" objects are the choice and REMAIN the choice of how to extend Access, or even that of VB6. With managed code, things change somewhat, but vb.net is quite happy to create COM objects that work well with Access.
While Access cannot as a tool create ActiveX (com) objects, you can certainly compile Access code into an accDE and THEN reference that library code from the VBA tools->references. So you can extend and share VBA code in one library with "many" applications, but this is not a com object.
So just like in the past to extend desktop programs, you can build such extensions as COM objects and consume them from Access – this is the standard approach to extend Access to say consume web services.
Access cannot be used to build individual COM objects as UI parts, but the STANDARD means in our industry to create COM objects is able to be consumed by Access.
Last but not least:
Any application you build in Access CAN BE CONSUMED as a COM object by other applications. So while you cannot build individual COM objects, your WHOLE application is in fact a com object.
So if you build an Application in Access then using Excel, VB6, FoxPro, another Access application, C++, or C# or vb.net? They ALL CAN consume your application as a com object by simply creating an instance of Access and your application.
So any development tool that supports "com" can consume your application as a com object. So any standard development tool, article or system for the last 20 years can consume your Access application as a COM object.
So while Access cannot create individual COM objects, the resulting Access applications are in fact a legal com objects that ANY application that supports COM can create an instance of your application. This means your code and VBA subruties etc. are callable from the host application that created the instance of your application. In theory any VBA code exposed as "public code" are thus able to be called from that other program.
So the "interfaces" available to Access remain the SAME as the near 20 year history of MOST desktop programs running on windows – that interface is COM.
So you have 20 years of history and 20 years of examples on the internet to have fun with - any example that shows how to create and consume a com object should work for your access application.
I understand that COM is really a way to program (i.e. like structured programming, or OO programming). However it is a little old. So I was just wondering what has really replaced this set of specifications? Will I find this in .NET documentation?
COM has not been replaced. The Component Object Model is a core part of Windows and will remain so for the foreseeable future.
COM provides you with one mechanism of inter process communication (communicating between applications on a machine), it is also used as a much simpler (for the consumer) system of sharing dlls. Its COM (or ActiveX, or OLE - all the same) that enables VBA to work so well in MS Office, it is the foundation of ActiveX controls.
COM is not a way to program (unlike OOP etc) it is a technology that works on windows to make access to other applications during runtime easier.
.NET can use COM object with wrappers, and if you want to allow any app to access your functionality, its still best to provide a COM wrapper.
Other methods of inter app coms now exist such as ZeroMQ.
The original specification for COM is old in age, but the specification as well as the concepts are still in use, and you can still create and consume COM objects.
For .NET, you can start by looking at the following links:
Com Interop Part 1: C# Client Tutorial (C#) # MSDN
Interoperating with unmanaged code # MSDN
In addition, there are other specs that are very similar to COM or have semantics that are the same. Most notably, XPCOM is in use in FireFox for their plugin spec and also used internally to FireFox to connectable objects.
XPCOM # MDN (Mozilla)
WinRT is an upcoming platform update for windows that is also heavy in COM concepts.
There are some useful here: Why is WinRT unmanaged # StackOverflow
For .NET developers, a lot of the declarative overhead is hidden as mentioned here: WinRT demystified - Miguel de Icaza
The head of the spec is here: The Windows Runtime # MSDN
And in the context of COM, developing WinRT components with C++ has similarities, although some syntax is borrowed from managed C++: Creating Windows Runtime Components in C++ # MSDN
It's hard to explain our situaction.
We have a 3-tier application. The engine is a DLL coded in C++, then we have a VB6 ActiveX EXE that access to the engine via API calls, and at the top level we have a Excel Addin (in C# using VSTO framework) calling the middle layer with an interop DLL. At this time, each "connection" from the Addin to the engine creates a new EXE (VB6 uses API calls to access to the engine) and all works fine.
Now we are moving the middle layer to .NET, it works 'presumably' fine (it pass all our Unit test) but, we found an error when we open 2 "connections" at same time (ups, no unit test check this situation because it's a new behavour). The DLL have static objects that it's shared over all instances in the same process and we have interactions between "connections". In our old version each "connection" creates a new EXE with no memory sharing between processes, now it's the same process and they share memory and the static objects.
Following the tips from this question. We tried to build a COM EXE in C# to do an out-of-process objects in the middle layer but we have the same result. They share the static objects, at the end, each connection not creates a independent process.
It's clear, but not affordable at this time, moving API calls to ATL or changing the static objects to instanciable references with a handle and change all the API calls to get/set this handlers. I reviewed all examples in MS All-in-one but I didn't find any solution. Neither it's possible to keep only one connection at time, each workbook can have one connection and in the future we want to explore a Web application with multiple connections at same time.
Any suggestion?
Thanks in advance,
Whether COM starts new EXE per each COM object, or uses single EXE to instantiate all the object is controlled by flags parameters passed to CoRegisterClassObject. See
http://msdn.microsoft.com/en-us/library/ms693407(v=vs.85).aspx, and
http://msdn.microsoft.com/en-us/library/ms679697(v=vs.85).aspx
You need to pass REGCLS_SINGLEUSE or REGCLS_MULTI_SEPARATE flags.
Now, the trick is to pass this flag, as you might not call this method directly - the details depend on how you implemented the COM EXE.
it's not clear from the question, but it sounds like the "middle layer" you have was built as a VB6 EXE, and you're trying to replace it with a .net DLL. If that's the case, you'll definitely get the behavior you describe.
With a VB6 EXE com project, instantiating a new object starts a new process. With a .net dll (or a Vb6 dll really) you +won't+ get a new process.
You'd either need to create a .net EXE that exposes COM objects just like your VB6 exe does, or (sounds like you've already investigated this) you'll need to refactor your EXE objects to properly handle multiple instances within a single process.
Honestly, it'd probably be better to do that latter, since relying on singletons like this is generally a bad code smell. But it a pinch, you should be able to replicate the behavior of the VB6 exe with a .net project. You just can't do it in a dll.
Was your middle layer created in .Net? If it was, you might be facing the issue that your COM class is been created as a native .net object instead of a COM object. The solution usually involve using Primary Interop Assemblies. Take a look on this SO question to see if it matches your problem.
I can't wrap my head around the differences among these terms.
Are COM and ActiveX synonyms?
Is ActiveX object just a COM object that exposes IDispatch?
Lots of older MSDN pages mention IDispatch without any COM context. Does it have a separate history, and was just introduced under the COM 'umbrella' later in its lifecycle?
Where does OLE fit in? Is its (considerable) presence in MFC naming and MSDN in general - all just legacy?
Wikipedia gives some insight, but not much. I couldn't find a more in depth reference.
Found some quotes from COM Programming by Example:
Another thing you'll quickly find with
COM is that marketing had a field trip
day with the terminology. Rather then
helping to promote understanding,
you'll find in most cases it promotes
mystery. ... OLE, ActiveX, Remotable
Objects - which one means what this
week? ...
COM evolved out of the solution to a
specific problem - how to allow a word
processor to edit the spreadsheet in a
letter without the user having to exit
the word processor to do it. This
solution was called OLE. ... However,
with the second release of OLE (OLE2),
its creators modified OLE32.DLL to
expose more of the basic functionality
of OLE so that its API could be used
to allow any application to acess the
functionality of another. This API,
which hasn't changed much since 1993,
is what is considered to be the COM
API.
...
Once the COM API was exposed,
Microsoft used it to create what were
then called OLE controls to allow
sophisticated controls (e.g., buttons
that spiral, list boxes that play
music) written in Visual C++ to be
accessible to Visual Basic
applications. Eventually this same
technology was used to allow a control
to be downloaded and used by your web
browser. At this point, the name
changed to ActiveX controls or just
plain ActiveX purely for marketing
reasons. Although you can package any
functionality in an ActiveX Control,
its requrirements have been
specialized for supporting a user
interface control.
I'm still curious about the very last sentence - must a COM object satisfy some additional requirements to qualify as an ActiveX control? - but its enough to let it go.
Thanks for your answers!
ActiveX is marketing-ese for COM, although ActiveX is usually used in the context of "ActiveX controls" which are GUI objects.
IDispatch is an interface implemented by COM objects so that client programs can call its methods dynamically at run-time (late-binding), as opposed to at compile time where all the methods and argument types need to be known ahead of time.
OLE is the earlier version of COM.
Regarding OLE: COM has its roots in OLE. But today, OLE may be considered to be built on top of COM and is mostly used for what its name suggests -- document linking and embedding. While COM itself defines only a couple of interfaces itself (IUnknown, IClassFactory, IMalloc etc), OLE adds a whole bunch of additional interfaces like IMoniker, IOleItemComtainer, etc.
To sum up: COM is the foundation, ActiveX and OLE are layers on top of COM.