Implementing the outside application „openedFileView“ in c# Project - c#

I work on a application where i want to find out which files on my filesystem is used by a Process.
After trying around with the System.Diagnostics.Process class, and didn´t get the resulst i wanted i find the application called OpenedFileView from Nirsoft.
http://www.nirsoft.net/utils/opened_files_view.html
Basically it does exactly what i want but i have some problems with the implimication in my project.
The option wich “OpenedFileView” gives you is to start it with some arguments that it creates you an txt file with all the information i want.
But for my case i want to whach the processes in realtime, and if i start the application repetitively i always have the hourglass at my mouse cursor.
So after this i tryed some ways to get rid of it, tryed out to put it in a BackgroundWorker Thread. But this changed nothing at all. I also looked for a way to force the Process not to exit, and sending new arguments to it, but this also didn´t worked.
So is there any way to use this application in the way I want, or does this didn´t work at all?
I hope somebody can help me either with getting away this annoying mouse cursor hourglass, or with a better implimication of this application so i can use it in realtime!
Thanks alot!
private void start()
{
_openedFileView = new Process();
_openedFileView.StartInfo.FileName = "pathToApp\\OpenedFilesView.exe";
_openedFileView.EnableRaisingEvents = true;
_openedFileView.Exited += new EventHandler(myProcess_Exited);
_openedFileView.StartInfo.Arguments = "/scomma pathToOutputFile";
_openedFileView.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
start();
}

You'll have to tweak your "real-time" requirement. A process can open and close hundreds of files in the time it takes to start that program. Given that you can never get a truly accurate view of file usage, you might as well reduce the rate at which you start the program. One immediate benefit is that you'll greatly reduce the CPU load.
A better mousetrap is the Sysinternals' Handle utility. It's a much lighter weight program. And is a console mode app, you can redirect its output so you don't have to use a file. And there's no wait cursor. It also allows selecting a specific process with the -p command line argument, an option you really want to use to keep execution time down to a reasonable level. This sample code worked pretty well:
using System;
using System.Diagnostics;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
for (int ix = 0; ix < 100; ++ix) {
var psi = new ProcessStartInfo(#"c:\bin\handle.exe", #"-p consoleapplication1");
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
var prc = Process.Start(psi);
var txt = prc.StandardOutput.ReadToEnd();
Console.WriteLine(txt);
System.Threading.Thread.Sleep(1000);
}
Console.ReadLine();
}
}
}
Oh, and resist the temptation to use its "close file" option. That's only good if you are looking for a way to permanently destroy data on your hard drive.

Related

Pass String from python script to C# UI [duplicate]

I'm making a program that controls a game server. One of the functions I'm making, is a live server logfile monitor.
There is a logfile (a simple textfile) that gets updated by the server as it runs.
How do I continuously check the logfile and output it's content in a RichTextBox?
I did this simple function just try and get the content of the log. It will of course just get the text row by row and output it to my textbox. Also it will lock the program for as long as the loop runs, so I know it's useless.
public void ReadLog()
{
using (StreamReader reader = new StreamReader("server.log"))
{
String line;
// Read and display lines from the file until the end of the file is reached.
while ((line = reader.ReadLine()) != null)
{
monitorTextBox.AppendText(line + "\n");
CursorDown();
}
}
}
But how would you go about solving the live monitoring as simple as possible?
*** EDIT ***
I'm using Prescots solution. great stuff.
At the moment I'm using a sstreamreader to put the text from the file to my textbox. I ran into the problem is that, whenever I tried to access any of the gui controls in my event handler the program just stopped with no error or warnings.
I found out that it has to do with threading. I solved that like this:
private void OnChanged(object source, FileSystemEventArgs e)
{
if (monitorTextField.InvokeRequired)
{
monitorTextField.Invoke((MethodInvoker)delegate { OnChanged(source, e); });
}
else
{
StreamReader reader = new StreamReader("file.txt");
monitorTextField.Text = "";
monitorTextField.Text = reader.ReadToEnd();
reader.Close();
CursorDown();
}
}
Now my only problem is that the file.txt is used by the server so I can't access it, since it's "being used by another process". I can't control that process, so maybe I'm out of luck.
But the file can be opened in notepad while the server is running, so somehow it must be possible. Perhaps I can do a temp copy of the file when it updates and read the copy. I don't know.
Check out the System.IO.FileSystemWatcher class:
public static Watch()
{
var watch = new FileSystemWatcher();
watch.Path = #"D:\tmp";
watch.Filter = "file.txt";
watch.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite; //more options
watch.Changed += new FileSystemEventHandler(OnChanged);
watch.EnableRaisingEvents = true;
}
/// Functions:
private static void OnChanged(object source, FileSystemEventArgs e)
{
if(e.FullPath == #"D:\tmp\file.txt")
{
// do stuff
}
}
Edit: if you know some details about the file, you could handle the most efficent way to get the last line. For example, maybe when you read the file, you can wipe out what you've read, so next time it's updated, you just grab whatever is there and output. Perhaps you know one line is added at a time, then your code can immediately jump to the last line of the file. Etc.
Although the FileSystemWatcher is the most simple solution I have found it to be unreliable in reality.. often a file can be updated with new contents but the FileSystemWatcher does not fire an event until seconds later and often never.
The only reliable way I have found to approach this is to check for changes to the file on a regular basis using a System.Timers.Timer object and checking the file size.
I have written a small class that demonstrates this available here:
https://gist.github.com/ant-fx/989dd86a1ace38a9ac58
Example Usage
var monitor = new LogFileMonitor("c:\temp\app.log", "\r\n");
monitor.OnLine += (s, e) =>
{
// WARNING.. this will be a different thread...
Console.WriteLine(e.Line);
};
monitor.Start();
The only real disadvantage here (apart from a slight performance delay caused by file size checking) is that because it uses a System.Timers.Timer the callback comes from a different thread.
If you are using a Windows Forms or WPF app you could easily modify the class to accept a SynchronizingObject which would ensure the event handler events are called from the same thread.
As #Prescott suggested, use a FileSystemWatcher. And make sure, you open the file with the appropriate FileShare mode (FileShare.ReadWrite seems to be appropriate), since the file might still be opened by the server. If you try to open the file exclusively while it is still used by another process, the open operation will fail.
Also in order to gain a bit of performance, you could remember the last position up to which you already have read the file and only read the new parts.
Use this answer on another post c# continuously read file.
This one is quite efficient, and it checks once per second if the file size has changed.
You can either run it on another thread (or convert to async code), but in any case you would need to marshall the text back to the main thread to append to the textbox.
Try adding a Timer and have the Timer.Tick set to an Interval of 1 second. On Timer.Tick you run the function.
private void myTimer_Tick(object sender, EventArgs e)
{
ReadLog();
}

Execute process/program silently

I am creating a wpf application that needs a prerequisite. If that prerequisites is not met then I ask the user if he will like to install the prerequisite that happens to be: Microsoft Visual C++ 2010 SP1 Redistributable Package.
So if the user chose to install the prerequisite I will execute vcredist_x86.exe (that is the file that get's downloaded from the first link that I provided).
Then on my application I will be able to tell when the installation is complete by doing something like:
ProcessStartInfo psi = new ProcessStartInfo(#"vcredist_x86.exe");
var p = new Process(); p.StartInfo = psi;
p.Start(); //start the process
p.WaitForExit(); // wait for the installation to finish
// installation should be done now
Ok everything works great so far. The problem is that I have a progress bar in my wpf application and I will like to show the progress in there.
I have been able to show the progress of the installation by doing the following:
There is a program called AutoIt that it is great for automating simple tasks. For example I can easily detect if a window exists with autoit by using something like:
I could then compile that script and create a very small executable. In that executable I will return 1 if the specified window exists or 0 otherwise.
When the user moves to the next window my script might return 2 because that is a different window. AutoIt can also see the progress of a progress bar of a window!!! so if that script returns 80 for example then I will update my progress to 80% for instance.
I do that by doing something like:
// start the autoitExecutable....
// wait for executable to exit usually takes 10 miliseconds it is fast
if (autoitProcess.ExitCode == 1)
{
// do somthing
}else if(autoitProcess.ExitCode == 2)
{
// do something else
} //etc....
As you can see I have to execute that script every 1 second to detect what changes have been done in order to update my progress bar in WPF. That works but every time I execute that executable with c# I get the:
cursor for about 500 milliseconds then on the next second it appears again. That becomes annoying even though no windows show up. It will be nice if I could get rid of that cursor and execute that executable silently somehow. when I execute the autoit executable there are no windows that show up nor nothing else.
P.S.
I know I could use c# to check for the existance of a window and maybe see the value of other window's handler's just like autoit is able to do it but it is so simple to create those programs with AutoIt and it will be nice if I could use AutoIt instead of C# for this kind of taks
I saw this behavior when the exe was set to "windows application" rather than "console application".
Changing the type to console no longer gives a busy cursor at launch.
You could add an event handler as well for example
System.Diagnostics.ProcessStartInfo p = new
System.Diagnostics.ProcessStartInfo(#"vcredist_x86.exe") ;
p.Arguments="-RunForever";
proc = new System.Diagnostics.Process();
proc.StartInfo = p;
proc.EnableRaisingEvents = true;
proc.Exited += new EventHandler(myProcess_Exited);
proc.Start();
inside the event if I wanted to do something like this
// Inside the form class:
private System.Diagnostics.Process proc;
private void myProcess_Exited(object sender, System.EventArgs e)
{
button3.BackColor=Color.LightGreen; //success indicator
}
if you wanted to do this in a While Loop you could also do something like this for example
but you would have to change the params to fit your case
example code you can utilize
while(!autoitProcess.WaitForExit(someTimeout))
{
if(ShouldCancel)
{
break;
}
}
does this make sense or help out...?

How do I limit my Windows application to spawning a single instance of a process?

I am working on a Windows application. I have created a help file (.chm) using a third party tool and I call it from the Windows application. The help file is invoked successfully when I click on Help menu item or press F1 for the application.
The problem I am facing is that if I click on the menu item again or press F1 (while the application is open and I have not closed the previous help file) it opens another instance of the help file.
Let me be clear by giving an example: I want it to be just like the "Solitaire" game. No matter how many times you press F1 or the Contents menu item it shows only one help window.
I want to do same thing like "Solitaire". I don't want multiple instances to be created.
I hope you understood my problem. Please let me know if my query is wrong.
I have posted my code below.
ProcessStartInfo info;
Process exeprocess;
The below code is in Help menuitem click event.
private void mnuContents_Click(object sender, EventArgs e)
{
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
}
One solution is:
Have your application create a system-wide resource (the example below uses a Win32 mutex)
Check the resource before you spawn the .chm (I imagine you're probably using ShellExec or some variant to spawn the help file.
Here's example code (in C++/Win32 code):
http://support.microsoft.com/kb/243953
Another, different approach is to see if any currently running processes match the one you would spawn. Here's example code for this approach:
http://www.dotnetperls.com/single-instance-windows-form
You have a Process object, so you should probably store it somewhere and check if it is still active the next time the help command is invoked. You could use Process.HasExited for that purpose. If it has exited, clean up the Process object by calling Dispose() and then launch a new instance, storing it away again. Repeat as needed.
Ok this is your block of code to start the CHM viewer:
private void mnuContents_Click(object sender, EventArgs e)
{
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
}
in exeprocess there is a property called Id. You need to keep track of that Id for the next time the user presses F1 or the menu key.
You need to do a check like
private void mnuContents_Click(object sender, EventArgs e)
{
if (Process.GetProcessById(self.previousId) != null) {
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
self.previousId = exeprocess.Id;
}
}
Something like that would work. If you want to get fancy, you can bring the already-running process to the foreground as well.

C#-C Interprocess communication

Okay, so I have a program written in c# that starts up a process running another program, this one written in C. Now I already worked out redirecting the stdout from the C program and picking it up on the C# side, and it works great. But I need a way for the C# program to tell the C program to end. My first thought, was that since the C program originally was controlled through testing kbhit from conio.h, that I could just redirect stdin and streamwrite something and it would detect a key hit, but that didn't work (I'm guessing kbhit doesn't lend itself to redirection), so I searched around and a lot of people kept suggesting PeekConsoleInput(), because I'm writing this program exclusively for windows (in fact a specific machine). So I changed the c program to use PeekConsoleInput instead of kbhit and redirected stdin and it still didn't detect anything I sent to it. For example in C...
#include <stdio.h>
#include <windows.h>
int main() {
BOOL peeked = 0;
HANDLE input_handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events = 0; // how many events took place
INPUT_RECORD input_record; // a record of input events
DWORD input_size = 1; // how many characters to read
printf("Hello World\n");
fflush(stdout);
while (1) {
FlushConsoleInputBuffer(input_handle);
peeked = PeekConsoleInput(input_handle, &input_record, input_size, &events);
if (peeked && events>0) {
break;
}
}
printf("Hit Detected\n");
return 0;
}
and a snippet from the C# code...
ProcessStartInfo info = new ProcessStartInfo("CTest.exe");
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardInput = true;
pro = new Process();
pro.StartInfo = info;
pro.Start();
StreamWriter sw = pro.StandardInput;
sw.AutoFlush = true;
pro.BeginOutputReadLine();
pro.OutputDataReceived += new DataReceivedEventHandler(pro_OutputDataReceived);
sw.WriteLine("Q");
The C program executes by itself, but when the C# program runs it, it never reaches "Hit Detected". I also delayed the s.WriteLine("Q") by a few seconds to see if it was a timing issue and it still didn't work.
Ideally, I wanted the C program to be able to run by itself, or be run by the C# program, but even if you couldn't run the C program by itself, that wouldn't be so bad.
One thing I tried that worked, was to have the C# program just write a file, and have the C program just poll with fopen's until it successfully opens it, but one of the main purposes of this C program is to write to data to disk really fast, and I worry that polling the disk may be slowing it down.
Another thing that kinda worked was just closing the process. But that's messy because the C program needs to clean up some stuff before it closes (unless there's some way to get the C program to execute some code before it shuts down, but I'm not sure if you can do that).
Other ways to get this done would be sockets, pipes, etc. but it seems like a lot of work for just a one bit signal. Also, all the examples I could find about how to do that all seemed to be how to get two C# programs to communicate or how to get two C programs to communicate, never two different programs in two different languages.
So, firstly, is there any way to get this stdin redirection thing working? and if not, what's the easiest solution to tell the C process that it needs to exit?
I ran into the same problem and was able to get it to work using SendKeys. Just add a reference to System.Windows.Forms if you have a WPF app.
For the processes StartInfo I used:
newProcess.StartInfo.UserShellExecute = false;
newProcess.StartInfo.CreateNoWindow = false;
newProcess.StartInfo.RedirectStandardInput = false;
newProcess.StartInfo.RedirectStandardOutput = true;
newProcess.StartInfo.RedirectStatndardError = true;
newProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
newProcess.OutputDataReceived += new DataReceivedHandler(gotData);
The reason for setting CreatNoWindow to false is that you can find the Window in Spy++. ProcessWindowStyle.Hidden hides the window after it pops up for a brief moment.
RedirectStatndardInput must be false because we are using SendKeys to simulated keyboard input to the hidden window.
Using SendKeys.waitSend("command{ENTER}"); I was able to send a command to the console app that uses _kbhit() and getc() for input.
Have you tried to see if and by how much the C program is faster at writing files?
There are other ways (in Windows) to do interprocess communication.
Named Pipes (similar to TCP)
Memory mapped files (might be a good option here - similar to your
other experiment which worked)
TCP/IP (as you've suggested.)
As far as TCP/IP is concerned it is not constrained to works with software build using the same language and tool. Your C program will be the TCP server and your C# program will be the TCP client. If you know how to do this in either of the languages you've got your answer.
You could use the Process object to kill the spawned process:
(assuming that the C program has a handler to do its cleanup after receiving the "CloseMainWindow()" signal)
/// <summary>
/// Close the shelled process, if there is any
/// </summary>
/// <param name="reason">why closing?</param>
public static void shellTerminate(string reason)
{
Process p = shelledProcess;
try
{
if (p == null)
{
o3(reason + ". No shelled process.");
}
else if (p.HasExited)
{
o3(reason + ". Process has exited already.");
}
else
{
//Process is still running.
//Test to see if the process is hung up.
if (p.Responding)
{
//Process was responding; close the main window.
o3(reason + ". Process is being closed gracefully.");
if (p.CloseMainWindow())
{
//Process was not responding; force the process to close.
o3(reason + ". Process is being killed.");
p.Kill();
p.Close();
p = null;
}
}
if (p != null)
{
//Process was not responding; force the process to close.
o3(reason + ". Process is being killed.");
p.Kill();
}
p.Close();
}
if (shellOut != null)
{
shellOut.Close();
shellOut = null;
}
shelledProcess = null;
}
catch (Exception ex)
{
o("Exception in shellTerminate: " + ex.Message);
}
}

How to make script/program to make it so an application is always running?

I have a simple .exe that needs to be running continuously.
Unfortunately, sometimes it crashes unexpectedly, and there's nothing that can be done for this.
I'm thinking of like a C# program that scans the running application tree on a timer and if the process stops running it re-launches it... ? Not sure how to do that though....
Any other ideas?
It's fairly easy to do that, but the "crashes unexpectedly, and there's nothing that can be done for this" sounds highly suspect to me. Perhaps you mean the program in question is from a third party, and you need to work around problems they can't/won't fix?
In any case, there's quite a bit of sample code to do exactly what you're talking about.
The first solution would be to fix your EXE, so it does not crash. If you can not fix it now, you probably need to add exception handling, so you can catch the exception, and not close the EXE.
Second solution is to write simple guard programm that will start your simple .exe and will monitor specific process handle. It will restart your program when it closes.
easiest way is to have you program see if an instance of itself is running and exit if it is. Set up a scheduled task to run it every couple of minutes.
class Program
{
static void Main(string[] args)
{
if (IsRunning())
{
return;
}
else
{
for (int x = 0; x < 10; x++)
{
//Do Stuff
System.Threading.Thread.Sleep(1000);
}
}
}
private static bool IsRunning()
{
Process[] P = Process.GetProcessesByName( Process.GetCurrentProcess().ProcessName ) ;
return P.Count() > 1;
}
}
One trick occasionally employed by malware in days past was to have two processes that each monitor the currently running processes and restart the other process if it is terminated.
The System.Diagnostics namespace has classes which can help, particularly "Process".
For example
static Process[] Process.GetProcesses()
returns a list of all the currently running processes.
If your other process is not in this list, you just restart it with, for example
Process.Start()
Your program needs to initially start your target process itself (with Process.Start), then simply wait for it to terminate (with WaitForExit on object that is returned by Process.Start()). After that whole procedure is repeated.
This way you'd be sure that you are watching the process you are interested in, and you don't need to poll process list at all.
Process.Start() and WaitForExit() usage example.

Categories

Resources