Synchronize to Form Thread - without usinig Form - vb.net

using Windows Forms it is possible to synchronize incoming data (like from events) which runs on another thread as that one which has created the form. However it is not allowed to update the form directly, therefore InvokeRequired and Invoke are used. Works great for me.
Now I want to move the logic part of my application (contains serial, networking, ... hence the threads) into a library. Also I want to have the synchronization in there, so there is no need to take care about that externally.
For now I create and pass a dummy form to my library, which is ugly, but works. At least some kind of. .Net Core has no Windows Forms. (3.0 has, but Windows only).
Even after reflecting the Form class I was not able to reproduce the synchronization process, so I could add it to my classes.
Does anyone know how to archive the same behaviour without Windows.Forms?
I use .Net Framework 2.0 and VB.Net, but C# examples are welcome as well

Related

VB.NET talking with Microsoft Access - can one do callbacks?

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.

Adding a COM interface to an existing application (EXE)

I intend to add a COM interface to an existing application (which, by the way, is written in C++ using Win32). I have some experience using COM objects, so I know the basic COM concepts of interfaces, etc., but this is the first time I'm actually implementing a component.
Ultimately I want to be able to use the COM interface to automate my application from scripts such as VB. I understand that there are two steps:
My application must act as an out-of-process server (i.e. I have to use MIDL and generate code for a proxy DLL and a stub DLL).
Once I have the server I can add automation capabilities by implementing the IDispatch interface.
Since the server-in-an-EXE thing with MIDL and what not is already a bit steep, I wanted to get a grasp on all that first before moving on to IDispatch.
I am reading the book "Inside COM" by Dale Rogerson and have completed the chapter on servers in EXEs (the following chapter will cover Automation).
The "Servers in EXEs" chapter provides example code that implements a server and a client. But it is necessary to start the server manually. This confuses me. Obviously, when my application (= server) is used by a client process, this extra manual step should not be necessary. Is there no mechanism to start the server automatically? Or is automation necessary to achieve that? At the moment, the prospect of having to start my server manually (once I even have one) makes me doubt I am moving in the right direction.
Hopefully someone with more knowledge of this can see what information I'm missing and point me in the right direction.
No, COM servers are not normally started by hand. Not sure why the book proposed it, possibly because it wanted to avoid talking about the registry keys you need to allow COM to automatically start the EXE. It isn't otherwise very complicated, you register the Application coclass of your app with the LocalServer32 key value giving the path to the EXE.
It is however not completely uncommon, especially with an existing program. One design decision to make is whether you let the client code completely control your program. Or if your program already has an existing user interface but you also want to expose services to other code. In the latter case it makes sense to let the user start the app by hand, like she'd normally does.
When your application is registered as LocalServer32, it will be invoked with the commandline specified there if no running process has registered a factory object for your CLSID yet.
This way, you can get the best of both worlds -- if the application is running already, this instance can provide the server side, and if it isn't, it will be started.
Automation is completely orthogonal to that -- your component becomes Automation compatible by implementing IDispatch.

.NET out-of-process COM objects sharing static instances in API calls

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.

VB: get compiled DLL's calling application info; COM security

Through COM, one can potentially gain absolute control over a target system. For example: using javascript's ActiveXObject object in IE, one can create certain objects which were designed to have direct access or interaction with system properties and files. One would think common sense dictates users disable ActiveX features in IE immediately after installing the browser to ensure their system is protected while surfing the net, or at least paying close attention to which websites they permit. But, I doubt many average PC users know how or why to do this, or just get tired of mirco-managing it over time. I think any PC user or admin my COM class caters to would greatly appreciate not having to deal with that. Thankfully it looks like IE versions come packaged with ActiveX disabled by default nowadays.
I've built a very versatile COM class library in VB. I didn't intend for it to be callable from any website, but that feature is just part of the COM platform. I'd like to prevent the library from being called from IE unless the website is on a white-listed domain to proactively protect the user (and ultimately their entire intranet) from harm from malicious websites. What would be the best method in VB.Net to tell which application called my DLL, to be able to tell if it was called from any command or process originating from IE? And, what domain called my dll?
Edit: I believe this might be a duplicate. See: Calling Assembly to get Application Name VB.NET
System.Environment.GetCommandLineArgs()(0) gets me the calling application path. With this info, I can compare it to a black/white-list of applications. Problem solved for now.
Don't mark the control as Safe for Scripting.
Default security settings will not allow such controls to be scripted.
Self-answer, and possibly duplicate, I suppose. See System.Environment.GetCommandLineArgs()(0) from Calling Assembly to get Application Name VB.NET
In this case, the class never was marked as safe for scripting and the intent was already never to mark it safe. The issue was how to obtain the calling application info so I could add additional security measures in case those which the calling application had were not enough.

RoutedCommands in Silverlight

Is it possible to use RoutedCommands such as ApplicationCommand.Copy, ApplicationCommand.Paste, etc in Silverlight 4 beta version ?
No, RoutedCommands are not supported in Silverlight although the primitive ICommand is. Silverlight 3 had ICommand but never used it anywhere. Silverlight 4 adds support to button controls to have an ICommand associated.
However, the full featured routed commands are not supported. They were not particularly useful in WPF anyway because they placed the burden of handling the command logic on the UI control that handled them. As it turns out, it is far more useful to have an ICommand exposed from the ViewModel.
Check out http://www.codeplex.com/compositewpf for the Prism project which includes some very useful classes such as DelegateCommand.
Having said that, commands like Cut/Copy/Paste are different from most commands because they are a generic command that usually applies directly to the control upon which it's executed. This is much different from a Save command for example which has a very specific meaning to the application behind the UI. For these clipboard related commands I'd say it's fine to break from the traditional separation patterns and write some UI-specific code in the code behind and use FocusManager.GetFocusedElement() to figure out which control you need to operate on.