How to force process isolation for an out of process COM server? - com

I'm writing managed code that has to interact with a vendor's COM automation server that runs out of process. I have found that this server becomes unstable if more than one client connects to it. For example, if I have managed code in process A and managed code in process B both connecting to this COM server, a single process will be spun up for the COM server and it's behavior is less than reliable. I'm hoping there's a way to force a separate process for each client - server connection. Ideally, I'd like to end up with:
Managed Process A talking to COM Server in process C1
Managed Process B talking to COM Server in process C2
One thought that came to mind was that if I ran process A and process B with different security identities, that that might cause the COM infrastructure to create separate server processes. I'd rather not go down that road, however. Managed Process A and Managed Process B are actually Windows Services. And I'm running them with identity Local System (because I need them to be able to interact with the desktop, and you can't check the "Interact with Desktop" box on the services applet for services that don't run as Local System). And the reason I need to interact with desktop is that this COM server occasionally throws up a dialog box on the screen and if the service itself cannot interact with the desktop then the COM server is spawns can't display the dialog (I believe it is displayed on a hidden WinStation).

Place the component registered at COM+, this put an isolation layer at your.
Use : Control Panel->Administrative Tools
or cmd/execute DCOMCNFG
Component Services->Computers->My Computer->COM+ Application, right click, new application, next, Create an empty application, enter app name “COM+ your.dll”, next, select Local Service, next, next, next, finish.
In new item made, expand, at Components, right click, new component, next, select Install new component, select your component.
Click Component properties, tab Identity, select System Account.
For errors in calls see Event after.

It's been a while since I've done this, so my memory is hazy.
If you configure the OOP COM server as a DCOM server using the DCOM config tool, I believe you can specify the isolation level. I did this years ago with a non-threadsafe in-process DLL that needed to be accessed in a threadsafe fashion from IIS and it worked a charm.
Let me know if it works for you :)

Your best bet would be to get the vendor to fix the component. After all, if it won't handle multiple clients, there could be other bugs lurking. If you can't do this, there are some other things to try.
With in-process COM objects I've had occassion to manually load the dll and access the interfaces directly without going through COM.
I haven't done this myself with out-of-process COM, but there are some things you could try. Ultimately the library is just a process sitting there receiving messages which invoke functions.
You might be able to manually start the a new copy of the process for each client and then send it messages. You may run into some hiccups with this. For example, the process may check to see if it's already running and refuse to start or otherwise be unhappy.
If you have a known upper limit on the number of clients, another approach you could consider would be to make multiple copies of the original .exe file and then use binary patching (something similar to the detours library from Microsoft Research) to override the COM registration functions and register each copy as a separate COM object.

Related

Debug .NET com dll when running from Access

I have a com dll developed in VB.net that provides an interface to eBay api's. Been working for many years. Recently eBay change certificate authority and moved to TLS 1.2. Sorted through that but now the dll seems to quit in mid transaction when called from Access. The functionality does listings from local inventory to eBay. The first part loads pictures of the listing item to eBay. That works fine. I can see the calls and responses using Fiddler. It then moves on to actually listing the item which seems to stop when called from Access. What I get back in Access is "Can't find x.dll at file location". I know the call is going to the dll because it uploads the pictures.
I have a test project developed in VB.net to test the dll and when run from that everything works. I can see the listing call and response in fiddler. When run from Access there is no listing call. I can verify that the endpoints for the calls are the same from test project or Access.
My question is how to debug the dll in the Visual Studio IDE when it is called from Access. Any thoughts?
Yes, the way you do this is open up the vs class you have for the .dll.
Then in debug of the project, setup this:
Now, when you hit f5, then access will launch and run.
If at this point, say you close access (exit), then you note the debugging process stops.
However, go though the forms and whatever in Access, and get to the point where you hit that button or whatever.
You find now that you can say set a break point and even step and debug your .net code like any other code. So say in my example (a custom sage 300 .net interface to access), I want to debug "find customer" routine from VBA.
Well, in vb.net I have this code:
so, when any routine - even those in the class instances is called, you can set break-points etc.
And to stop? Just exit access.
So, you can make a change to your code, and even hit f5.
It not clear how you are registering your .dll (or do you use some VBA to side-load the .net - that's what I do, since it is a pain to have to register my .net com objects on each PC.
But, do give the above a try. It should let you debug your .dll code. The trick is to have VS launch ms-access as a attached debug session - and that is exactly what the above setting in your class project above allows you to do.
do note in above, I used the path to access 2010 (access 14), so replace the path name to the access.exe with your version of access you are using.
And keep in mind, that if have some installer, or some custom "thing" that registers your .net .dll for you?
Well, during this process, if your VBA assumes a registered com object, then ensure you have this check box enabled:
On compile for the project settings, you thus want this option checked:
NOTE very careful, checking the above option does not change the code or anything at all - it ONLY does a regasum automatic for you, and this would of course re-register your existing .dll - which is what we want for debugging. After you done, do run your re-register of your .dll to switch back from the debug .dll that going to be in your current project bin folder to whatever you "regular" use on your PC.
FYI:
In MOST cases, I find this whole idea does NOT work unless you launch VS as administraor. So, make sure VS is being run as administraor for this to work.
I tend to just tap windows key, or even right click on your vs shortcut, and of course choose run as administraor.
This is so often required, you note that VS will EASY and quite CLEAR show you running in admin mode, and I quite much now always run VS this way.
You should see this:

Unloading and reloading dll without restarting the jvm

I am working with a java program where I need to call a native library in order to call other dll that in turn would contact some Remote "Amadeus" (Airline related service) service.
Problem statement:
The jni dll creates a session every time it contacts the remote service and close the session after completion of its intended task. Its very similar to jdbc approach where no connection pooling is involved.
Now it seems that the session is actually not being closed properly and at the server end it eventually results in max session exception and refusing any further connection requests.
It seems there is some issue at the dll-remote service connectivity end, because from java code the connection is being properly closed by calling the native call.
Workaround identified:
Restarting the application fixes this issue because it forces all open connection getting closed.
We don't have access to alter the dll for the time being, so we are thinking if we could have the same flavour of restarting the jvm without actually restarting the jvm but reconnecting (unloading and reloading) the dll.
Here we think if we can disconnect the dll, all memory allocated to the dll would be cleared off, and hence would force to close/collect the open sessions at server end.
Question:
Can we really unload and then reload the dll without restarting the jvm?
Please help us.
Thanks in advance.
Krgds,
Debojit
You can unload it. It's probably not safe to do so, however.
Assuming you're running on a Windows platform, without knowing the details of the DLL, it's not possible to safely unload the library. Per the documentation for the FreeLibrary function:
Use caution when calling FreeLibrary with a handle returned by
GetModuleHandle. The GetModuleHandle function does not increment a
module's reference count, so passing this handle to FreeLibrary can
cause a module to be unloaded prematurely.
Since you're not going to have direct access to the handle used to load the library nor all the references into the library, you can't know if all references to the library are no longer used.
Also, unloading the library may not solve your problem. Ending the entire process solves the problem because that causes everything that process uses to be released/closed (for the most part - there are always exceptions...). Simply unloading one library loaded into the address space doesn't do that. Unloading the library might do what you want - if the library is designed to work that way. Given that it's apparently not working properly when used normally, I'd say the odds of it working properly when used abnormally aren't very good - if unloading the library while it's being used doesn't cause even worse problems.
You need to actually solve the problem - not simply try things and see if they work.

VB.NET application randomly spawns another instance of itself during use

I have a Windows forms application which I have a bit of a sporadic issue with. The application would randomly start/spawn another instance of itself without any warning or reason. I only have one use of Process.Start in the whole application (15 forms/files and about 5000 lines of code) and that calls a net use command to map a network drive.
I've not been able to reproduce this in my testing and therefore I made the project a Windows Assembly Framework single instance application (pros/cons of this I know). This has obviously stopped any other instances of the application from running, but now at random intervals their program will minimise and snap to another application they have running. I don't know for certain whether this is related but they certainly sound a bit close for comfort!
Any ideas/pointers/thoughts appreciated.
Thanks,
Jamie
This could happen if the application, at some point, calls Application.Restart.

How to Inspect COM Objects From Visual Basic Dump File?

Background
We have a .NET WinForms application written in C# that interfaces to a handheld store scanner via a console application. The console application is written in good ol' VB6-- no managed code there. The VB6 application consists of several COM objects.
The .NET WinForms application refreshes the data in the scanner by invoking the console application with the right parameters. When the console application starts, it pops up a modal form reminding the user to place the handheld device into its cradle.
Problem
A customer has a bizarre situation in which the call to start the console application appears to hang before it displays the reminder form. If the user presses any key-- even something innocent like Shift or Alt-- the application unfreezes, and the reminder form appears. While it is hung, the CPU usage of the console application is very high.
We have obtained a memory dump from the command line application using ProcDump. I have some experience debugging managed dump files, but this VB 6 dump is strange to me.
We captured several full memory dumps in a row. In some of them, there appears to be COM glue stacks. For example, several dump files show a call stack like this:
msvbm60!BASIC_DISPINTERFACE_GetTICount
msvbm60!_vbaStrToAnsi
msvbm60!IIDIVbaHost
msvbm60!rtcDoEvents
msvbm60!IIDIVbaHost
msvbm60!BASICCLASS_QueryInterface
[our code which I think is trying to create and invoke a COM object]
It doesn't help that the only symbols I have are from our code. The Microsoft symbol server does not have a PDB file for msvbm60.dll (or at least not from their version which is 6.0.98.2).
Questions
I am suspecting there may be some COM threading issue that is happening only on their system.
1) How can I determine the thread state of each thread in a dump file? If this were a managed dump file, I would look at !threads and then !threadstate to figure out the thread states. There is no managed code, so I can't use sos.dll. I didn't see any hints using ~ and !teb.
2) Is there a way to see what COM objects have been created in a dump file? Again, in a managed dump, I can do a !dumpheap to get a list of managed objects. Is there something similar I can find for COM objects?
3) Can I determine the threading model of COM objects in the dump file?
You can dump thread state by using command:
~*
this will not display 'background' as a state, you will only see running, frozen or suspended.
I'm not sure how you can get information from COM objects, I have never tried but will investigate and get back to you, regards to threading model it will be difficult to infer that without painful monitoring of application state after stepping through and even with that, when you step through all other threads will run unless you use .bpsync 1 which syncs all threads to the current one, but that could cause a hang (e.g. gui thread has now been told to freeze) so I think it will be difficult unless you have access to the source code.
I can only answer question 1. Use !runaway to find the thread or threads consuming the CPU. To get all thread stacks use ~*kb1000.

Remote (RDP) utility with mstscax.dll

I am looking for information on using mstscax.dll in VB. The goal is to create a utility that logs into a remote service in the same manner as remote desktop. However, my utility is not required to show the desktop.
I have a series of commands that I will start off with that will look for users, reset logins, shadow, and message. I have been using a batch file on my RDP to perform these functions, but we are already looking for more functionality and power than what the batch commands can offer.
I am googling 'mstscax.dll' but the results have been less than satisfactory although I continue to search. Does anyone have any good references? Is this even going to be possible?
If you are looking to list or perform operations on remote desktop sessions, you might find the Cassia library helpful. The library can list users logged on to a server, disconnect or logoff sessions, shadow sessions, and display message boxes in a session, among other things. (Note that the shadowing functionality requires a pre-release version of the library available on the project's build server -- use the artifacts link.)
I think you're supposed to use the msrdp.ocx control rather than that dll, though I've personally never used either so can't say for sure.
Edit: Add link
Here's a codeproject article about automating RDP:
http://www.codeproject.com/KB/cs/RemoteDesktop_CSharpNET.aspx