Make a message box only pop up once in c# - c#

I have attached my code below. I am trying to get the message box to go away after one pop up until another action within the application triggers it.
using (VIModel vi = new VIModel())
{
var VideoFiles = vi.VI_VIDEO_FILES.Where(a => a.SEGMENT_ID == segmentId);
foreach (var vf in VideoFiles)
{
string location = vf.URL;
location = location.Replace('/', '\\');
string[] smain = location.Split('\\');
string unamemain = smain.Last().ToString();
string fileToCopySource = Path.Combine(inputDirectory, location);
string fileToCopyDestination = Path.Combine(outputDirectory, unamemain);
foreach (char c in fileToCopySource)
{
if (fileToCopySource.Contains(c))
{
// notify user that the inputDirectory isn't valid
MessageBox.Show("FOO");
}
}
if (!File.Exists(fileToCopySource))
{
// notify user that file doesn't exist
MessageBox.Show("FOO");
}
//File.Copy(inputDirectory + location, outputDirectory + unamemain, true);
File.Copy(fileToCopySource, fileToCopyDestination, true);
lbConsole.Items.Add("Moved " + location + " from: " + inputDirectory + " to " + fileToCopyDestination);
}
}

Your code is alerting multiple times -- once for every "alertable" condition it finds, i.e. input directory not valid. What you need to do is record the fact that anything caused the condition that will need to be alerted, and then alert only once, outside of the loop:
bool needAlert = false;
foreach (char c in fileToCopySource)
{
if (fileToCopySource.Contains(c))
{
needAlert = true;
break; // no more looping needed.
}
}
if(needAlert) MessageBox.Show("FOO"); // notify user that the inputDirectory isn't valid

Related

Cleaning up nested if statements to be more readable?

I'm writing a project, and the part I'm doing now is getting arrow shaped real fast. How can I remove the nested if statements, but still have the same behaviour?
The code below might not look so bad now, but I'm planning on refactoring to include more methods.
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//Checking if the Integration failed
if (reportResponse.Error == null)
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
else
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
}
}
}
As mentioned in the comment, the indentation level is fine for now, but its always better to minimize when possible, especially when you are repeating same blocks of code.
The best way to do this is to write a separate function that contains that block of code and then call that function instead of the nested if statements.
In your case it would be something like this:
private async void checkTotalDiff(diffReport) {
...
}
You could pass anything you might need in the parameters. This way in your main code, you could replace the if statements with checkTotalDiff(diffReport) and save the return (if any) to a variable.
Also note I used void for return but you could change the type depending on what the function returns.
I wouldn't consider this as having an excessive amount of nested if-statements. It is fine as is. Otherwise you could do the following (also suggested by #Caius Jard):
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
//Checking if the Integration failed
if (reportResponse.Error != null)
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
return;
}
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
}

Docusign Move Envelope using C# - How can I turn XML/JSON requests and "PUT" methods into working C# code?

First, my code:
string accountID = loginInfo.LoginAccounts[0].AccountId;
Console.WriteLine("Account ID:" + accountID);
FoldersApi foldApi = new FoldersApi();
var folders = foldApi.List(accountID);
//this is pointing to my "Sent" folder
string folderID = folders.Folders[1].FolderId;
var envID = foldApi.ListItems(accountID, folderID);
foreach (FolderItem fi in envID.FolderItems)
{
EnvelopesApi envApi = new EnvelopesApi();
EnvelopeDocumentsResult docsList = envApi.ListDocuments(accountID, fi.EnvelopeId);
Recipients listRecip = envApi.ListRecipients(accountID, fi.EnvelopeId);
string listOfInfo = "";
Envelope myEnv = envApi.GetEnvelope(accountID, fi.EnvelopeId);
if (myEnv.Status == "completed")
{
foreach (var signer in listRecip.Signers)
{
var listTabs = envApi.ListTabs(accountID, fi.EnvelopeId, signer.RecipientId);
foreach (var tab in listTabs.TextTabs)
{
//listOfInfo is for each specific document, just to view results
listOfInfo += tab.TabLabel + " - " + tab.Value + " \n ";
//bigString is an aggregation of all documents tab values
bigString += tab.TabLabel + " - " + tab.Value + " \n ";
}
Console.WriteLine("Stop here");//breakpoint
}
//Move code should go here.
}
}
Currently my code enters into my account, gets a list of all the folders, and I then point towards my "Sent" folder. After that, I look at all of the documents in the sent folder, check if their status is "completed", and when it is, go "into" that document and strip out all of the information living in the texttabs I've placed on a document.
Onto my question!
Where the comment "//Move code should go here." after I have stripped out my needed information, I would like to move an envelope from my "Sent" folder (Folders[1]) and place it into my "Loaded" folder (Folders[3]).
I have reviewed : https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST%20API%20References/Move%20Envelope.htm
but I am unable to make sense of how to turn XML/JSON requests and "PUT" methods into working C# code.
Any assistance would be greatly appreciated.
Thanks,
-Kyle.
Updated Code.
Console.WriteLine("Account ID:" + accountID);
FoldersApi foldApi = new FoldersApi();
//create fr object
FoldersRequest fr = new FoldersRequest();
//instantiate EnvelopeIds string list, to a new string list..
fr.EnvelopeIds = new List<string>();
//get folders
var folders = foldApi.List(accountID);
string sentFolderID = "";
string loadedFolderID = "";
foreach (var fold in folders.Folders)
{//get sent/loaded folder IDs
if (fold.Name == "Sent Items") { sentFolderID = fold.FolderId; }
else if(fold.Name == "Loaded") { loadedFolderID = fold.FolderId; }
}
//list the items in the folder
var envID = foldApi.ListItems(accountID, sentFolderID);
//for each item in the folder...
foreach (FolderItem fi in envID.FolderItems)
{
EnvelopesApi envApi = new EnvelopesApi();
//get a list of documents in the envelope
EnvelopeDocumentsResult docsList = envApi.ListDocuments(accountID, fi.EnvelopeId);
//list recipients
Recipients listRecip = envApi.ListRecipients(accountID, fi.EnvelopeId);
string listOfInfo = "";
Envelope myEnv = envApi.GetEnvelope(accountID, fi.EnvelopeId);
if (myEnv.Status == "completed")
{
foreach (var signer in listRecip.Signers)
{
var listTabs = envApi.ListTabs(accountID, fi.EnvelopeId, signer.RecipientId);
foreach (var tab in listTabs.TextTabs)
{
//get info out of document
listOfInfo += tab.TabLabel + " - " + tab.Value + " \n ";
bigString += tab.TabLabel + " - " + tab.Value + " \n ";
}
Console.WriteLine("Stop here");//breakpoint
}
//add this envelope ID to the list of envelopes to be moved
fr.EnvelopeIds.Add(myEnv.EnvelopeId);
}
}
//move all the envelopes in the list
if (fr.EnvelopeIds.Count >= 1) { foldApi.MoveEnvelopes(accountID, loadedFolderID, fr); }
I found a solution.

need to check all items in string array with if condition

i have got the below code to check whether the login user access to menu item
but if first item fails the if condition it is redirecting to error page, but i need to check second item from that string array with if condition even the first item fails the if condition ...
please find the below given code for test..
var count = 0;
string[] strPageId = PageId.Split(';');
foreach (string menuPageId in strPageId)
{
if (objDALookup.IsPageVisible(PageType,Int32.Parse(menuPageId), role, AcctId) == false)
{
Session["ErrorInfo"] = "Access denied, please contact system administrator.";
new Lib.Utils.Log().logInfo("FORCE_ACCESS", strUser + " tried to access PageId:" + PageId + " PageType:" + PageType);
Response.Redirect(ConfigurationManager.AppSettings["ACCESS_DENIED_URL"], true);
}
else
{
count++;
if (count == strPageId.Length) break;
}
}
You can make condition something like this by figuring out condition in loop and executing the action outside loop once it is decided.
bool access = false;
foreach (string menuPageId in strPageId)
{
if (objDALookup.IsPageVisible(PageType,Int32.Parse(menuPageId), role, AcctId) == true)
{
access = true;
break;
}
}
if(!access)
{
Session["ErrorInfo"] = "Access denied, please contact system administrator.";
new Lib.Utils.Log().logInfo("FORCE_ACCESS", strUser + " tried to access PageId:" + PageId + " PageType:" + PageType);
Response.Redirect(ConfigurationManager.AppSettings["ACCESS_DENIED_URL"], true);
}
OR
You can use linq
bool access = strPageId.Any(s=> objDALookup.IsPageVisible(PageType,Int32.Parse(menuPageId), role, AcctId) == true);
if(!access)
{
}

C# Pause during foreach loop until Process.Exited

So I have a foreach loop that goes through a DataGridView. For each row in the grid it executes a pspasswrd.exe and changes the password of a local account. How can I pause the foreach loop until the process completes before moving onto the next computer in the list?
I am not sure, I tried WaitForExit but this is not reliable since it is synchronous so it cause my program to not respond if it takes a long time. I need to utilize Process.Exited but unsure how to do this correctly.
Here is my foreach loop. Which also checks if the password was changed successfully. And inputs data into another Datagridview if it was success.
foreach (DataGridViewRow row in dgvData.Rows)
{
if (!row.IsNewRow && row.Cells["cIPAddress"].Value.ToString().Contains("Invalid") == false)
{
if (pspasswrd(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword).Contains("Password successfully changed"))
{
dgvResults.Rows.Add(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword);
AppendNumber = AppendNumber + IncreaseNumber;
NewPassword = BasePassword + AppendNumber;
}
else
row.DefaultCellStyle.BackColor = Color.Red;
}
Thread.Sleep(1000);
}
But what I am unsure is that if I change my code below to use process.exited. How will it associate the password change to the computer it was successfully on. As it will be asynchronous.
public string pspasswrd(string ip, string user, string password)
{
String CD = #Directory.GetCurrentDirectory() + "\\pspasswrd.exe";
ProcessStartInfo p = new ProcessStartInfo();
string result = null;
p.FileName = CD;
p.Arguments = #"\\" + ip + " " + user + " " + password + " -accepteula";
p.CreateNoWindow = true;
p.RedirectStandardOutput = true;
p.RedirectStandardError = true;
p.UseShellExecute = false;
Process x = Process.Start(p);
StreamReader stream = x.StandardOutput;
result = stream.ReadToEnd();
x.WaitForExit(2000);
x.Close();
return result;
}
You should first collect all the needed information from DataGridView in a collection then run your code for executing pspasswrd.exe in a background thread looping on the collection instead of DataGridView and use WaitForExit, this will not block your UI thread.
EDIT
Here is the code with WaitForExit and a new thread. I believe that you will not gain much using the Exit event instead of WaitForExit other then much more complexity and deadlock scenarios:
private void OnSomeUIEvent()
{
//In UI thread
var ipRows = new Dictionary<string, DataGridViewRow>();
var targetUser = ""; //tbTargetUser.Text
var pwd = ""; //NewPassword
var basePassword = ""; //Some value
foreach (DataGridViewRow row in dgvData.Rows)
{
var ipAddress = row.Cells["cIPAddress"].Value.ToString();
if (!row.IsNewRow && ipAddress.Contains("Invalid") == false)
{
ipRows.Add(ipAddress, row);
}
}
Task.Factory.StartNew(() => {
ChangePassword(ipRows, targetUser, pwd, basePassword);
}).ContinueWith(t => {
//Do Something when task completed
});
}
private void ChangePassword(Dictionary<string, DataGridViewRow> ipRows, string targetUser, string newPwd, string basePwd)
{ //in background thread
foreach (var ipRow in ipRows)
{
var pwd = newPwd;
var basePassword = basePwd;
var appendNumber = 0;
var increaseNumber = 1; //some number
if (pspasswrd(ipRow.Key, targetUser, pwd).Contains("Password successfully changed"))
{
dgvResults.Invoke((MethodInvoker)(() =>
{
dgvResults.Rows.Add(ipRow.Key, targetUser, pwd);
}));
appendNumber = appendNumber + increaseNumber;
pwd = basePassword + increaseNumber;
}
else
{
dgvData.Invoke((MethodInvoker)(() =>
{
ipRow.Value.DefaultCellStyle.BackColor = Color.Red;
}));
}
}
}

Unauthoriezed Access Exception

i have a cloud database server like application on my computer that i'm hosting my game on. However, every time an user tries to save data i get an UnauthorizedAccessException.
Im running it by admin and i dont have any specias right in my folder so i have no idea what's the problem.
Here's my code:
public const string root = "D:/DATABASE/";
public static void WriteData(string playername, string type, string data)
{
if (!Directory.Exists("D:/DATABASE/" + playername))
{
Directory.CreateDirectory("D:/DATABASE/" + playername);
Directory.CreateDirectory("D:/DATABASE/" + playername + "/weapons");
}
if (type != "Weapon")
{
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/" + type + ".sav"))
{
sw.WriteLine(data);
}
}
else
{
string[] dat = data.Split('%');
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/weapons/" + dat[0] + ".gfa"))
{
string[] lines = dat[1].Split('#');
foreach (string cline in lines)
{
sw.WriteLine(cline);
}
}
}
}
public static string ReadLoadout(string playername)
{
string output = "";
string[] items = new string[2];
using (StreamReader sr = new StreamReader(root + playername + "/loadout.gfl"))
{
items[0] = sr.ReadLine();
items[1] = sr.ReadLine();
}
int c = 0;
foreach (string citem in items)
{
if (c > 0) output += "$";
output += citem + "%" + GetCompressedWeaponFile(playername, citem);
c++;
}
return output;
}
public static string GetCompressedWeaponFile(string playerName, string weaponName)
{
string output = "";
using (StreamReader sr = new StreamReader(root + playerName + "/weapons/" + weaponName))
{
string line = " ";
int c = 0;
while (line != null)
{
line = sr.ReadLine();
if (line != null)
{
if (c > 0) output += "#";
output += line;
}
c++;
}
}
return output;
}
public static void RegisterNewUser(string username, string password, string email)
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
public static void EditLoadout(string username, string items)
{
File.WriteAllLines(root + username + "/loadout.gfl",items.Split('#'));
}
It is difficult to provide specific help without more information. Here are a few of troubleshooting suggestions:
1) Try running your code on a different machine. Specifically your development computer. Do you still have the same error? If not, then there is indeed a permission problem.
2) Have you tried checking the stack trace of the exception?
When you run the application on your own computer, try using the IDE to display the exception. Yes, the problem may ultimately be in a low-level class, but you should be able to break on the error and go back in the call stack to see which method in your code is actually throwing the error.
3) Check the actual exception, even for a system-level exception.
Chances are, if you are able to debug this in the IDE, that you will see property information that will give you a hint. Is it in a directory method or a file write method? Check additional properties. Somewhere it might give you the text of the path (assuming it's a file issue) that it failed on that that could help narrow things down too.
4) Add Exception handling to your code
This is a good rule of thumb, and you should really do this anyway to make a stronger program. Regardless of who's method you are calling (yours, someone else's, or a system method) you need to determine where it should be handled.
For example, in your code, in the RegisterNewUser() method, consider something like:
public static void RegisterNewUser(string username, string password, string email)
{
try
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
catch (Exception ex)
{
// Create a method to display or log the exception, with it's own error handler
LogAndDisplayExceptions(ex);
// Send the user a message that we failed to add them. Put this in it's own try-catch block
// ideally, for readability, in it's own method.
try
{
Email.Send(email, "Failed to register", "An error occurred while trying to add your account.");
}
catch (Exception exNested)
{
LogAndDisplayExceptions(exNested);
}
}
}
5) Add a "crash-and-burn" exception handler to "main"
In the method that is your "top method" (it's hard to tell in the snippet you provided since there are few methods that would attempt to write to the disk) you could wrap your code in a try - catch block and print the exception or write it to disk.
If you have having trouble writing the exception to disk, I would suggest creating an error file first, make sure that the user account that is running the program can write to it, and then in the catch block open the file for APPEND. This should make it easier to get to the error text.
6) When all else fails, use the Debug class or Console class to write the traditional "I made it to line x."
While this will not solve your problem, it should help you get more information that will provide more insight into where your code is causing an error.

Categories

Resources