Collaborators have built a prototype using Processing that connects to a Sparkfun RFID reader, I think using a serial connection over USB. We've deployed the prototype into a number of trialists' homes and one common usage scenario I foolishly overlooked was user switching. Hence I am writing a wrapper that ensures only one instance of the prototype application is running across all users on the machine.
I’m testing out my first stab at this as a simple console app. Here’s the code:
static void Main(string[] args)
{
// http://stackoverflow.com/a/2590446/575530
var users = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var rule = new EventWaitHandleAccessRule(users, EventWaitHandleRights.FullControl, AccessControlType.Allow);
var security = new EventWaitHandleSecurity();
security.AddAccessRule(rule);
bool createdStartup;
using (var whStartup = new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppStartupEvent", out createdStartup, security))
{
bool createdShutdown;
using (var whShutdown = new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppShutdownEvent", out createdShutdown, security))
{
Console.WriteLine("Let other instances shutdown");
whStartup.Set();
Console.WriteLine("If other instances exist wait for them to shutdown");
if (!createdShutdown)
{
whShutdown.WaitOne();
}
whShutdown.Reset();
Console.WriteLine("Start tray app");
var tokenProc = Process.Start(#"C:\Temp\FAMILY3_WIN\TokensApp.exe");
Console.WriteLine(tokenProc.ProcessName);
Console.WriteLine("Wait to see if another instance to tries to start");
whStartup.Reset();
whStartup.WaitOne();
Console.WriteLine("Shutdown if another instance starts");
//if (tokenProc != null) tokenProc.Kill();
foreach (var process in Process.GetProcesses())
{
if (process.ProcessName.StartsWith("javaw"))
{
process.Kill();
}
}
whShutdown.Set();
}
}
Console.WriteLine("Done...");
Console.ReadLine();
}
(N.B. I know there are issues with this code around (1) killing Java processes that are not the running prototype and (2) there’s no code to respond to lots of instances starting simultaneously, just two at a time. But that’s not what my question is about.)
Testing this under a single user account works fine. I can start my app, it in turn starts the prototype, and if I start a second instance of my app the first one kills the initial instance of the prototype before the second one starts another instance of the prototype afresh.
But if I try doing this from two different user accounts it fails (silently). If I
Start an instance of my application it starts the prototype
Switch user
Start an instance of my application then it starts the
prototype without my app from step 1 first shutting down the existing
instance.
Can anyone see what’s wrong with my code? How should I use EventWaitHandle across several simultaneous user sessions on the same machine?
Isn't it always the way, minutes after writing a long question the answer leaps to mind!
I got the slash the wrong way around in the name of the EventWaitHandle. For example replacing the constructor call:
new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppShutdownEvent", out createdShutdown, security)
with this one:
new EventWaitHandle(false, EventResetMode.AutoReset, #"Global\AaltoTokensAppShutdownEvent", out createdShutdown, security)
fixes my problem.
Related
Overall Goal
I'm attempting to kill all of the processes by a certain name (notepad.exe below) that I currently own. Generally speaking, it's along the lines of:
Get all of the applications with a certain name that I'm the owner of
In this case, "I" will usually be a service account
Kill all of them.
Questions
How likely is it that from the time I grab a PID to the time I kill it, another application could have spawned that uses that PID? If I grab a PID of ID 123, how likely is it that it could have closed and a different application now owns PID 123?
What is the best way I can reasonably pull this off while limiting the potential that I kill off the wrong PID?
What I have so Far
The below code is based on another SO answer and uses WMI to get all the processes by a certain name and list the users.
What's next: The next step is to kill the processes that are owned by me; however, how can I tell that the PIDs I have here will be the same PIDs I'm trying to kill?
static void Main(string[] args)
{
const string PROCESS_NAME = "notepad.exe";
var queryString = string.Format("Name = '{0}'", PROCESS_NAME);
var propertiesToSelect = new[] { "Handle", "ProcessId" };
var processQuery = new SelectQuery("Win32_Process", queryString, propertiesToSelect);
using (var searcher = new ManagementObjectSearcher(processQuery))
{
using (var processes = searcher.Get())
foreach (var aProcess in processes)
{
var process = (ManagementObject)aProcess;
var outParameters = new object[2];
var result = (uint)process.InvokeMethod("GetOwner", outParameters);
if (result == 0)
{
var user = (string)outParameters[0];
var domain = (string)outParameters[1];
var processId = (uint)process["ProcessId"];
Console.WriteLine("PID: {0} | User: {1}\\{2}", processId, domain, user);
// TODO: Use process data...
}
else
{
// TODO: Handle GetOwner() failure...
}
}
}
Console.ReadLine();
}
Yes, there is a risk of killing the wrong process. The reuse of PIDs probably is a history accident that has caused a lot of grief over the years.
Do it like this:
Find the PIDs you want to kill.
Obtain handles to those processes to stabilize the PIDs. Note, that this might obtain handles to wrong processes.
Re-find the PIDs you want to kill.
Kill those processes that you have stabilized and that are in the second find result set.
By inserting this lock-and-validate step you can be sure.
How likely is it that from the time I grab a PID to the time I kill it, another application could have spawned that uses that PID?
Another application wouldn't be assigned the same PID if it was spawned whilst the other one was alive. So this condition wouldn't happen as Windows' PIDs are unique decimal numbers to that specific process.
If I grab a PID of ID 123, how likely is it that it could have closed and a different application now owns PID 123?
This is technically feasible that the process could be closed between the time you gain your handle on the process and when you want to kill it. However, that would depend entirely on the lifespan of the process handling within your code. I guess there will always be edge cases where the application could be closed just as you're about to hook onto it, but if you're talking milliseconds/a couple of seconds I imagine it would be few and far between. As for Windows assigning the same PID immediately afterwards, I don't know for sure but they seem pretty random and now allocated again immediately after use, but they eventually would do.
What is the best way I can reasonably pull this off while limiting the potential that I kill off the wrong PID?
There is the Management Event Watcher class which appears to allow you to monitor the starting and stopping of processes. Maybe this could be used to capture events whenever they are closed for your given process name, so this way you know that it no longer exists?
Another answer discussing Management Event Watcher
MSDN ManagementEventWatcher class with example usage
Consider opposite approach - adjust permissions on service account so it can't kill processes of other users.
I believe such permissions are very close to default for non-admin accounts (or just default) - so unless you run service as box admin/system you may be fine with no-code solution.
A process id is guaranteed to stay the same as long as the process continues to run. Once the process exits... there is no guarantee.
When a new process starts, Windows will pick a random process ID and assign it to the new process. Its unlikely, but possible that the id chosen was associated with a process that recently exited.
Have you looked at System.Diagnostics.Process?
They have a GetProcessesByName method that will return a list of Process objects.
Process [] localByName = Process.GetProcessesByName("notepad");
Then you can simply iterate through the Processes and kill them. Since the Process object has a handle to the process... an attempt to kill it will generate a useful exception, which you can catch.
foreach (Process p in localByName)
{
try
{
p.Kill();
}
catch (Exception e)
{
// process either couldn't be terminated or was no longer running
}
}
Does .Net Remoting opens multiple connections or just one ?
let say I have a server and a client. if the client creates multiple SingleCall objects. then for every object is there going to be a new connection or there going to be a single connection for every object ?
I can't find the answer anywhere.
Long answer is: it depends on many things.
Short answer is yes. Yes Yes.
Let's make an experiment and see the most common default situation.
We have 2 console apps and 1 common class library which is referred by both console apps.
The 1st console app has the role of the client and the 2nd one has that of the server.
First, here's what the commonly depended upon class library contains:
public interface IFactory {
string Hello(string name);
}
Now for some server code. Here's the start up:
private static TcpChannel channel;
static void Main(string[] args) {
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = TypeFilterLevel.Full;
channel = new TcpChannel(
properties: new Hashtable {
{ #"port", 2013 }
},
clientSinkProvider: clientProv,
serverSinkProvider: serverProv
);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Factory), "Factory.rem", WellKnownObjectMode.SingleCall);
Console.WriteLine("Server started...");
Console.WriteLine("Press any key to stop...");
Console.ReadKey(intercept: true);
}
We just mentioned a class called Factory.
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Factory), "Factory.rem", WellKnownObjectMode.SingleCall);
You guessed it. It's the IFactory implementation:
private sealed class Factory : MarshalByRefObject, IFactory {
#region IFactory Members
string IFactory.Hello(string name) {
return #"Hello " + name + #" !";
}
#endregion
}
Now for some client:
static void Main(string[] args) {
Console.WriteLine("Press any key to connect...");
Console.ReadKey(intercept: true);
IFactory factory = Activator.GetObject(typeof(IFactory), #"tcp://127.0.0.1:2013/Factory.rem") as IFactory;
EventWaitHandle signal = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset);
ThreadStart action = () => {
signal.WaitOne();
var result = factory.Hello("Eduard");
Console.WriteLine(result);
};
foreach (var i in Enumerable.Range(0, 99))
new Thread(action) { IsBackground = true }.Start();
Console.WriteLine("Press any key to bombard server...");
Console.ReadKey(intercept: true);
signal.Set();
Console.ReadKey(intercept: true);
}
You already know all of these things, I'm sure. We obtain a transparent proxy to the SingleCall service on the other side (they're both on the same machine and we're using TCP port 2013):
IFactory factory = Activator.GetObject(typeof(IFactory), #"tcp://127.0.0.1:2013/Factory.rem") as IFactory;
Then, for "simulataneous-ness" reasons we create 100 threads, start them (which can take some time), but "hold them in a leash" (a signal is an essential means of synchronization of the OS) until we "pull the trigger":
EventWaitHandle signal = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset);
ThreadStart action = () => {
signal.WaitOne();
var result = factory.Hello("Eduard");
Console.WriteLine(result);
};
foreach (var i in Enumerable.Range(0, 99))
new Thread(action) { IsBackground = true }.Start();
So although all 100 threads have been created AND started, they are all waiting in the following invocation:
signal.WaitOne();
That way we can get the to start at the same time better, otherwise the creation and starting of threads itself would have made their actual execution more or less sequential.
We ask the user to decide when to "bombard the server" with 100 Hello invocations:
Console.WriteLine("Press any key to bombard server...");
Console.ReadKey(intercept: true);
signal.Set();
And this is what happens:
1) We start the server console app and let it run in peace:
2) We start the client console app, "make the connection" by pressing any key (which is only a logical connection since it just creates a transparent proxy) but we postpone the "bombardment":
3) We start up Mark Russinovich's Process Explorer and use it to discover the client process in the process list, and while doing that we open it's properties window and select the TCP/IP tab:
4) We hit any key in the client console app, and .. TA DAA !!
You get a lot of connections in Process Explorer.
Are they a hundred ? Sometimes yes, sometimes no.
It's a connection pool, that's for sure.
After a short while (5 to 10 seconds) of idleness they close down which is a very good thing (because the .NET Remoting stack is implemented that way).
I hope this experiment generally answered your question.
In more specific cases and in a more rigorous sense you should check out the documentation and read about the various channels that you might use in your .NET Remoting apps (there are loads of them out there, what you've seen here is just the regular TcpChannel officially provided by Microsoft, it depends on what your .NET Remoting configuration says, on whether you're hosting the server in IIS or not, etc).
The number of network connections depends on remoting channel you use. The default TcpChannel opens as many network connections as many threads in your program try to access the server during one point of time.
For single-threaded applications, TcpChannel uses one network connection.
As an opposite example, a third party remoting channel IiopChannel uses multiplexing and thus allows to have just a few network connections for many hundreds of active threads.
I'm trying to make a console app in c# that will confirm that another application is always running. The other application periodically crashes, and I need to check every few minutes and relaunch it if it has stopped working.
There are many questions on SO that address making sure than no more than one instance of the application is running. I'm trying to confirm that one (no more or less) is running at all times.
Does anybody know how to even begin approaching this?
I would suggest using System.Diagnostics.Process.GetProcessesByName to see if your process is running and then, if not, using System.Diagnostics.Process.Start to start the process.
var processes = Process.GetProcessesByName("yourProcessName");
if(processes.Length == 0)
{
Process.Start(#"C:\Path\To\Your\Process.exe");
}
// Kill the extras
for(int i = 1; i < process.Length; i++)
{
processes[i].Kill();
}
These commands are useful to control processes:
// check for processes
Process[] processes = Process.GetProcessesByName("nameOfExecutable");
foreach (Process proc in processes)
{
// do stuff
}
// start process (need path)
Process.Start("pathToExecutable");
// close gui process gently (if needed)
bool status = proc.CloseMainWindow();
// wait for process to close gently
bool status = proc.WaitForExit(killTimeMS);
// force close (kill) process
proc.Kill();
If you implement a "no more than one" rule (which is well-documented, as you point out) and then implement the periodic crash-checker, that should be sufficient to ensure that one and only one copy is running.
In fact, the periodic process doesn't even have to check for a crash. It can just fire up an instance, which will immediately exit if another instance is already running, thanks to whatever "no more than one" mechanism you implement. This has the added benefit of avoiding a possible race-condition between detecting a dead process and starting a new one.
You have a few options. The first is checking for a running process using the Process class. I got this from a Microsoft site, but it looks like it works:
public bool IsProcessRunning(string name)
{
//here we're going to get a list of all running processes on
//the computer
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.StartsWith(name))
{
//process found so it's running so return true
return true;
}
}
//process not found, return false
return false;
}
You could also use interprocess communications. This is something we do in house. We have a watcher application that sends a message to a service being monitored. If the service doesn't return an ACK in a timeout period, we attempt to restart it.
I suggest you to check if your application is in the list of running processes:
System.Diagnostics.Process.GetProcesses();
I have two windows application, one is a windows service which create EventWaitHandle and wait for it. Second application is a windows gui which open it by calling EventWaitHandle.OpenExisting() and try to Set the event. But I am getting an exception in OpenExisting. The Exception is "Access to the path is denied".
windows Service code
EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset, "MyEventName");
wh.WaitOne();
Windows GUI code
try
{
EventWaitHandle wh = EventWaitHandle.OpenExisting("MyEventName");
wh.Set();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I tried the same code with two sample console application, it was working fine.
You need to use the version of the EventWaitHandle constructor that takes an EventWaitHandleSecurity instance. For example, the following code should work (it's not tested, but hopefully will get you started):
// create a rule that allows anybody in the "Users" group to synchronise with us
var users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
var rule = new EventWaitHandleAccessRule(users, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
AccessControlType.Allow);
var security = new EventWaitHandleSecurity();
security.AddAccessRule(rule);
bool created;
var wh = new EventWaitHandle(false, EventResetMode.AutoReset, "MyEventName", out created, security);
...
Also, if you're running on Vista or later, you need to create the event in the global namespace (that is, prefix the name with "Global\"). You'd also have to do this on Windows XP if you use the "Fast User Switching" feature.
This might be caused by the service process running at an elevated privilege level, but the GUI process is not. If you put the same code into two console apps, they'll both be running at user level and won't have any trouble accessing each other's named shared objects.
Try running the GUI app with the "Run as administrator" flag from the Windows start menu. If that solves the issue, you need to read up on how to request elevation within your code. (I haven't done that)
I have created a webservice in .net 2.0, C#. I need to log some information to a file whenever different methods are called by the web service clients.
The problem comes when one user process is writing to a file and another process tries to write to it. I get the following error:
The process cannot access the file because it is being used by another process.
The solutions that I have tried to implement in C# and failed are as below.
Implemented singleton class that contains code that writes to a file.
Used lock statement to wrap the code that writes to the file.
I have also tried to use open source logger log4net but it also is not a perfect solution.
I know about logging to system event logger, but I do not have that choice.
I want to know if there exists a perfect and complete solution to such a problem?
The locking is probably failing because your webservice is being run by more than one worker process.
You could protect the access with a named mutex, which is shared across processes, unlike the locks you get by using lock(someobject) {...}:
Mutex lock = new Mutex("mymutex", false);
lock.WaitOne();
// access file
lock.ReleaseMutex();
You don't say how your web service is hosted, so I'll assume it's in IIS. I don't think the file should be accessed by multiple processes unless your service runs in multiple application pools. Nevertheless, I guess you could get this error when multiple threads in one process are trying to write.
I think I'd go for the solution you suggest yourself, Pradeep, build a single object that does all the writing to the log file. Inside that object I'd have a Queue into which all data to be logged gets written. I'd have a separate thread reading from this queue and writing to the log file. In a thread-pooled hosting environment like IIS, it doesn't seem too nice to create another thread, but it's only one... Bear in mind that the in-memory queue will not survive IIS resets; you might lose some entries that are "in-flight" when the IIS process goes down.
Other alternatives certainly include using a separate process (such as a Service) to write to the file, but that has extra deployment overhead and IPC costs. If that doesn't work for you, go with the singleton.
Maybe write a "queue line" of sorts for writing to the file, so when you try to write to the file it keeps checking to see if the file is locked, if it is - it keeps waiting, if it isn't locked - then write to it.
You could push the results onto an MSMQ Queue and have a windows service pick the items off of the queue and log them. It's a little heavy, but it should work.
Joel and charles. That was quick! :)
Joel: When you say "queue line" do you mean creating a separate thread that runs in a loop to keep checking the queue as well as write to a file when it is not locked?
Charles: I know about MSMQ and windows service combination, but like I said I have no choice other than writing to a file from within the web service :)
thanks
pradeep_tp
Trouble with all the approached tried so far is that multiple threads can enter the code.
That is multiple threads try to acquire and use the file handler - hence the errors - you need a single thread outside of the worker threads to do the work - with a single file handle held open.
Probably easiest thing to do would be to create a thread during application start in Global.asax and have that listen to a synchronized in-memory queue (System.Collections.Generics.Queue). Have the thread open and own the lifetime of the file handle, only that thread can write to the file.
Client requests in ASP will lock the queue momentarily, push the new logging message onto the queue, then unlock.
The logger thread will poll the queue periodically for new messages - when messages arrive on the queue, the thread will read and dispatch the data in to the file.
To know what I am trying to do in my code, following is the singletone class I have implemented in C#
public sealed class FileWriteTest
{
private static volatile FileWriteTest instance;
private static object syncRoot = new Object();
private static Queue logMessages = new Queue();
private static ErrorLogger oNetLogger = new ErrorLogger();
private FileWriteTest() { }
public static FileWriteTest Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new FileWriteTest();
Thread MyThread = new Thread(new ThreadStart(StartCollectingLogs));
MyThread.Start();
}
}
}
return instance;
}
}
private static void StartCollectingLogs()
{
//Infinite loop
while (true)
{
cdoLogMessage objMessage = new cdoLogMessage();
if (logMessages.Count != 0)
{
objMessage = (cdoLogMessage)logMessages.Dequeue();
oNetLogger.WriteLog(objMessage.LogText, objMessage.SeverityLevel);
}
}
}
public void WriteLog(string logText, SeverityLevel errorSeverity)
{
cdoLogMessage objMessage = new cdoLogMessage();
objMessage.LogText = logText;
objMessage.SeverityLevel = errorSeverity;
logMessages.Enqueue(objMessage);
}
}
When I run this code in debug mode (simulates just one user access), I get the error "stack overflow" at the line where queue is dequeued.
Note: In the above code ErrorLogger is a class that has code to write to the File. objMessage is an entity class to carry the log message.
Alternatively, you might want to do error logging into the database (if you're using one)
Koth,
I have implemented Mutex lock, which has removed the "stack overflow" error. I yet have to do a load testing before I can conclude whether it is working fine in all cases.
I was reading about Mutex objets in one of the websites, which says that Mutex affects the performance. I want to know one thing with putting lock through Mutex.
Suppose User Process1 is writing to a file and at the same time User Process2 tries to write to the same file. Since Process1 has put a lock on the code block, will Process2 will keep trying or just die after the first attempet iteself.?
thanks
pradeep_tp
It will wait until the mutex is released....
Joel: When you say "queue line" do you
mean creating a separate thread that
runs in a loop to keep checking the
queue as well as write to a file when
it is not locked?
Yeah, that's basically what I was thinking. Have another thread that has a while loop until it can get access to the file and save, then end.
But you would have to do it in a way where the first thread to start looking gets access first. Which is why I say queue.