EDIT 8/8/2012: I've made some significant changes to the code I'm using and would like some fresh help on one last problem I'm having. I'm going to rewrite most of this question.
I have a small program which iterates recursively through each file and folder under a target directory checking the names for specific characters. It works just fine but I'm looking for help on how to make a specific method work faster.
Here's the code I'm currently using. This is just a couple of lines from the method that kicks everything off:
if(getFullList(initialPathTB.Text))
SearchFolder();
And these are the two methods you need to see:
private void SearchFolder()
{
int newRow;
int numItems = 0;
numItems = itemsMaster.Length;
for (int x = 0; x < numItems; x++)
{
if (hasIllegalChars(itemsMaster[x]) == true)
{
newRow = dataGridView1.Rows.Add();
dataGridView1.Rows[newRow].Cells[0].Value = itemsMaster[x];
filesFound++;
}
}
}
private bool getFullList(string folderPath)
{
try
{
if (checkBox17.Checked)
itemsMaster = Directory.GetFileSystemEntries(folderPath, "*", SearchOption.AllDirectories);
else
itemsMaster = Directory.GetFileSystemEntries(folderPath, "*", SearchOption.TopDirectoryOnly);
return true;
}
catch (UnauthorizedAccessException e)
{
if(folderPath[folderPath.Length - 1] != '\\')
folderPath += #"\";
if (e.Message == "Access to the path '" + folderPath + "' is denied.")
{
MessageBox.Show("You do not have read permission for the following directory:\n\n\t" + folderPath + "\n\nPlease select another folder or log in as a user with read access to this folder.", "Access Denied", MessageBoxButtons.OK, MessageBoxIcon.Error);
folderPath = folderPath.Substring(0, folderPath.Length - 1);
}
else
{
if (accessDenied == null)
accessDenied = new StringBuilder("");
accessDenied.AppendLine(e.Message.Substring(20, e.Message.Length - 32));
}
return false;
}
}
initialPathTB.Text is populated with something like "F:\COMMON\Administration".
Here's my problem. When the top level that's passed to folderPath is one which the user does not have read access everything works fine. When the top level and all subordinate directories are folders which the user has read access everything works fine again. The issue lies with directories where the user has read access to the top level but does not for some child folder deeper within. This is why getFullList() is a bool; if there are any UnauthorizedAccessExceptions then itemsMaster remains empty and SearchFolder() fails on numItems = itemsMaster.Length;.
What I'd like is to populate itemsMaster with every item within folderPath and simply skip the items for which the user doesn't have read access but I don't know how to do that without recursively crawling and checking each directory.
This code works so much faster than my old method so I'd rather not abandon it for something else entirely. Is there any way to make the Directory.GetFileSystemEntries() method do what I want?
Directory.GetFileSystemEntries(folderPath, "*", SearchOption.AllDirectories).Length
or another option (with this option, keep in mind the first 3-5 elements in fullstring will be garbage text from the output which you should remove):
Process process = new Process();
List<string> fullstring = new List<string>();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.UseShellExecute = false;
process.OutputDataReceived += (sender, args2) => fullstring.Add(args2.Data);
process.Start();
process.StandardInput.WriteLine(#"dir /b /s c:\temp | find """" /v");
process.BeginOutputReadLine();
process.WaitForExit(10000); //or whatever is appropriate time
process.Close();
If you want to track down errors better, make these changes:
Declare List<string> fullstring = new List<string>(); globally, then change the event handler of OutputDataReceived like below:
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
}
static void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
try
{
fullstring.Add(e.Data);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
//log exception
}
}
You write that "I'd like the progress bar to actually indicate how far through the list of items the program is, so therefore I need a number of items to set the ProgressBar.Maximum property to."
This is kind of a specific desire, and I'm not sure its worthwhile in the given case. If your ProgressBar is (say) 800 px wide, 1 percentage point would be 0.125px wide. For a list "over a hundred thousand items" -- let's make that a minimum of 100,000 -- you have to process 8,000 items to move the bar to move a single pixel. How much time does it take for your program to process 8,000 items? That will help you understand what kind of actual feedback you're giving the user. If it takes too long, it might look like things have hung, even if it's working.
If you're looking to give good user feedback, I'd suggest setting your ProgressBar's style to Marquee and providing a "Now checking file #x" textual indicator.
Related
I am attempting to get the metadata from a few music files and failing miserably. Online, there seems to be absolutely NO HOPE in finding an answer; no matter what I google. I thought it would be a great time to come and ask here because of this.
The specific error I got was: Error HRESULT E_FAIL has been returned from a call to a COM component. I really wish I could elaborate on this issue, but I'm simply getting nothing back from the COMException object. The error code was -2147467259, and it in hex is -0x7FFFBFFB, and Microsoft have not documented this specific error.
I 70% sure that its not the file's fault. My code will run through a directory full of music and convert the file into a song, hence the ConvertFileToSong name. The function would not be running if the file were to not exist is what I'm trying to say.
The only thing I can really say is that I'm using Dotnet 6, and have a massive headache.
Well, I guess I could also share another problem I had before this error showed up. Dotnet6 has top level code or whatever its called, this means that I can't add the [STAThread] attribute. To solve this, I simply added the code bellow to the top. Not sure why I have to set it to unknown, but that's what I (someone else on Stack Overflow) have to do. That solved that previous problem that the Shell32 could not start, but could that be causing my current problem? Who knows... definitely not me.
Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
Here is the code:
// Help from: https://stackoverflow.com/questions/37869388/how-to-read-extended-file-properties-file-metadata
public static Song ConvertFileToSong(FileInfo file)
{
Song song = new Song();
List<string> headers = new List<string>();
// initialise the windows shell to parse attributes from
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder = null;
try
{
objFolder = shell.NameSpace(file.FullName);
}
catch (COMException e)
{
int code = e.ErrorCode;
string hex = code.ToString();
Console.WriteLine("MESSAGE: " + e.Message + ", CODE: " + hex);
return null;
}
Shell32.FolderItem folderItem = objFolder.ParseName(file.Name);
// the rest of the code is not important, but I'll leave it there anyway
// pretty much loop infinetly with a counter better than
// while loop because we don't have to declare an int on a new
// line
for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(null, i);
// the header does not exist, so we must exit
if (String.IsNullOrEmpty(header)) break;
headers.Add(header);
}
// Once the code works, I'll try and get this to work
song.Title = objFolder.GetDetailsOf(folderItem, 0);
return song;
}
Good night,
Diseased Finger
Ok, so the solution isn't that hard. I used file.FullName which includes the file's name, but Shell32.NameSpace ONLY requires the directory name (discluding the file name).
This is the code that fixed it:
public static Song ConvertFileToSong(FileInfo file)
{
// .....
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder = file.DirectoryName;
Shell32.FolderItem folderItem = objFolder.ParseName(file.Name);
// .....
return something;
}
I'm currently working on a dll library project.
if (!Directory.Exists(MenGinPath))
{
Directory.CreateDirectory(MenGinPath + #"TimedMessages");
File.WriteAllLines(MenGinPath + #"TimedMessages\timedmessages.txt", new string[] { "Seperate each message with a new line" });
}
else if (!File.Exists(MenGinPath + #"TimedMessages\timedmessages.txt"))
{
Directory.CreateDirectory(MenGinPath + #"TimedMessages");
File.WriteAllLines(MenGinPath + #"TimedMessages\timedmessages.txt", new string[] { "Seperate each message with a new line" });
}
As you can see if the statement Directory.Exists is false a specific directory (MenGinPath) will be created. However, if the same path, with another file in addition is false, the second functions will be called.
My question is the following: is there any way to make this shorter?
Because as you can see I'm calling 2 times the same functions:
Directory.CreateDirectory(MenGinPath + #TimedMessages\timedmessages.txt
and
File.WriteAllLines(MenGinPath + #"\TimedMessages\timedmessages.txt"))
Any help would be welcome!!
You don't need to check if directory exists because Directory.CreateDirectory automatically creates the directory if it does not exists and does nothing if the directory already exists.
Also, do not include the filename when creating the directory. Yes, it wont error but just for clarity sake.
Another one is to use Path.Combine instead of hardcoding the path. This will improve readability of your code.
So, here's what I can come up with:
string dir = Path.Combine(MenGinPath, #"Groups\TimesMessages");
string file = Path.Combine(dir, "timedmessages.txt");
// this automatically creates all directories in specified path
// unless it already exists
Directory.CreateDirectory(dir);
//of course, you still need to check if the file exists
if (!File.Exists(file) {
File.WriteAllLines(filePath, new string[] { "Seperate each message with a new line" });
}
/* or if file exists, do your stuff (optional)
* else {
* //do something else? maybe edit the file?
* }
*/
You can make your code shorter given the fact that CreateDirectory does nothing when the directory exists. Moreover do not pullute your code with all that string concatenations to create the path and the file names.
Just do it one time before entering the logic using the appropriate method to create filenames and pathnames (Path.Combine).
string messagePath = Path.Combine(MenGinPath, "TimedMessages");
string fileName = Path.Combine(messagePath, "timedmessages.txt");
// call the create even if it exists. The CreateDirectory checks the fact
// by itself and thus, if you add your own check, you are checking two times.
Directory.CreateDirectory(messagePath);
if (!File.Exists(fileName)
File.WriteAllLines(fileName, new string[] { "Seperate each message with a new line" });
Would something like this work?
string strAppended = string.Empty;
if (!Directory.Exists(MenGinPath))
{
strAppended = MenGinPath + #"Groups\timedmessages.txt";
}
else if (!File.Exists(MenGinPath + #"TimedMessages\timedmessages.txt"))
{
strAppended = MenGinPath + #"TimedMessages\TimedMessages.txt";
}
else
{
return;
}
Directory.CreateDirectory(strAppended);
File.WriteAllLines(strAppended, new string[] { "Seperate each message with a new line" });
I have found that it is a great idea to reuse blocks of code like this instead of hiding them in if statements because it makes code maintenance and debugging easier and less prone to missed bugs.
It seems the only difference between the 2 cases is the path. So just get only this path in your if-else
const string GroupsPath = #"Groups\timedmessages.txt";
const string TimedMessagesTxt = #"TimedMessages\TimedMessages.txt";
string addPath = null;
if (!Directory.Exists(MenGinPath)) {
addPath = GroupsPath;
} else if (!File.Exists(Path.Combine(MenGinPath, TimedMessagesTxt))) {
addPath = TimedMessagesTxt;
}
If (addPath != null) {
Directory.CreateDirectory(Path.Combine(MenGinPath, addPath));
File.WriteAllLines(Path.Combine(MenGinPath, TimedMessagesTxt),
new string[] { "Seperate each message with a new line" });
}
Note: Using Path.Combine instead of string concatenation has the advantage that missig or extra \ are added or removed automatically.
I have the following code:
private void Form2_Load(object sender, EventArgs e)
{
string[] files = Directory.GetFiles(Form1.programdir + "\\card_images", "*", SearchOption.TopDirectoryOnly);
MessageBox.Show(files.ElementAt(1).ToString());
PictureBox[] cards = new PictureBox[files.Count()];
for (int i = 0; i < files.Count(); i++)
{
MessageBox.Show(i.ToString());
cards[i] = new PictureBox();
cards[i].BackgroundImage = new Bitmap(Form1.programdir + "\\card_images\\" + files[i]);
MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);
cards[i].Padding = new Padding(0);
cards[i].BackgroundImageLayout = ImageLayout.Stretch;
cards[i].MouseDown += new MouseEventHandler(card_click);
cards[i].Size = new Size((int)(this.ClientSize.Width / 2) - 15, images.Height);
images.Controls.Add(cards[i]);
}
}
Note: "images" is a FlowLayoutPanel in my program's graphic designer. I use it to easily keep track of the images.
I'm trying to get it to display images of a few poker cards, from the directory. The directory is correct, the folder is there, and previous uses of the folder have worked; Form1 is the first form of the program, and "programdir" is:
public static string programdir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Messageboxes seem to display the correct diagnostic information (folder location, card file names, even files.Count() seems to be correct), but I can't get any files displayed in pictureboxes. Any advice?
EDIT: Apparently, the line
MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);
Does not run, ever, at all, even though
MessageBox.Show(files.ElementAt(1).ToString());
Does run. As well,
MessageBox.Show(i.ToString());
Only runs once, outputting "0" in a messagebox (since "i" is set to 0 initially), even though it should run 4 times, since the size of the array "files" is 4.
EDIT 2: The new code, which runs flawlessly, is:
private void Form2_Load(object sender, EventArgs e)
{
Uri baseUri = new Uri(Form1.programdir + "\\card_images\\");
string[] files = Directory.GetFiles(Form1.programdir + "\\card_images", "*", SearchOption.TopDirectoryOnly);
MessageBox.Show(files.Count().ToString());
PictureBox[] cards = new PictureBox[files.Count()];
for (int i = 0; i < files.Count(); i++)
{
Bitmap bmp = null;
Uri completeUri = new Uri(baseUri, files[i]);
try
{
bmp = new Bitmap(completeUri.LocalPath);
}
catch (Exception exc)
{
// remove this if you don't want to see the exception message
MessageBox.Show(exc.Message);
continue;
}
MessageBox.Show(i.ToString());
cards[i] = new PictureBox();
cards[i].BackgroundImage = bmp;
MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);
cards[i].Padding = new Padding(0);
cards[i].BackgroundImageLayout = ImageLayout.Stretch;
cards[i].MouseDown += new MouseEventHandler(card_click);
cards[i].Size = new Size((int)(this.ClientSize.Width / 2) - 15, images.Height);
cards[i].Visible = true;
images.Controls.Add(cards[i]);
}
}
The try/catch block isn't mandatory because it doesn't catch any errors anymore, but I'm leading it just in case something else happens some time down the road. This code will grab all images from the folder (with the assumption that only image files are in the folder, which is a separate issue), display them, and bake you a cake all at once.
So the problem appears to be that the path you are attempting to load from is invalid, because of some assumptions about the output of Directory.GetFiles(), combined with the fact that the exception you would normally expect to see is being silently dropped.
With that in mind, here's my take on a rewrite:
private void Form2_Load(object sender, EventArgs e)
{
string[] files = Directory.GetFiles(Form1.programdir + "\\card_images", "*", SearchOption.TopDirectoryOnly);
foreach (var filename in files)
{
Bitmap bmp = null;
try
{
bmp = new Bitmap(filename);
}
catch (Exception e)
{
// remove this if you don't want to see the exception message
MessageBox.Show(e.Message);
continue;
}
var card = new PictureBox();
card.BackgroundImage = bmp;
card.Padding = new Padding(0);
card.BackgroundImageLayout = ImageLayout.Stretch;
card.MouseDown += new MouseEventHandler(card_click);
card.Size = new Size((int)(this.ClientSize.Width / 2) - 15, images.Height);
images.Controls.Add(card);
}
}
I skipped creating an array since you're not keeping it anyway, and took out your diagnostic MessageBox calls. This code should load any files it finds, ignoring any that it failed to load for whatever reason, and create a PictureBox for each one that loads successfully.
Incidentally, one of the possible reasons for failure is if there are any files in the card_images folder that can't be handled by the Bitmap class. It's good, but it won't render an image from a document file or a DLL :P
Final thought: breakpoints and single-step debugging will definitely help you find the issues much faster. Visual Studio Express is sufficient for the task if you don't have anything else.
Update: Dealing with long path names
Long story short, long filenames are a pain in the rear end.
And the long story....
After a bit of checking it seems that the .NET framework by design (see this series of articles from 2007) will not handle long path names. The \\?\ prefix is rejected by all .NET classes, and UNC paths in the form //localhost/C$/........... are also rejected if they exceed MAX_PATH characters in length.
There are only a few things you can do about this:
The solution suggested by the .NET designers is to get rid of the long paths by relocating the files to a shorter path. (In other words, don't even try to use long paths.)
Create new versions of the System.IO classes with long path support. (Not for the faint of heart.)
A variety of hacks abound, including using the DefineDosDevice API (the core of the old subst dos command) to map an available drive letter to some subset of the path that fits inside the MAX_PATH limit. (Fun, but hacky.)
Use the GetShortPathName API function to turn a long path into an abbreviated version of itself using the 8.3 abbreviations created in the filesystem.
I'll focus on that last option.
public static class NativeMethods
{
const int MAX_PATH = 260;
// Force unicode version to get long-path support
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern uint GetShortPathNameW(
[MarshalAs(UnmanagedType.LPTStr)]
string lpszLongPath,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder lpszShortPath,
uint cchBuffer
);
public static string ShortenPath(string longPath)
{
// check if path is already short enough
if (string.IsNullOrWhiteSpace(longPath) || longPath.Length <= MAX_PATH)
return longPath;
// Get short version of path
StringBuilder shortNameBuffer = new StringBuilder(MAX_PATH);
uint result = GetShortPathNameW(#"\\?\" + longPath, shortNameBuffer, (uint)MAX_PATH);
// result is length of returned path. Must be >4 bytes to be valid
if (result <= 4)
return null;
// Get result, removing "\\?\" prefix
var res = shortNameBuffer.ToString().Substring(4);
return res;
}
}
Call NativeMethods.ShortenPath with a valid path of any length and it will try to shorten it for you if necessary. Will fail on long paths if the file couldn't be found, and might return invalid results if the resultant shortened filename is greater than MAX_PATH characters in length... which means you have 27+ directories with long names in the path, which is pretty silly anyway :P
And of course now that you've posted your workaround... it turns out that the path isn't actually too long. sigh If you ever hit the path limit, this will still help.
Okay so I've been looking around and I can't find an answer anywhere.
What I want my program to do is every time I run it, the name that shows up in the task manager is randomized.
There is a program called 'Liberation' that when you run it, it will change the process name to some random characters like AeB4B3wf52.tmp or something. I'm not sure what it is coded in though, so that might be the issue.
Is this possible in C#?
Edit:
I made a sloppy work around, I created a separate program that will check if there is a file named 'pb.dat', it will copy it to the temp folder, rename it to a 'randomchars.tmp' and run it.
Code if anyone was interested:
private void Form1_Load(object sender, EventArgs e)
{
try
{
if (!Directory.Exists(Environment.CurrentDirectory + #"\temp")) // Create a temp directory.
Directory.CreateDirectory(Environment.CurrentDirectory + #"\temp");
DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory + #"\temp");
foreach (FileInfo f in di.GetFiles()) // Cleaning old .tmp files
{
if (f.Name.EndsWith(".tmp"))
f.Delete();
}
string charList = "abcdefghijklmnopqrstuvwxyz1234567890";
char[] trueList = charList.ToCharArray();
string newProcName = "";
for (int i = 0; i < 8; i++) // Build the random name
newProcName += trueList[r.Next(0, charList.Length)];
newProcName += ".tmp";
if (File.Exists(Environment.CurrentDirectory + #"\pb.dat")) // Just renaming and running.
{
File.Copy(Environment.CurrentDirectory + #"\pb.dat", Environment.CurrentDirectory + #"\temp\" + newProcName);
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = Environment.CurrentDirectory + #"\temp\" + newProcName;
p.UseShellExecute = false;
Process.Start(p);
}
}
catch (Exception ex)
{
MessageBox.Show("I caught an exception! This is a bad thing...\n\n" + ex.ToString(), "Exception caught!");
}
Environment.Exit(-1); // Close this program anyway.
}
The process name in the task manager bases on the executable name without the extension, which you can not change while it is running.
Read the documentation:
The ProcessName property holds an executable file name, such as
Outlook, that does not include the .exe extension or the path. It is
helpful for getting and manipulating all the processes that are
associated with the same executable file.
in visual studio go to Project - Properties - Application - Assembly information and change Title
I would implement a host application to do this that simply runs and monitors a sub process (other executable). You may rename a file as such:
System.IO.File.Move("oldfilename", "newfilename");
and start the process like this:
Process.Start("newfilename");
This would mean that instead of one process you would have two, but the owner process only needs to be alive under startup - in order to change the name.
Brief Summary
I am creating a lightweight IDE for NASM development in C# (I know kind of an irony). Kinda of like Notepad++ but simpler but with features that make it more than source editor. Since Notepad++ is really just a fancy source editor. I have already implemented features like Project creation (using a project format similar to how Visual Studio organizes projects). Project extension .nasmproj. I am also in the works of hosting it in an open-source place (Codeplex). Although the program is far from finish, and definitely cannot be used in a production environment without proper protection and equipment. In addition, I am working alone with it at this moment, more like a spare time project since I just finished my last Summer final taking Calculus I.
Problem
Right now I am facing a problem, I can build the project but no output from NASM is being fed into the IDE. I have succesfully built a project, and I was able to produce object files. I even tried producing a syntax error to see if I finally see something come up but none and I check the bin folder of the test project I created and I see no object file creating. So definitely NASM is doing its magic. Is it because NASM doesn't want me to see its output. Is there a solution? Any advice would be great. Here is the code which I think is giving Trouble.
Things to Note
I have already checked if events have been invoked. An yes they have but they return empty strings
I have also checked error data and same effect.
Code
public static bool Build(string arguments, out Process nasmP)
{
try
{
ProcessStartInfo nasm = new ProcessStartInfo("nasm", arguments);
nasm.CreateNoWindow = true;
nasm.RedirectStandardError = true;
nasm.RedirectStandardInput = true;
nasm.RedirectStandardOutput = true;
nasm.UseShellExecute = false;
nasmP = new Process();
nasmP.EnableRaisingEvents = true;
nasmP.StartInfo = nasm;
bool predicate = nasmP.Start();
nasmP.BeginOutputReadLine();
return true;
}
catch
{
nasmP = null;
return false;
}
}
//Hasn't been tested nor used
public static bool Clean(string binPath)
{
if (binPath == null || !Directory.Exists(binPath))
{
throw new ArgumentException("Either path is null or it does not exist!");
}
else
{
try
{
DirectoryInfo binInfo = new DirectoryInfo(binPath);
FileInfo[] filesInfo = binInfo.GetFiles();
for (int index = 0; index < filesInfo.Length; index++)
{
try
{
filesInfo[index].Delete();
filesInfo[index] = null;
}
catch
{
break;
}
}
GC.Collect();
return true;
}
catch
{
return false;
}
}
}
}
using (BuildDialog dlg = new BuildDialog(currentSolution))
{
DialogResult result = dlg.ShowDialog();
dlg.onOutputRecieved += new BuildDialog.OnOutputRecievedHandler(delegate(Process _sender, string output)
{
if (result == System.Windows.Forms.DialogResult.OK)
{
outputWindow.Invoke(new InvokeDelegate(delegate(string o)
{
Console.WriteLine("Data:" + o);
outputWindow.Text = o;
}), output);
}
});
}
Edits
I have tried doing synchronously instead of asynchronously but still the same result (and empty string "" is returned) actually by debugging the stream is already at the end. So looks like nothing has been written into the stream.
This is what I tried:
string readToEnd = nasmP.StandardOutput.ReadToEnd();
nasmP.WaitForExit();
Console.WriteLine(readToEnd);
And another interesting thing I have tried was I copied the arguments from the debugger and pasted it in the command line shell and I can see NASM compiling and giving the error that I wanted to see all along. So definitely not a NASM problem. Could it be a problem with my code or the .Net framework.
Here is a nice snapshot of the shell window (although not technically proof; this is what the output should look like in my IDE):
Alan made a very good point, check the sub processes or threads. Is sub process and thread synonymous? But here is the problem. Almost all the properties except a select few and output/error streams are throwing an invalid operation. Here is the debugger information as an image (I wish Visual Studio would allow you to copy the entire information in click):
Okay I finally was able to do it. I just found this control that redirect output from a process and I just looked at the source code of it and got what I needed to do. Here is the the modified code:
public static bool Build(string command, out StringBuilder buildOutput)
{
try
{
buildOutput = new StringBuilder();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe");
startInfo.Arguments = "/C " + " nasm " + command;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process p = Process.Start(startInfo);
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
if (output.Length != 0)
buildOutput.Append(output);
else if (error.Length != 0)
buildOutput.Append(error);
else
buildOutput.Append("\n");
return true;
}
catch
{
buildOutput = null;
return false;
}
}
Here is how the output is formatted like:
I also wanted to thank Alan for helping me debug my code, although he didn't physically had my code. But he really was helpful and I thank him for it.