i was searching how to do it for about 6 hours,but didn't find a way.
Is there any way i can change a process's parent process? some api maby ?
google didn't gave much, same for this site, so i opened new question.
What i'm trying to do is to lock a file for personal use, then delete it.
i create the file on program A and use it with program B, when B finish the use, i delete with A, the thing is that B creates a sub process, which don't have B as his parent, so when i use :
File.Open(_moviePath, FileMode.Open, FileAccess.Read, FileShare.Inheritable);
I try to lock the file because i don't want other programs/users to be able to copy it but
it failes.
tnx.
instead of locking the file this way, why not use Mutex? It allows for cross process locking. This will work fine if this is to remain on a single box. http://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.110).aspx
And no you cannot reassign a parent process owner to a child process.
Here is an example, i will explain below: http://www.dotnetperls.com/mutex
using System;
using System.Threading;
class Program
{
static Mutex _m;
static bool IsMutexExisting(string token)
{
try
{
// Try to open existing mutex.
Mutex.OpenExisting(token);
}
catch
{
return true;
}
// More than one instance.
return false;
}
So in your example program A will do it's thing and then wait.. how to get A to wait?
Have program A attempt to open an existing mutex (a mutex that only B will create), for example... pcode:
while( IsMutexExisting("B Token") == false )
{
System.Threading.Thread.Sleep(500); //sleep for a 1/2 sec
}
//ok, B has created the mutex, let's wait for it to be released indicating it is complete.
Mutex m = Mutex.OpenExisting("B Token");
m.WaitOne(); // will block execution until B releases the Mutex
// lock created, this means B signaled us
// do the rest of A code here...
Program B:
<does what it does>
//Create Mutex to signal A
Mutex m = null;
try{
m =new Mutex(true,"B Token");
...
...
}
finally{
m.ReleaseMutex();
}
Related
I am using the next code to log errors of an web application.
using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
{
myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
}
Sometimes, the following exception 'System.IO.IOException: The process cannot access the file '.txt' because it is being used by another process.' is thrown.
I think this is caused by multiple instances of the web app at the same time. Can you help me fix this problem, please ?
EDIT: I have to add that for every method I log like this:
Date - Method X started.
Date - Exception.Message (table not found or other errors)
Date - Method X stopped.
and when this Error appears, it's logged only this:
Date - System.IO.IOException: The process cannot access the file '.txt' because it is being used by another process.
Sadly Windows does not allow waiting on a file lock. In order to get around this all your applications will have to create a lock that all the processes involved can check.
The use of this code will only prevent threads within a single process from accessing the file:
/* Suitable for a single process but fails with multiple processes */
private static object lockObj = new Object();
lock (lockObj)
{
using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
{
myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
}
}
In order to lock across multiple processes a Mutex lock is required. This gives a name to the lock that other processes can check for. It works like this:
/* Suitable for multiple processes on the same machine but fails for
multiple processes on multiple machines */
using (Mutex myMutex = new Mutex(true, "Some name that is unlikly to clash with other mutextes", bool))
{
myMutex.WaitOne();
try
{
using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
{
myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
}
}
finally
{
myMutex.ReleaseMutex();
}
}
I don't think Mutexes can be access from remote machines so if you have a file on a file share and you are trying to write to it from processes on multiple machines then you are probably better off writing a server component on the machine that hosts the file to mediate between the processes.
Your web server will run requests in multiple threads. If two or more requests have to log exceptions at the same time, this will lead to the exception you see.
You could either lock the section as James proposed, or you could use a logging framework that will handle multithreading issues for you, for example Lgo4net or NLog.
Assuming you need each thread to eventually write to the log, you could lock the critical section
private static object fileLock = new Object();
...
lock (fileLock)
{
using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
{
myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10 {3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
}
}
This means only 1 thread at any given time can be writing to the file, other threads are blocked until the current thread has exited the critical section (at which point the file lock will have been removed).
One thing to note here is that lock works per process, therefore if your site is running the context of a web farm/garden then you would need to look at a system-wide locking mechanism i.e. Mutexes.
I've added this code to my class:
public static bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch
{
return true;
}
finally
{
if (stream != null)
{
stream.Close();
}
}
return false;
}
and now my LogToFile method is like this:
while (IsFileLocked(fi))
{
}
using (StreamWriter myStream = new StreamWriter(sLogFilePath, true))
{
if (displayTime == true)
myStream.WriteLine(string.Format("{0, -45}{1, -25}{2, -10}{3}", guid, DateTime.Now, StringEnum.GetStringValue(enumMsg), sText));
else
myStream.WriteLine(string.Format("{0, -70}{1, -10}{2} ", guid, StringEnum.GetStringValue(enumMsg), sText));
}
I hope this will work.
It's code that will execute 4 threads in 15-min intervals. The last time that I ran it, the first 15-minutes were copied fast (20 files in 6 minutes), but the 2nd 15-minutes are much slower. It's something sporadic and I want to make certain that, if there's any bottleneck, it's in a bandwidth limitation with the remote server.
EDIT: I'm monitoring the last run and the 15:00 and :45 copied in under 8 minutes each. The :15 hasn't finished and neither has :30, and both began at least 10 minutes before :45.
Here's my code:
static void Main(string[] args)
{
Timer t0 = new Timer((s) =>
{
Class myClass0 = new Class();
myClass0.DownloadFilesByPeriod(taskRunDateTime, 0, cts0.Token);
Copy0Done.Set();
}, null, TimeSpan.FromMinutes(20), TimeSpan.FromMilliseconds(-1));
Timer t1 = new Timer((s) =>
{
Class myClass1 = new Class();
myClass1.DownloadFilesByPeriod(taskRunDateTime, 1, cts1.Token);
Copy1Done.Set();
}, null, TimeSpan.FromMinutes(35), TimeSpan.FromMilliseconds(-1));
Timer t2 = new Timer((s) =>
{
Class myClass2 = new Class();
myClass2.DownloadFilesByPeriod(taskRunDateTime, 2, cts2.Token);
Copy2Done.Set();
}, null, TimeSpan.FromMinutes(50), TimeSpan.FromMilliseconds(-1));
Timer t3 = new Timer((s) =>
{
Class myClass3 = new Class();
myClass3.DownloadFilesByPeriod(taskRunDateTime, 3, cts3.Token);
Copy3Done.Set();
}, null, TimeSpan.FromMinutes(65), TimeSpan.FromMilliseconds(-1));
}
public struct FilesStruct
{
public string RemoteFilePath;
public string LocalFilePath;
}
Private void DownloadFilesByPeriod(DateTime TaskRunDateTime, int Period, Object obj)
{
FilesStruct[] Array = GetAllFiles(TaskRunDateTime, Period);
//Array has 20 files for the specific period.
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
TransferOperationResult transferResult;
foreach (FilesStruct u in Array)
{
if (session.FileExists(u.RemoteFilePath)) //File exists remotely
{
if (!File.Exists(u.LocalFilePath)) //File does not exist locally
{
transferResult = session.GetFiles(u.RemoteFilePath, u.LocalFilePath);
transferResult.Check();
foreach (TransferEventArgs transfer in transferResult.Transfers)
{
//Log that File has been transferred
}
}
else
{
using (StreamWriter w = File.AppendText(Logger._LogName))
{
//Log that File exists locally
}
}
}
else
{
using (StreamWriter w = File.AppendText(Logger._LogName))
{
//Log that File exists remotely
}
}
if (token.IsCancellationRequested)
{
break;
}
}
}
}
Something is not quite right here. First thing is, you're setting 4 timers to run parallel. If you think about it, there is no need. You don't need 4 threads running parallel all the time. You just need to initiate tasks at specific intervals. So how many timers do you need? ONE.
The second problem is why TimeSpan.FromMilliseconds(-1)? What is the purpose of that? I can't figure out why you put that in there, but I wouldn't.
The third problem, not related to multi-programming, but I should point out anyway, is that you create a new instance of Class each time, which is unnecessary. It would be necessary if, in your class, you need to set constructors and your logic access different methods or fields of the class in some order. In your case, all you want to do is to call the method. So you don't need a new instance of the class every time. You just need to make the method you're calling static.
Here is what I would do:
Store the files you need to download in an array / List<>. Can't you spot out that you're doing the same thing every time? Why write 4 different versions of code for that? This is unnecessary. Store items in an array, then just change the index in the call!
Setup the timer at perhaps 5 seconds interval. When it reaches the 20 min/ 35 min/ etc. mark, spawn a new thread to do the task. That way a new task can start even if the previous one is not finished.
Wait for all threads to complete (terminate). When they do, check if they throw exceptions, and handle them / log them if necessary.
After everything is done, terminate the program.
For step 2, you have the option to use the new async keyword if you're using .NET 4.5. But it won't make a noticeable difference if you use threads manually.
And why is it so slow...why don't you check your system status using task manager? Is the CPU high and running or is the network throughput occupied by something else or what? You can easily tell the answer yourself from there.
The problem was the sftp client.
The purpose of the console application was to loop through a list<> and download the files. I tried with winscp and, even though, it did the job, it was very slow. I also tested sharpSSH and it was even slower than winscp.
I finally ended up using ssh.net which, at least in my particular case, was much faster than both winscp and sharpssh. I think the problem with winscp is that there was no evident way of disconnecting after I was done. With ssh.net I could connect/disconnect after every file download was made, something I couldn't do with winscp.
I am using a named system mutex to synchronise 2 processes. This is how I am currently acquiring a mutex within my application:
using System.Threading;
public static bool AcquireMutex()
{
// Protect against double acquisitions
if (MyMutex != null)
{
throw new ApplicationException("Failed to acquire mutex");
}
try
{
// See if a named system mutex has already been created - if it has,
// wait a short amount of time for its release.
MyMutex = Mutex.OpenExisting(MutexName);
if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false))
{
// MyMutex still being held
MyMutex = null;
return false;
}
}
catch
{
// MyMutex doesn't exist so create it
MyMutex = new Mutex(true, MutexName);
}
return true;
}
OpenExisting will throw an exception if the named system mutex with MutexName doesn't exist, allowing my application to create it.
However, there seems to be a race condition here - if OpenExisting throws, there is a small window before the call to new Mutex where the other application may have acquired the mutex.
What is the best way to avoid this race condition and make this code more reliable?
A colleague mentioned that he was using CreateMutex from the Win32 Platform SDK in his code (the other process which needs to be synchronised). This doesn't seem to be natively supported by the .NET Framework, however. So I'm not sure it's the best solution for my code.
Update
Based on the answer from #David Schwartz, here is my new code:
public static bool AcquireMutex()
{
// Protect against double acquisitions
if (MyMutex != null)
{
throw new ApplicationException("Failed to acquire mutex");
}
bool createdNew;
MyMutex = new Mutex(true, MutexName, out createdNew);
if (createdNew)
{
// Mutex was created so ownership is guaranteed; no need to wait on it.
return true;
}
try
{
if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false))
{
MyMutex = null;
return false;
}
}
catch (AbandonedMutexException)
{
// Other application was aborted, which led to an abandoned mutex.
// This is fine, as we have still successfully acquired the mutex.
}
return true;
}
There's a constructor specifically designed for this purpose. From the docs:
createdNew
Type: System.Boolean
When this method returns, contains a Boolean that is true if a local mutex was created (that is, if name is null or an empty string) or if the specified named system mutex was created; false if the specified named system mutex already existed. This parameter is passed uninitialized.
I have some System.Diagnotics.Processes to run. I'd like to call the close method on them automatically. Apparently the "using" keyword does this for me.
Is this the way to use the using keyword?
foreach(string command in S) // command is something like "c:\a.exe"
{
try
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
catch (Exception e)
{
// notify of process failure
}
}
I'd like to start multiple processes to run concurrently.
using(p = Process.Start(command))
This will compile, as the Process class implements IDisposable, however you actually want to call the Close method.
Logic would have it that the Dispose method would call Close for you, and by digging into the CLR using reflector, we can see that it does in fact do this for us. So far so good.
Again using reflector, I looked at what the Close method does - it releases the underlying native win32 process handle, and clears some member variables. This (releasing external resources) is exactly what the IDisposable pattern is supposed to do.
However I'm not sure if this is what you want to achieve here.
Releasing the underlying handles simply says to windows 'I am no longer interested in tracking this other process'. At no point does it actually cause the other process to quit, or cause your process to wait.
If you want to force them quit, you'll need to use the p.Kill() method on the processes - however be advised it is never a good idea to kill processes as they can't clean up after themselves, and may leave behind corrupt files, and so on.
If you want to wait for them to quit on their own, you could use p.WaitForExit() - however this will only work if you're waiting for one process at a time. If you want to wait for them all concurrently, it gets tricky.
Normally you'd use WaitHandle.WaitAll for this, but as there's no way to get a WaitHandle object out of a System.Diagnostics.Process, you can't do this (seriously, wtf were microsoft thinking?).
You could spin up a thread for each process, and call `WaitForExit in those threads, but this is also the wrong way to do it.
You instead have to use p/invoke to access the native win32 WaitForMultipleObjects function.
Here's a sample (which I've tested, and actually works)
[System.Runtime.InteropServices.DllImport( "kernel32.dll" )]
static extern uint WaitForMultipleObjects( uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds );
static void Main( string[] args )
{
var procs = new Process[] {
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 2'" ),
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 3'" ),
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 4'" ) };
// all started asynchronously in the background
var handles = procs.Select( p => p.Handle ).ToArray();
WaitForMultipleObjects( (uint)handles.Length, handles, true, uint.MaxValue ); // uint.maxvalue waits forever
}
For reference:
The using keyword for IDisposable objects:
using(Writer writer = new Writer())
{
writer.Write("Hello");
}
is just compiler syntax. What it compiles down to is:
Writer writer = null;
try
{
writer = new Writer();
writer.Write("Hello");
}
finally
{
if( writer != null)
{
((IDisposable)writer).Dispose();
}
}
using is a bit better since the compiler prevents you from reassigning the writer reference inside the using block.
The framework guidelines Section 9.3.1 p. 256 state:
CONSIDER providing method Close(), in addition to the Dispose(), if close is standard terminology in the area.
In your code example, the outer try-catch is unnecessary (see above).
Using probably isn't doing what you want to here since Dispose() gets called as soon as p goes out of scope. This doesn't shut down the process (tested).
Processes are independent, so unless you call p.WaitForExit() they spin off and do their own thing completely independent of your program.
Counter-intuitively, for a Process, Close() only releases resources but leaves the program running. CloseMainWindow() can work for some processes, and Kill() will work to kill any process. Both CloseMainWindow() and Kill() can throw exceptions, so be careful if you're using them in a finally block.
To finish, here's some code that waits for processes to finish but doesn't kill off the processes when an exception occurs. I'm not saying it's better than Orion Edwards, just different.
List<System.Diagnostics.Process> processList = new List<System.Diagnostics.Process>();
try
{
foreach (string command in Commands)
{
processList.Add(System.Diagnostics.Process.Start(command));
}
// loop until all spawned processes Exit normally.
while (processList.Any())
{
System.Threading.Thread.Sleep(1000); // wait and see.
List<System.Diagnostics.Process> finished = (from o in processList
where o.HasExited
select o).ToList();
processList = processList.Except(finished).ToList();
foreach (var p in finished)
{
// could inspect exit code and exit time.
// note many properties are unavailable after process exits
p.Close();
}
}
}
catch (Exception ex)
{
// log the exception
throw;
}
finally
{
foreach (var p in processList)
{
if (p != null)
{
//if (!p.HasExited)
// processes will still be running
// but CloseMainWindow() or Kill() can throw exceptions
p.Dispose();
}
}
}
I didn't bother Kill()'ing off the processes because the code starts get even uglier. Read the msdn documentation for more information.
try
{
foreach(string command in S) // command is something like "c:\a.exe"
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
}
catch (Exception e)
{
// notify of process failure
}
The reason it works is because when the exception happens, the variable p falls out of scope and thus it's Dispose method is called that closes the process is how that would go. Additionally, I would think you'd want to spin a thread off for each command rather than wait for an executable to finish before going on to the next one.
I have a .NET application that I only allow to run a single process at a time of, however that app is used on Citrix boxes from time to time, and as such, can be run by multiple users on the same machine.
I want to check and make sure that the application is only running once per user session, because right now if user A is running the app, then user B gets the "App already in use" message, and should not.
This is what I have now that checks for the running process:
Process[] p = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
if (p.Length > 1)
{
#if !DEBUG
allowedToOpen &= false;
errorMessage +=
string.Format("{0} is already running.{1}", Constants.AssemblyTitle, Environment.NewLine);
#endif
}
EDIT: Improved the answer according to this cw question ...
You can use a mutex for checking wether the app already runs:
using( var mutex = new Mutex( false, AppGuid ) )
{
try
{
try
{
if( !mutex.WaitOne( 0, false ) )
{
MessageBox.Show( "Another instance is already running." );
return;
}
}
catch( AbandonedMutexException )
{
// Log the fact the mutex was abandoned in another process,
// it will still get aquired
}
Application.Run(new Form1());
}
finally
{
mutex.ReleaseMutex();
}
}
Important is the AppGuid - you could make it depend on the user.
Maybe you like to read this article: the misunderstood mutex
As tanascius already say, you can use the Mutex.
On a server that is running Terminal Services, a named system mutex can have two levels of visibility. If its name begins with the prefix "Global\", the mutex is visible in all terminal server sessions. If its name begins with the prefix "Local\", the mutex is visible only in the terminal server session where it was created.
Source: msdn, Mutex Class
Just stating the obvious - although Mutex is usually considered better solution, you can still solve the single-instance-per-session issue without Mutex - just test the SessionId as well.
private static bool ApplicationIsAlreadyRunning()
{
var currentProcess = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
// test if there's another process running in current session.
var intTotalRunningInCurrentSession = processes.Count(prc => prc.SessionId == currentProcess.SessionId);
return intTotalRunningInCurrentSession > 1;
}
Source (no Linq)
If Form1 launches non-background threads, and that Form1 exits, you've got a problem: the mutex is released but the process is still there. Something along the lines below is better IMHO:
static class Program {
private static Mutex mutex;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
bool createdNew = true;
mutex = new Mutex(true, #"Global\Test", out createdNew);
if (createdNew) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else {
MessageBox.Show(
"Application is already running",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
}
}
The mutex won't be released as long as the primary application domain is still up. And that will be around as long as the application is running.