c# check->create->check folder loop - c#

I want ask an easy question about my code in c# .... I know that there are lot of topics with same or similar topic/code result. But I need to hand in my code to school, so I can't just use the best solution on Stackoverflow or another page. I showed my code to my teacher and now need to fix a little bug.
The Code is about backing up files with a console report, so in first step I check if a folder exists. Second step is to report that the folder exists or doesn't exist, if it doesn't the code creates this folder and rechecks ...
SITUATION : CONSOLE REPORT
folders doesnt exist:
02:02:06 directory for backup Exist ... can continue
02:02:05 directory for backup DOESNT EXIST ... creating required folders...
folders exist :
02:02:55 directory for backup Exist ... can continue
02:02:54 directory for backup Exist ... can continue
In the 1st example the report is OK, but in the 2nd, my code tells me the same information twice... i just can't get my code to work properly..
Here is my code:
public void checkbackupfolders() {
do {
create_backup_folders();
} while (create_backup_folders() == false);
}
public bool create_backup_folders()
{
string path = "\\BACKUP\\" + Globals.hostname;
if (Directory.Exists(path))
{
consolecho("directory for backup Exist ... can continue");
return true;
}
else
{
consolecho("directory for backup DOESNT EXIST ... creating required folders...");
Directory.CreateDirectory("\\BACKUP\\" + Globals.hostname);
return false;
}
}

Why are you calling the method twice here?:
do {
create_backup_folders();
} while (create_backup_folders() == false);
That's going to make things confusing, as you're now discovering. Just call the method once on each loop iteration and store the result of the method. Then use that stored result in the loop condition:
var canContinue = false;
do {
canContinue = create_backup_folders();
} while (canContinue == false);

Related

'System.IO.FileNotFoundException' when trying to save an outlook Attachment

I have built a small web application to read appointments from outlook calendar and i used Microsoft.Office.Interop.Outlook. Now I want to to able to save the attachments which are inside the appointment.
Here is my code so far :
foreach (var item in AppointmentItems) {
for (int i = 1; i <= item.Attachments.Count; i++) {
var Attachment = item.Attachments[i];
string SavePath = Path.Combine(#"D:\SaveTest", Attachment.FileName);
Attachment.SaveAsFile(SavePath);
}
}
Problem :
Exception thrown: 'System.IO.FileNotFoundException at exactly
Attachment.SaveAsFile(SavePath);
I have already looked everywhere, this method should save the attachment to the path but its somehow trying to read a file.
Assuming that the attachment exist, FileNotFoundExecption is triggered by a not existing part of your path. You can check if the path exist first:
Directory.Exists(#"D:\SaveTest")
Then you can check if you have write rights on the directory:
Try
{
return System.IO.Directory.GetAccessControl(#"D:\SaveTest")
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount))
.Cast<System.Security.AccessControl.FileSystemAccessRule>()
.Where(rule => (System.Security.AccessControl.FileSystemRights.Write & rule.FileSystemRights) == System.Security.AccessControl.FileSystemRights.Write)
.Any(rule => rule.AccessControlType == System.Security.AccessControl.AccessControlType.Allow);
} catch(Exception)
{
return false;
}
3 things you could try to do:
Make sure that the directory exists
Check if Attachment.FileName have valid name and extension
Check your write access
System.IO.FileNotFoundExecption means it can't find the file you are looking for or the path you are trying to save to in your case. remove # and try "D:\foldername\" + attachment.filename. although removing # should still work I think you need use plus operator. Would help you can post the whole block of code so we can understand what is going on from top to bottom.

Why does my file sometimes disappear in the process of reading from it or writing to it?

I have an app that reads from text files to determine which reports should be generated. It works as it should most of the time, but once in awhile, the program deletes one of the text files it reads from/writes to. Then an exception is thrown ("Could not find file") and progress ceases.
Here is some pertinent code.
First, reading from the file:
List<String> delPerfRecords = ReadFileContents(DelPerfFile);
. . .
private static List<String> ReadFileContents(string fileName)
{
List<String> fileContents = new List<string>();
try
{
fileContents = File.ReadAllLines(fileName).ToList();
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
return fileContents;
}
Then, writing to the file -- it marks the record/line in that file as having been processed, so that the same report is not re-generated the next time the file is examined:
MarkAsProcessed(DelPerfFile, qrRecord);
. . .
private static void MarkAsProcessed(string fileToUpdate, string
qrRecord)
{
try
{
var fileContents = File.ReadAllLines(fileToUpdate).ToList();
for (int i = 0; i < fileContents.Count; i++)
{
if (fileContents[i] == qrRecord)
{
fileContents[i] = string.Format("{0}{1} {2}"
qrRecord, RoboReporterConstsAndUtils.COMPLETED_FLAG, DateTime.Now);
}
}
// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
}
So I do delete the file, but immediately replace it:
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
The files being read have contents such as this:
Opas,20170110,20161127,20161231-COMPLETED 1/10/2017 12:33:27 AM
Opas,20170209,20170101,20170128-COMPLETED 2/9/2017 11:26:04 AM
Opas,20170309,20170129,20170225-COMPLETED
Opas,20170409,20170226,20170401
If "-COMPLETED" appears at the end of the record/row/line, it is ignored - will not be processed.
Also, if the second element (at index 1) is a date in the future, it will not be processed (yet).
So, for these examples shown above, the first three have already been done, and will be subsequently ignored. The fourth one will not be acted on until on or after April 9th, 2017 (at which time the data within the data range of the last two dates will be retrieved).
Why is the file sometimes deleted? What can I do to prevent it from ever happening?
If helpful, in more context, the logic is like so:
internal static string GenerateAndSaveDelPerfReports()
{
string allUnitsProcessed = String.Empty;
bool success = false;
try
{
List<String> delPerfRecords = ReadFileContents(DelPerfFile);
List<QueuedReports> qrList = new List<QueuedReports>();
foreach (string qrRecord in delPerfRecords)
{
var qr = ConvertCRVRecordToQueuedReport(qrRecord);
// Rows that have already been processed return null
if (null == qr) continue;
// If the report has not yet been run, and it is due, add i
to the list
if (qr.DateToGenerate <= DateTime.Today)
{
var unit = qr.Unit;
qrList.Add(qr);
MarkAsProcessed(DelPerfFile, qrRecord);
if (String.IsNullOrWhiteSpace(allUnitsProcessed))
{
allUnitsProcessed = unit;
}
else if (!allUnitsProcessed.Contains(unit))
{
allUnitsProcessed = allUnitsProcessed + " and "
unit;
}
}
}
foreach (QueuedReports qrs in qrList)
{
GenerateAndSaveDelPerfReport(qrs);
success = true;
}
}
catch
{
success = false;
}
if (success)
{
return String.Format("Delivery Performance report[s] generate
for {0} by RoboReporter2017", allUnitsProcessed);
}
return String.Empty;
}
How can I ironclad this code to prevent the files from being periodically trashed?
UPDATE
I can't really test this, because the problem occurs so infrequently, but I wonder if adding a "pause" between the File.Delete() and the File.WriteAllLines() would solve the problem?
UPDATE 2
I'm not absolutely sure what the answer to my question is, so I won't add this as an answer, but my guess is that the File.Delete() and File.WriteAllLines() were occurring too close together and so the delete was sometimes occurring on both the old and the new copy of the file.
If so, a pause between the two calls may have solved the problem 99.42% of the time, but from what I found here, it seems the File.Delete() is redundant/superfluous anyway, and so I tested with the File.Delete() commented out, and it worked fine; so, I'm just doing without that occasionally problematic call now. I expect that to solve the issue.
// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
I would simply add an extra parameter to WriteAllLines() (which could default to false) to tell the function to open the file in overwrite mode, and not call File.Delete() at all then.
Do you currently check the return value of the file open?
Update: ok, it looks like WriteAllLines() is a .Net Framework function and therefore cannot be changed, so I deleted this answer. However now this shows up in the comments, as a proposed solution on another forum:
"just use something like File.WriteAllText where if the file exists,
the data is just overwritten, if the file does not exist it will be
created."
And this was exactly what I meant (while thinking WriteAllLines() was a user defined function), because I've had similar problems in the past.
So, a solution like that could solve some tricky problems (instead of deleting/fast reopening, just overwriting the file) - also less work for the OS, and possibly less file/disk fragmentation.

Moving a folder, from one directory to another. in c#

Okay, so me and several others are trying to move a bunch of files from a game launcher. To said directory of your choice.
The problem is, the files wont move.
The way the launcher works, is you click install on the game, it installs a bunch of files to the location of your choice. But the files wont move.
Here' the code.
private void MoveFolders()
{
string sourceDir = Config.GetGamePath();
string destinationDir = textBoxFolder.Text;
try
{
if (Directory.Exists(sourceDir) == true)
{
if (bGameIsInstalled == true && textBoxFolder.TextLength > 0)
{
Directory.Move(sourceDir, destinationDir);
bMoveFolders = true;
}
else
{
MessageBox.Show("Select Arma 3 directory before starting game");
}
}
else
{
// Do somthing about source directory not existing -
}
}
catch (Exception ex)
{
//TODO: Handle the execption that has been thrown will do this on launcher update
}
}
You can use CopyFile. As you said this should be a installer, i wouldn't move them folders to another direction. Just copy it, because you can't use the installer one more time after all these files needed are moved away.
And if you debug it, please just don't use try and catch. Test your code simply.

"There is no working folder mapping" error when accessing TFS

I'm working on an application that can create and add items to TFS.
My files get created correctly and in the correct location, however the Workspace.PendAdd method only works for one specific workspace, other workspaces give me the "There is no working folder mapping" error.
The method I am using is PendAdd(string filepath, bool recursive) so I pass in a directory to be added and would expect to add both the directory and its files as a pending add in TFS.
Both workspaces are identical in everything but name, neither have any files currently checked out and neither contain any files.
From my google searches I have found that there may be an issue when adding files to a workspace mapped to $/ but the workspace I am using is mapped to $/TFSFiles/ and so far nothing else seems likely.
The code for my PendAdd method is :
private IEnumerable<PendingChange> PendAddFileToTfs(string newFilename)
{
var previousPendingChanges = new List<PendingChange>(_selectedWorkspace.GetPendingChanges());
var changesAdded = _selectedWorkspace.PendAdd(Path.GetDirectoryName(newFilename), true);
var pendingAdds = new List<PendingChange>(_selectedWorkspace.GetPendingChanges());
var itemsToCheckIn = pendingAdds.Except(previousPendingChanges);
return itemsToCheckIn;
}
The method fails at the _selectedWorkspace.PendAdd line. I debugged and verified it is the correct local path and correct workspace.
Can someone point me in the right direction here?
EDIT:
The _selectedWorkspace variable is set by the user.
I get a list of all available workspaces via this code:
_workspaces = _versionControl.QueryWorkspaces(null, _versionControl.AuthorizedUser,environment.MachineName);
I then show a list of workspaces in a combobox and allow the user to select one.
This calls this method:
public void SetWorkspace(string workspaceName)
{
_selectedWorkspace = _workspaces.FirstOrDefault(ws => ws.Name.Equals(workspaceName));
}
You need to create a local workspace before you can add pendAdd files to TFS. I am not sure where _selectedWorkspace is coming from but it looks like it is not configured properly. Although I don't have a c# version to hand I do have a version in PowerShell that calls c#... should give you the way to go.
function New-TfsTeamProjectRootFolder {
Param(
[Microsoft.TeamFoundation.Client.TfsTeamProjectCollection] $TfsCollection,
[Microsoft.TeamFoundation.Server.ProjectInfo] $TfsTeamProject,
[String] $GlobalEntryValue
)
$TempWorkspaceName = "Create-TfsTeamSourceFolder"
$TempFolder = "c:\temp\$TempWorkspaceName"
$ServerFolder = "$/$($TfsTeamProject.Name)"
$TfsVersionControl = Get-TfsVersionControlServer $TfsCollection
try {
$workspace = $TfsVersionControl.GetWorkspace($TempFolder )
} catch {
$workspace = $TfsVersionControl.CreateWorkspace($TempWorkspaceName);
$workspace.Map($ServerFolder, $TempFolder);
}
$NewFolder = "$TempFolder\$GlobalEntryValue";
try {
$SourceItem = $TfsVersionControl.GetItem("$ServerFolder/$GlobalEntryValue")
} catch {
New-Item -ItemType Directory -Force -Path $NewFolder;
$workspace.PendAdd($NewFolder, $true);
$pendingChanges = $workspace.GetPendingChanges();
$changesetNumber = $workspace.CheckIn($pendingChanges, "Added folder for '$GlobalEntryValue'");
$SourceItem = $TfsVersionControl.GetItem("$ServerFolder/$GlobalEntryValue")
}
$workspace.Delete()
Return $SourceItem
}
Again I am not sure why your code is not working as I think the issue is in the greater context than we can see in the example above.

How did this application update itself?

i have been looking for a way to update my application for ages, and still haven't found a solution. (Please don't say ClickOnce, it isn't suitable for this app).
Years ago i used to use MCadmin to run a Minecraft server, and i remembered that when it started, sometimes it would just say "Update downloaded, please restart!". I have tried to find out how this was done, so i have been looking in the source code and found some things.
Here is some code that i found:
private void CheckUpdateThread()
{
Program.AddRTLine(Color.Green, "Verifying existence of essential files...\r\n", false);
if (!File.Exists("ICSharpCode.SharpZipLib.dll"))
Util.DownloadURLToFile("https://internal.mcadmin.eu/ICSharpCode.SharpZipLib.dll", "ICSharpCode.SharpZipLib.dll");
if (!File.Exists("LICENSE.txt"))
Util.DownloadURLToFile("https://internal.mcadmin.eu/LICENSE.txt", "LICENSE.txt");
Program.AddRTLine(Color.Green, "Essential file validation completed!\r\n", false);
if (Program.dontUpdate)
{
Program.AddRTLine(Color.Green, "Update checking disabled!!!\r\n", false);
return;
}
UpdateRunning = true;
Program.AddRTLine(Color.Green, "Checking for updates...\r\n", false);
bool isUpdate;
if (Program.dontUpdateMCAdmin || 1 == 1)
{
Program.AddRTLine(Color.Green, "MCAdmin update checking disabled.\r\n", false);
}
else
{
isUpdate = Util.DownloadURLToAndDiff("https://internal.mcadmin.eu/MCAdmin.exe", "MCAdmin.exe.new", "MCAdmin.exe");
if (!isUpdate)
{
if (OutOfDateMCA)
{
Program.AddRTLine(Color.Orange, "MCAdmin update downloaded! Restart MCAdmin to apply update!\r\n", false);
SendAdminMessage("MCAdmin update downloaded, consider restarting.", 4);
}
else
{
Program.AddRTLine(Color.Green, "MCAdmin already up to date!\r\n", false);
}
}
else
{
try
{
if (File.Exists("MCAdmin.exe.old"))
File.Delete("MCAdmin.exe.old");
}
catch { }
try
{
if (File.Exists("MCAdmin.exe"))
File.Delete("MCAdmin.exe");
}
catch { }
if (File.Exists("MCAdmin.exe"))
File.Move("MCAdmin.exe", "MCAdmin.exe.old");
File.Move("MCAdmin.exe.new", "MCAdmin.exe");
OutOfDateMCA = true;
Program.AddRTLine(Color.Orange, "MCAdmin update downloaded! Restart MCAdmin to apply update!\r\n", false);
SendAdminMessage("MCAdmin update downloaded, consider restarting.", 4);
}
}
This code is from a single void in a class called "UpdateManager".
See how it does the whole "MCadmin.exe.old" and "MCadmin.exe.new" files, a bit like shadow copying.
There is more to the updater code, but i don't quite understand.
Here is the SVN:
https://code.google.com/p/mcadminfork/source/browse/
Could anybody help me find out how this updater was acheived?
Thanks.
Util.DownloadURLToAndDiff() does the actual downloading and file comparison. So you probably want to look at that.
Otherwise, it's pretty simple:
Download MCAdmin.exe.new
Delete MCAdmin.exe.old (leftover from previous update)
Try to delete current MCAdmin.exe
If delete fails (file in use probably), rename MCAdmin.exe MCAdmin.exe.old
Rename MCAdmin.exe.new MCAdmin.exe

Categories

Resources