C# console application design like htop - c#

I want to build console application with similar interface like htop's one (fixed console design). Here is a link to htop console design: http://upload.wikimedia.org/wikipedia/commons/b/b1/Htop.png. I wanted to ask how can I build application like this as I only know C#'s Console.Write() method. I am writing simple program that is starting up applications via Process.Start() and then I am monitoring for example their RAM usage via Process.WorkingSet64 and outputing it via simple Console.WriteLine() each line to console. But how could I design C# console application like htop so it has fixed design that will be for example refreshing every 1 second. By fixed designed I mean that I it will be fixed position on the console where I will print out process names, ram usage, application name, etc. Here is my code of the program:
class Program
{
static void Main(string[] args)
{
string[] myApps = { "notepad.exe", "calc.exe", "explorer.exe" };
Thread w;
ParameterizedThreadStart ts = new ParameterizedThreadStart(StartMyApp);
foreach (var myApp in myApps)
{
w = new Thread(ts);
w.Start(myApp);
Thread.Sleep(1000);
}
}
public static void StartMyApp(object myAppPath)
{
ProcessStartInfo myInfoProcess = new ProcessStartInfo();
myInfoProcess.FileName = myAppPath.ToString();
myInfoProcess.WindowStyle = ProcessWindowStyle.Minimized;
Process myProcess = Process.Start(myInfoProcess);
do
{
if (!myProcess.HasExited)
{
myProcess.Refresh(); // Refresh the current process property values.
Console.WriteLine(myProcess.ProcessName+" RAM: " + (myProcess.WorkingSet64 / 1024 / 1024).ToString() + "\n");
Thread.Sleep(1000);
}
}
while (!myProcess.WaitForExit(1000));
}
}
EDIT: Thanks for pointing to Console.SetCursorPosition #Jim Mischel. I want to use that in my application but now I have another problem. How could I pass to my StartMyApp method, the index number from myApps array so I could do something like:
Console.WriteLine((Array.IndexOf(myApps, myAppPath) + " " + myProcess.ProcessName+" RAM: "+ (myProcess.WorkingSet64 / 1024 / 1024).ToString() + "\n");
That is inside my StartMyApp method. Any method I use I end up getting The name 'myApps' does not exist in the current context. This is very important for me so I could design my application later using Console.SetCursorPosition but I need that index number. So my output would be for example:
0 notepad RAM: 4
1 calc RAM: 4
2 explorer RAM: 12

You want to call Console.SetCursorPosition to set the position where the next write will occur. The linked MSDN topic has a basic example that will get you started.
You'll also be interested in the BackgroundColor, ForegroundColor, and possibly other properties. See the Console class documentation for details.

Related

Call Process.Start once and subsequent calls without starting new process

I have a c# method that sets the brightness of all monitors using a third-party executable.I call it using the method below. The problem is that I need to call this executable with different parameters to change the brightness. But my code creates a new process each time I call SetBrightness. How does one use an exiting process that is already running, and pass different parameters to execute it again? I don't see any method inthe Process class that makes this easy.
Edit: When I run this exe using the command line, the process stays open in the Windows System Tray, and I see the process is running in Task Manager. When I run my code, however, I sometimes see two instances of the exe in Task Manager. So I guess what I'm trying to do is always call the same instance but with different parameters. Restarting the exe every time is not an option because it takes too long to start up each time.
public bool SetBrightness(short monitorStartIndex, short monitorEndIndex, short brightness)
{
// Construct the parameter string used by the tool so that it updates all monitors in one call.
// Example "1 b75 2 b75" will set brightness to 75 for monitors 1 and 2.
StringBuilder arguments = new StringBuilder();
for (int i = monitorStartIndex; i <= monitorEndIndex; i++)
{
arguments.Append(i).Append(" ");
arguments.Append(string.Format("b{0}", brightness)).Append(" ");
}
var path = Path.GetDirectoryName(Environment.GetCommandLineArgs()[1]);
var final = Path.Combine(path, "External Assemblies\\ClickMonitorDDC_3_9.exe");
var p = new Process
{
StartInfo =
{
FileName = final,
Arguments = arguments.ToString(),
UseShellExecute = false,
RedirectStandardOutput = true
}
};
try
{
p.Start();
}
catch (Exception e)
{
Trace.TraceError("Error while changing the brightness using ClickMonitorDDC_3_9.exe. Inner Exception : " + e.Message);
return false;
}
return true;
}
You will want to use the WaitForExit method available in the Process class. If you attempt to use the third-party executable from the command line using the same type of parameters as you have in your code, it should return to the prompt as it is setting the parameters and exiting. You would just call your method whenever you want to change the brightness and wait until it's set and exit out.
Change your code as seen below:
try
{
p.Start();
p.WaitForExit()
}

Socket connection from Unity to retrieve SUMO's vehicles

I would like to generate a 3D scenario for a traffic simulation.
The main idea would be having SUMO running a simulation and then getting the direction, speed and coordinates (X,Y) from each vehicle, so that I would create 3D models for this cars.
For this purpose, I was thinking about using some kind of TCP/IP communication between Unity and SUMO. Since this is possible while communicating SUMO with a network simulator such as OMNeT++, I was wondering if this would also be possible. I don't need to control the simulation in SUMO from Unity, just retrieve data regarding the vehicles in the network.
Unfortunately, I have no remarkable experience with Unity, so I cannot provide any code trying to achieve this...
EDIT:
As requested, I included some code. However, I only have code in Java.
String configFile = "test/resources/sumo_maps/Test2/Test2.sumo.cfg";
SumoTraciConnection trial = new SumoTraciConnection(configFile,-1);
trial.runServer();
Collection<Vehicle> vehicles = trial.getVehicleRepository().getAll().values();
for(Vehicle car : vehicles){
bw.write(time + " // The vehicle with ID: " + car.getID()+ " is driving "
+ "with a speed of "+ car.getSpeed() + " and is in coordinates x: " +car.getPosition().getX()+
" and y: " + car.getPosition().getY());
bw.newLine();
}
Now, let's proceed to get a bit into the class SumoTraciConnection and its methods. This class is part of the mentioned (in the comments) library Traci4j.
It can be found in GitHub in case you need more info: https://github.com/egueli/TraCI4J/blob/master/src/java/it/polito/appeal/traci/SumoTraciConnection.java
The constructor:
public SumoTraciConnection(String configFile, int randomSeed) {
this.randomSeed = randomSeed;
this.configFile = configFile;
}
Now the runServer() method (I put the one with a boolean argument because if no parameter is given then it is automatically called with a false) Basically, this boolean is used to determine wheter the GUI version of SUMO or the console version will be ran:
public void runServer(boolean withGui) throws IOException, InterruptedException {
retrieveFromURLs(); //Checks if the configFile given has an "http://" at the beggining, in order to download the file
int port = findAvailablePort(); //creates a Socket and finds a port with ServerSocket.getLocalPort()
runSUMO(port, withGui); //It is used to run SUMO with different options, such as the configFile for the simulation, the remote port... sumoProcess is set here as: sumoProcess = Runtime.getRuntime().exec(argsArray);, where argsArray contains the different options mentioned
tryConnect(InetAddress.getLocalHost(), port, sumoProcess); // tryConnect basicaly calls this method tryConnectOnce, which connects as a client to the sumo process mentioned before, and does some checks that everything is correct.
postConnect(); //I will explain this function after
}
postConnect() initialices the DataInput and DataOutput streams and creates the repositories. I show now the relevant parts of the code:
dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
vehicles = new HashMap<String, Vehicle>();
edgeRepo = new Repository.Edges(dis, dos, newIDListQuery(Constants.CMD_GET_EDGE_VARIABLE));
addStepAdvanceListener(edgeRepo);
laneRepo = new Repository.Lanes(dis, dos, edgeRepo, newIDListQuery(Constants.CMD_GET_LANE_VARIABLE));
vehicleListQuery = newIDListQuery(Constants.CMD_GET_VEHICLE_VARIABLE);
addStepAdvanceListener(new StepAdvanceListener() {
public void nextStep(double step) {
vehicleListQuery.setObsolete();
}
});
vehicleListBefore = new HashSet<String>(vehicleListQuery.get());
vehicleRepo = new Repository.Vehicles(dis, dos, edgeRepo, laneRepo, vehicles, vehicleListQuery);
addStepAdvanceListener(vehicleRepo);
Where one StepAdvanceListener is just the following(I cannot explain exactly what is this for but I understand that is something that allow us to realize the new simulationstep has been done, so we have to update the repositories):
//Interface for an object that can be notified when the simulation advances by one step.
public interface StepAdvanceListener {
/**
* Callback for step advancement.
* #param step the new simulation time, in seconds
*/
void nextStep(double step);
}
Up to here, it would be the part related to the connection with SUMO. In the next edit (I need some rest right now..) I'll put the parts related with the Repositories and the Data retrieval
Thanks in advance!

Sending a keypress to the active window that doesn't handle Windows message in C#

When I am detecting a pixel with a given color, I want to send the Key "k".
The problem is that even though the window is active, wit the following code it sends me an exception : SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method. The Sendwait method doesn't seem to press the key fast enough (but at least it gives no exception). I don't really care if the required solution is "dirty", it's a poc I'll use once
static void Main(string[] args)
{
string ligne;
string previousligne = string.Empty;
int compteur = 0;
while (true)
{
Color pixColor = Win32.GetPixelColor(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
ligne = pixColor.Name;
if (previousligne != ligne)
{
if (ligne == "ffcecefe")
{
SendKeys.Send("k");
}
Console.WriteLine(ligne);
System.IO.File.AppendAllText(#"C:\Users\Public\WriteLines.txt", "-----" + DateTime.Now.Minute + ":" + DateTime.Now.Second + ":" + DateTime.Now.Millisecond + " = " + ligne);
previousligne = ligne;
compteur++;
if (compteur % 10 == 0)
{
System.IO.File.AppendAllText(#"C:\Users\Public\WriteLines.txt", "---------" + compteur);
Console.WriteLine("---------" + compteur);
}
}
}
}
If you know Final Fantasy X, I'm trying to automate the process of avoiding the lightning bolts : video
I could just cheat to get the ingame result (or do it the legit way) and it would have already been done, but if I can learn a bit more of C# instead it would be better.
The console window (i.e. your running process) is the active window which SendKeys is sending data to. Since the console doesn't have a message loop, there is nowhere for the message to be received at, and it's lost. You would need to activate the target window with something like SetActiveWindow().
See also How do I send key strokes to a window without having to activate it using Windows API?

C#/.NET console applications that behave like normal Unix tools

This question is regarding designing console applications in .NET that behave like normal Unix tools. The basic fundamental of Unix tools is that they can be chained together with 1 tool being able to take input from any compatible stream and giving output to any compatible stream.
If I'm writing console applications in .NET for Windows, what are the general things I need to follow for my tools to be of the same type?
"Do only one thing" is definitely one, but there are more:
Do only one thing and do it well
Output nothing on success (other than the result, of course)
Use stdin for the input, stdout for the output, and stderr for errors
Use non-zero exit codes to communicate failure
With this in mind, here's what is, in my opinion, a more "unixy" "to-uppercase" program in C#:
using System;
class Program
{
static int Main(string[] args)
{
try
{
var buf = new char[4096];
while (true)
{
int read = Console.In.Read(buf, 0, buf.Length);
if (read == 0)
break;
for (int i = 0; i < read; i++)
buf[i] = char.ToUpper(buf[i]);
Console.Out.Write(buf, 0, read);
}
return 0;
}
catch (Exception e)
{
Console.Error.WriteLine("ERROR: " + e.Message);
return 1;
}
}
}
Like a typical unixy program, you can run it without arguments and then it will be interactive, allowing you to type input manually on the console, terminated with Ctrl+Z, printing output whenever it receives a chunk of your input. Or you could pass it a file to process: uppercase.exe <input.txt and it will print the output to the console. Or you could redirect the output to a file too. Or you could pipe the input into it. Etc.
The main principle behind *nix tools is do one thing, and do it well.
Let's say I set out to create a *nix style tool that converted the input to uppercase. It's a trivial example, but that allows me to post the whole program here.
Here's the source code:
using System;
using System.Diagnostics.Contracts;
namespace Upperc {
class Program {
static void Main(string[] args) {
var input = Console.ReadLine();
Contract.Assert(input != null);
Console.WriteLine(input.ToUpperInvariant());
}
}
}
I took advantage of the fact that Console methods handle input and output and the standard streams. Example usage is:
> type example.txt | Upperc.exe > uppercased.txt
The input file is a plain text file:
example text file before processing
and the output file:
EXAMPLE TEXT FILE BEFORE PROCESSING

Search String takes a long time the first time only?

No shortage of search for string performance questions out there yet I still can not make heads or tails out of what the best approach is.
Long story short, I have committed to moving from 4NT to PowerShell. In leaving the 4NT I am going to miss the console super quick string searching utility that came with it called FFIND. I have decided to use my rudimentary C# programming skills to try an create my own utility to use in PowerShell that is just as quick.
So far search results on a string search in 100's of directories across a few 1000 files, some of which are quite large, are FFIND 2.4 seconds and my utility 4.4 seconds..... after I have ran mine at least once????
The first time I run them FFIND does it near the same time but mine takes over a minute? What is this? Loading of libraries? File indexing? Am I doing something wrong in my code? I do not mind waiting a little longer but the difference is extreme enough that if there is a better language or approach I would rather start down that path now before I get too invested.
Do I need to pick another language to write a string search that will be lighting fast
I have the need to use this utility to search through 1000 of files for strings in web code, C# code, and another propitiatory language that uses text files. I also need to be able to use this utility to find strings in very large log files, MB size.
class Program
{
public static int linecounter;
public static int filecounter;
static void Main(string[] args)
{
//
//INIT
//
filecounter = 0;
linecounter = 0;
string word;
// Read properties from application settings.
string filelocation = Properties.Settings.Default.FavOne;
// Set Args from console.
word = args[0];
//
//Recursive search for sub folders and files
//
string startDIR;
string filename;
startDIR = Environment.CurrentDirectory;
//startDIR = "c:\\SearchStringTestDIR\\";
filename = args[1];
DirSearch(startDIR, word, filename);
Console.WriteLine(filecounter + " " + "Files found");
Console.WriteLine(linecounter + " " + "Lines found");
Console.ReadKey();
}
static void DirSearch(string dir, string word, string filename)
{
string fileline;
string ColorOne = Properties.Settings.Default.ColorOne;
string ColorTwo = Properties.Settings.Default.ColorTwo;
ConsoleColor valuecolorone = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorOne);
ConsoleColor valuecolortwo = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorTwo);
try
{
foreach (string f in Directory.GetFiles(dir, filename))
{
StreamReader file = new StreamReader(f);
bool t = true;
int counter = 1;
while ((fileline = file.ReadLine()) != null)
{
if (fileline.Contains(word))
{
if (t)
{
t = false;
filecounter++;
Console.ForegroundColor = valuecolorone;
Console.WriteLine(" ");
Console.WriteLine(f);
Console.ForegroundColor = valuecolortwo;
}
linecounter++;
Console.WriteLine(counter.ToString() + ". " + fileline);
}
counter++;
}
file.Close();
file = null;
}
foreach (string d in Directory.GetDirectories(dir))
{
//Console.WriteLine(d);
DirSearch(d,word,filename);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
If you want to speed up your code run a performance analysis and see what is taking the most time. I can almost guaruntee the longest step here will be
fileline.Contains(word)
This function is called on every line of the file, on every file. Naively searching for a word in a string can taken len(string) * len(word) comparisons.
You could code your own Contains method, that uses a faster string comparison algorithm. Google for "fast string exact matching". You could try using a regex and seeing if that gives you a performance enhancement. But I think the simplest optimization you can try is :
Don't read every line. Make a large string of all the content of the file.
StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8);
string text = streamReader.ReadToEnd();
Run contains on this.
If you need all the matches in a file, then you need to use something like Regex.Matches(string,string).
After you have used regex to get all the matches for a single file, you can iterate over this match collection (if there are any matches). For each match, you can recover the line of the original file by writing a function that reads forward and backward from the match object index attribute, to where you find the '\n' character. Then output that string between those two newlines, to get your line.
This will be much faster, I guarantee it.
If you want to go even further, some things I've noticed are :
Remove the try catch statement from outside the loop. Only use it exactly where you need it. I would not use it at all.
Also make sure your system is running, ngen. Most setups usually have this, but sometimes ngen is not running. You can see the process in process explorer. Ngen generates a native image of the C# managed bytecode so the code does not have to be interpreted each time, but can be run natively. This speeds up C# a lot.
EDIT
Other points:
Why is there a difference between first and subsequent run times? Seems like caching. The OS could have cached the requests for the directories, for the files, for running and loading programs. Usually one sees speedups after a first run. Ngen could also be playing a part here, too, in generating the native image after compilation on the first run, then storing that in the native image cache.
In general, I find C# performance too variable for my liking. If the optimizations suggested are not satisfactory and you want more consistent performance results, try another language -- one that is not 'managed'. C is probably the best for your needs.

Categories

Resources