Is there a way to associate arbitrary data to a Windows Process? - c#

I have many instances of a process I've written on a server. I'd like to associate some information with each process. In this specific case I'd like to store the "CurrentState" of the process - "RUNNING|DRAINING|STOPPING", but it would be useful for me to store a "Friendly Name" and so on.
I want to query this information from another "mother" process - this mother process will query the processes running and collate the data.
I've thought of a couple of different ways I could achieve this. For example I might open up a NetPipe to each process of interest and ask for the data, or have each process broadcast it's state regularly.
I was wondering: is there a way to store key value pair information against a process built into Windows itself? Is there an accepted pattern for doing this?
I control the source for the child processes and the mother process. They are written in C#, P/Invoking is fine. The operating system is Windows 2012 R2.

You can host WCF services that use named pipes:
http://msdn.microsoft.com/en-us/library/ms733769(v=vs.110).aspx
Based on some of your comments, it looks like you could also consider the System.AddIn (aka Managed AddIn Framework (MAF)) functionality to create, host, and communicate with Add-ins. MAF supports loading addins in your app domain, a separate app domain, or in a completely separate process. The downside with MAF is that it requires 5 DLLs to get started, but in doing that gives you a lot of flexibility with API compatibility as you version and change your pipeline.

If you're controlling the data from a Mother process, you can also use AppDomains to load your other processes and communicate via Marhsaled data such as a Status class, or use the AppDomains to Set and Get data.
Be aware that any Status data you transfer needs to either be a class which derives from the Marshaling class or be marked as Serializable. The reason for this is because AppDomains are treated in the OS the same as different processes, so they can't access each others memory an actually have to serialize data as if it were being passed through IPC.

Take a look at the .Net Process Class:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx
You can use it to get all running processes, start a process, get the processes unique Id, and be alerted when the process exits. This should give you everything you need to track processes.
Children can call Process.GetCurrentProcess to get their own process id, then make a call to the "mother" process to associate arbitrary data about itself.

Related

C#/.NET: Reporting subprocess state to the parent service

I currently have a service running several subprocesses (with System.Diagnostics.Process). Each subprocess can run for hours and be in a specific, predefined state (think "starting", "working", "cleaning up", etc - completely predefined, no custom data attached to each state has to be reported). Each process cannot be an individual Windows service (there are more possible states than Windows service states). I need to somehow report this state to the parent service. All processes are running on the same Windows machine.
I need to be able to both query subprocess states from other processes (not the ones started by the service), and update the parent service about each subprocess states from those subprocesses. Each process gets a unique ID, so other processes can read the states easily without having to manage processes themselves. All processes share a configuration file in which each subprocess gets assigned a unique ID to identify itself with. I've thought about doing it like so:
Redirect subprocesses' standard output to the service (RedirectStandardOutput = true), read each line in the output and catch "special" lines (STATECHANGE:state)
Write out all subprocesses' states to a file in a predefined location whenever that state changes, delete that file on service exit.
It looks like I'm trying to find a solution to a problem which was solved ages ago and I haven't found that solution. Is there any "nice" way to do such state reporting?
In general, you're delving into the realm of interprocess communications, or IPC.
Though you haven't tagged this question as being specific to Microsoft Windows, it is tagged as C# and .NET, so it's probably that you are running in a Windows environment. My answer assumes you're running this system in a MS Windows.
A common solution to a problem such as this is store state in database. Each service/process could write to the database independently, and then it could be queried by any process that was interested in that information. But this isn't real two-way communication.
Regarding how the parent could communicate with the child processes, this could be done a number of ways, but it would probably be easiest if the child process ran some kind of message pump on a thread and performed data processing on another thread. The message pump would receive and respond to messages, while the data processing thread would do its thing.
Using this scheme, messages could be exchanged in a number of different ways, including:
Windows Communications Framework (WCF)
Named Pipes
.NET Remoting
MS Message Queue (MSMQ)
Windows Clipboard
Dynamic Data Exchange (DDE)
Component Object Model (COM)
Memory-mapped Files
Remote Procedure Calls (RPC)
Sockets
Since all of these processes are running on the same machine, pipes are a simple straightforward choice. Check out the System.IO.Pipes namespace
WCF allows you to build a rich messaging interface that can be implemented on top of pipes, as well as on top of other IPC mechanisms.
There are lots of good resources on the I'net that discuss interprocess communications on .NET, and rather than rehash those here, you should search these out using terms such as ".NET", "interprocess communications", "IPC" and "local machine" (since you need IPC between processes on the local machine).

Limiting external process resources programmatically

I'm developing a .NET application, which have a 3rd party plugins. These plugins comes as EXE files, which works with application APIs and data.
Due to security concerns, I would like to be able "sandbox" them, when they're launched through my application. Especially, the most important is to be able to limit access to the drives or directories of filesystem.
Is there any way to do this through AppDomain? Or in any other way?
Also some external plugins may not be written in managed code as my software exposes APIs to COM, but it is possible to drop non .NET plugin support. The more important thing for us is to sandbox those plugins.
Any way to solve this is appreciated.
Given that you need to do this for a process that's not (necessarily) entirely based on .NET, AppDomains probably won't be adequate for the task.
I'd consider running the processing inside a Windows Job Object. This lets you set up a sandbox that limits the process' use of things like the CPU and memory.
Access to the file system is already handled based on user accounts using Discretionary Access Control Lists (DACLs). To limit access to a few specific parts of the file system, set up an account to use to run the sandboxed jobs, and set up access-allowed ACEs for the parts of the file system they're allowed to use. If you need to support more than one user running sandboxed jobs, you might want to set up a user group for the sandboxed jobs, and associate the ACEs with the group instead of the individual users.

Creating COM Component in .NET to override IE functionality (custom download manager)

I have to create a custom download manager that will replace a standard download manager in Internet Explorer. After googling I've learned that I have to create a COM component that implements the IDownloadManager interface.
As far as I understand I have to create a dll, generate guid for it and register it using regasm.exe utility, and then add specific entry in windows registry for IE.
I have a few questions:
I want my program to be an exe and I want to be able to run it manualy and add url to it as well as run it by IE after clicking on a downloadable link.
Although I would prefer to have a single executable, I think to achieve this i have to create dll and exe, and from dll i should check whether the exe is running (by window id) and run if it isn't and communicate with it somehow. Is this correct approach?
I want to share my program with other users, and i don't want them to register COM manually. Is it possible to do it from the code? Or perhaps I should create an installer (which I would like to avoid)?
I'll start with a WARNING: Do not create a .Net components that will be loaded in IE. Ask yourself the question "What would happen if another app does the same, and it uses different version of the CLR?". IE does not guarantee any order of loading the different COM components it needs, so there's no guarantee that your version of the CLR will be loaded in the process by the time IE calls you.
Now onto your problem. There are several issue with your scenario:
.Net does not support creating out-of-proc COM components natively. Yes, it is possible to create one by doing bunch of hacks and manual registration; however, it is not a simple task and requires deep knowledge of how COM works;
with the above in mind, your option is really to create a .Net DLL and use the ComVisible attribute to expose the classes you need to COM. As you mentioned it, you will need to register it using RegAsm.exe, for IE to be able to use it;
since you want the main functionality of your download manager to be in a standalone executable, you will have to use a .Net supported cross-process communication mechanism. .Net Remoting is likely the easiest way to implement it, and should for the most part meet your requirements. The alternative is to implement the download functionality in-proc. However, beside the consideration that you now could easily hose the IE process, if you are not careful to listen to its quit notification (which require a lot more work by itself), there's also the whole enchilada with the IE7+ protected mode, which severely limits what your in-proc code can do (limited file access, registry access, Windows APIs and other limitations);
there are certain complications arising from the IE8 and IE9 process model. Besides the top frame process, IE8/9 create a pool of processes and load-balance the tabs into these. I don't know which process will try to create your COM component and wheter it's going to be one per tab or per process or for the whole IE session (which spans multiple processes), so you have to be prepared that you might have multiple instances in multiple processes running concurrently. If this is the case, you will have to figure out how to ensure that the communication between the in-proc COM component and the executable is not serialized one instance at a time, or you might affect the browsing experience for the user. (A simple scenario would be a page with multiple download links and the user right-clicking on each link and selecting Open in new tab, thus launching multiple downloads in several tabs at once);
even if there is one instance per IE session, elevated IE instances run in a separate session from the regular user IE instances for security reasons. There's the interesting complication that your .Net Remoting call from the in-proc COM component in the elevated IE session will result in a second copy of your executable being launched also elevated. Thus, your download manager will have to be prepared that there might be two processes accessing the same download queue;
starting with IE7, IE protected mode (the default) will intercept any calls that result in starting a new process and show a dialog to the user. The only way to avoid this would be to register a silent IE elevation policy for your process. The elevation policies are registered in HKEY_LOCAL_MACHINE, which means that you will need an installer, or at least a simple script for the users to run as administrator;
even if you decide against the elevation policy and to live with the bad experience of this dialog, to register your download manager with IE, you still will have to write to the HKEY_LOCAL_MACHINE registry hive, otherwise IE will not know of it and won't use it. In other words, you still need some kind of installer or a deployment script;
IE is fairly aggressive in measuring the performance of the code that runs on the UI thread and in terminating background threads when exiting the process. So whatever functionality you have in the in-proc component, you will have to balance between being as fast as possible on the UI thread (which means less work or you'll impact the user experience) and doing work on the background threads (which means be prepared you might be killed without notification at any moment);
I think this list covers the main issues you will have to solve. The biggest problem you will encounter is that a lot of the specifics around IE process model are not well documented on MSDN, and there are almost no examples of implementing this scenario in managed code (and of those that exist, most are old and are not updated for IE8/IE9, and some even won't work in IE7).

Listing and terminating processes in .Net

How can I list and terminate existing processes in .Net application? Target applications are 1) .Net applications, 2) they are instances of the same executable 3) they have unique Ids but I don't know how to get this information from them, 4) they are spawned externally (i.e. I do not have handles to them as I don't create them).
I want to list all processes, get unique ids from them and restart some of them. I assume that all of them are responsive.
You can grab a list of running processes with Process.GetProcesses static method. You can easily query the return value (possibly with LINQ) to get the ones you want.
System.Diagnostics.Process.GetProcesses()
Process.Kill();
Check this out for killing processes:
http://www.dreamincode.net/code/snippet1543.htm
The Process Id is a property of the process. Eg:
Process.Id
All of the methods available on the process are listed here:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process_methods.aspx
I'd like to refer you to this question on interprocess communication, and also this tutorial. You can use WCF to query a process, and request a shutdown. Each process will need it's own named pipe. You can generate a unique name at startup, based on the process ID (Process.GetCurrentProcess().Id).
All this may be a little heavy weight for some simple communication though. Using the Windows message queue might be an option as well. You can use process.MainWindowHandle to get a process' window handle and send custom messages to instances of your application. See Messages and Message queues. If you choose to go that way, pinvoke could be of help.

How to query a variable in another running application in c#?

I have an app that, when launched, checks for duplicate processes of itself.
That part I have right - but what I need is to check a state variable in the original running process in order to run some logic.
So: how do I make a variable (e.g. bool) available publicly to other applications so they can query it?
There are a bunch of ways to do this. A very primative way would be to read/write from a file. The old win32 way would be to use PostMessage. The more .NET way would be to use remoting or WCF and Named Pipes.
.NET 4 is also getting support for Memory Mapped files.
Here is a pretty thorough looking artcile describing a few different approaches including support for Memory Mapped files outside of .NET 4
http://www.codeproject.com/KB/threads/csthreadmsg.aspx
The easiest: Create a file, and write something in it.
More advanced, and when done correctly more robust, is using WCF, you use named pipes to setup some communication channel on the local computer only.
If you're using a Mutex to check whether another process is running (you should be) you could use another Mutex whose locked state would be the boolean flag you're looking.
The standard way of doing this is to use the Windows API to create and lock a mutex. The first app to open will create and lock the mutex. Any subsequent executions of the app will not be able to get it and can then shutdown.

Categories