I have some VBA code that needs to talk to a running c# application.
For what it's worth, the c# application runs as a service, and exposes an interface via .net remoting.
I posted a question regarding a specific problem I'm having already (From VB6 to .net via COM and Remoting...What a mess!) but I think I may have my structure all wrong...
So I'm taking a step back - what's the best way to go about doing this?
One thing that's worth taking into account is that I want to call into the running application - not just call a precompiled DLL...
In the past, one way I accomplished something similar was with Microsoft Message Queueing. Both languages/platforms can read/write to a queue.
In my scenario, we had a legacy Access database that we had to maintain. We wanted to migrate away from it and replace it with a more robust .NET solution. To get real time data out of the current system into the new system, we added VBA code to write data to a message queue. Then we wrote a C# windows service to process that data in the new system.
I'm not entirely sure of what you're doing, so this may not be a fit, but I thought I'd mention it.
I've come up with a solution using my original structure...
That is, the VBA application calls a COM wrapper application that translates all of the types from .Net to COM safe types. This wrapper then calls the main service using .net remoting.
The problem I was having was that the common dlls between the wrapper and the service needed to be in the C:\Program Files\Microsoft Office\Office12 folder (along side msaccess.exe).
While I was using the AssemblyResolve method to provide the dlls at runtime, this wasn't working...So for now I'll just have to have the dlls copied to the folder - a far from elegant solution, but at least the communication is working for now.
Related
I've created a .Net app, hosted on a secure sharepoint. I want to be able to run this app via VBA (or other apps).
Through asking and research yesterday, I found this is easy to do via Shell filePath, vbNormalFocus - and I can even pass arguments to the app, but what I really want is to control the app as an object, similar to controlling a COM object. After researching and much confusion today I found I can't use COM because this isn't a class library - it's an .exe app (although I've learned SO much today!)
Imagine this type of deal:
Dim x as Object
Set x = Shell "filePath", vbNormalFocus
x.NotSureHowThisWorks
I want to start the app in my Excel environment, and make many calls to and from the app, to give it instructions. The calls could be strings or whatever but the point is I need the running app coupled to an object variable in the VBA code so I can repeat calls and receive responses.
Is this possible?
Since the app is yours, the most simplest thing you can do is to break your app into 2 projects; one DLL and one EXE project. Have the EXE project reference the DLL for all the functionalities, and make the DLL COM-visible then just reference that DLL from your COM application.
If it's meant to be a shared process, then it might be simpler to just run it as a service rather than an .exe.
My work has an application written in VB6. I am tasked with writing another, different, application in C# .NET. I am not allowed to change the VB6 code, but I need to call a function (from my .NET application) every time a particular function gets called in the VB6 application.
My boss recommended using COM or DCOM for this task. I am not familiar with either of these topics, and am having trouble finding a tutorial that I can understand easily and that relates to my task.
Can I do this using COM or will I have to modify the existing VB6 code?
You need to expose the function in VB6 as COM (ActiveX DLL). This is straight forward.
http://vb-helper.com/howto_activex_dll.html
Calling a COM Object is easy too.
http://www.c-sharpcorner.com/UploadFile/psingh/CallingCOMComponentFromCSharp12022005231615PM/CallingCOMComponentFromCSharp.aspx
It sounds to me like you have a VB6 application whose source code should not be changed. Now every time a method in the VB6 application is called you also want to call a method in another component (C#).
The above is an assumption since your question is not 100% clear.
If that is the case and you can't change the VB6 application then you might be able to do something using COM Channel Hooks (assuming the VB6 app is composed of COM objects).
But that would be using C++ and low level COM which is probably something you don't want to do.
I think you are asking about invoking a method from your C# application from within your VB6 application. So we are talking about some form of inter-process communication (hence the comment about DCOM).
I've used .NET Remoting to replace DCOM in some applications by creating a COM-callable .NET library to act as the client with the remoting objects being hosted in a .NET application. Your VB6 application uses the objects, and the methods execute on the server.
BUT you will have to modify your VB6 application, at least a little, to inject the new calls to your .NET. Can you be more clear on the requirements to not change the VB6 application?
I have searched quite a lot of places and I only found one GINA replacement called pGINA but it is in C++ which I don't know at all.
Does anybody know one in either C# or VB.NET?
(I'm writing software for use at work to control what employees are doing)
Hosting .NET in Winlogon (where GINA dlls are loaded) is probably not such a hot idea- could cause all sorts of conflicts if something else decides to do the same thing, and if you trash winlogon, you're not getting anywhere with that PC. Also, GINA has been replaced as of Vista with ICredentialProvider (see here)- so your investment would be lost as soon as you move to a newer OS. Even there, the same thing applies: custom credential providers are loaded into Winlogon, so probably not a great idea to use .NET there.
Regardless, both of these are intended to support custom authentication modules, not "controlling what employees are doing". There are other ways to run software on the logon desktops, if that's what you're trying to do.
All that said, if you still want to try it, you'll need an unmanaged shim DLL, C++/CLI or some IL hacking (see here) to export the GINA functions because C# can't directly export DLL functions. A pure managed C# solution isn't possible.
To expand on nitzmahone's eexcellent points:
Completely replacing GINA is really a no-no using managed code. OTOH, it is quite possible to write a replacement GINA in C++ and have it call .Net code to do the grunt work.
Some years ago I used this technique to replace the CTRL+ALT+DEL screen with a fancy news service. My custom GINA was a proxy for the standard GINA. Most of the time it transparently passed calls on to the standard GINA. The exception was that it ran the .exe for the .Net app instead of displaying the ALT+DEL+CTRL screen, then waited for the .exe to terminate before displaying the logon screen.
With regret, I abandoned the project when it was clear that the work could not be directly applied to Vista.
I know how to create a COM DLL (a Class Library) in C#. Is it possible to create a COM Surrogate EXE using C#?
This would be a standalone server capable of launching and hosting COM objects, which would then be accessible to COM clients.
The default surrogate process for COM - the thing that hosts COM DLLs, aka the COM Surrogate - is dllhost.exe. It is possible to create a surrogate process in C++. This article explains how.
But those APIs are not exposed in wrappers as part of the base class library in the .NET Framework. If you want to write to write only managed code, you need something else.
I see a couple options.
The Visual Studio SDK, a free download that is intended for devs who want to extend Visual Studio. Within that SDK, there's a class lib that has such wrappers. In particular, look at the ISurrogate class.
BUT, the VS SDK license says that the SDK is ok to use only for products that extend or add value to Visual Studio. I am no lawyer, but that is my understanding of the license, which is pretty clear. These terms means the VS SDK would not be useful for general app building.
The one remaining question is, exactly how do you use the VS SDK technically to produce a COM Surrogate using only C# code? Again, here I don't know. I looked in the docs briefly for guides on using the ISurrogate wrapper, but found none.
Use the code in this article.
The article explores a bunch of different aspects around COM and .NET interop. Towards the end of the article it offers source code for building your own COM server in C#, complete with all the p/invoke calls to CoRegisterClassObject() and friends.
I wanted to make same thing and found excellent project example CSExeCOMServer on All-In-One Code Framework. It actually reconstructs normal COM server logic by means of .NET and native calls to Windows API. But it looks all still overcomplicated. I suppose there is no simple and fast way to expose .NET objects as COM in out-of-process server and it is not the architecture of choice.
One option, if you want an out-of-process COM component, is to host a dll in COM+ via serviced components. This only supports dll though, but you could write a shell exe (for standalone use) that simply defers to the dll.
Not quite as simple as VB, but it works.
I do remember somebody showing me a more direct way (no COM+), but I can't for the life of me remember what it was...
I am trying to implement an "out of proc" COM server written in C#. How do I do this?
I need the C# code to be "out of proc" from my main C++ application, because I cannot load the .NET runtime into my main process space
WHY?:
My C++ code is in a DLL that is loaded into many different customer EXE's, some of which use different versions of the .NET runtime. Since there can only be one runtime loaded into a single process, my best bet seems to be to put my C# code into another process.
You can create COM+ components using System.EnterpriseServices.ServicedComponent. Consequently, you'll be able to create out-of-proc and in-proc (client) component activation as well as all COM+ benefits of pooling, remoting, run as a windows service etc.
Here we can read that it is possible, but the exe will be loaded as an library and not started in it's own process like an exe. I don't know if that is a problem for you? It also contains some possible solutions if you do want to make it act like a real out of process com server. But maybe using another way of inter process communication is better. Like .Net Remoting.
I cannot recommend this as the way, but you could create a COM-callable wrapper for your C# library, then create a VB6 ActiveX exe project that delegates calls to your C# library.
Why can't you load the .net runtime into you process space? It is possible to host the .net runtime and call into .net using COM.