Simplifying logic to avoid duplicate error messages - c#

So far I have the following:
// Gets all the drives
DriveInfo[] allDrives = DriveInfo.GetDrives();
// checks if any CD-Rom exists in the drives
var cdRomExists = allDrives.Any(x => x.DriveType == DriveType.CDRom);
// Get all the cd roms
var cdRoms = allDrives.Where(x=>x.DriveType==DriveType.CDRom);
if (cdRomExists.Equals(true))
{
// Loop through the cd roms collection
foreach(var cdRom in cdRoms)
{
Console.WriteLine("Drive {0}", cdRom.Name);
Console.WriteLine(" File type: {0}", cdRom.DriveType);
if (cdRom.IsReady == true)
{
if (cdRom.DriveType == DriveType.CDRom)
{
DirectoryInfo di = new DirectoryInfo(cdRom.RootDirectory.Name);
var file = di.GetFiles("*.csv", SearchOption.AllDirectories).FirstOrDefault();
if (file == null)
{
errorwindow.Message = LanguageResources.Resource.File_Not_Found;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
else
{
foreach (FileInfo info in di.GetFiles("*.csv", SearchOption.AllDirectories))
{
Debug.Print(info.FullName);
ImportCSV(info.FullName);
break; // only looking for the first one
}
}
}
}
else if (cdRom.IsReady == false)
{
errorwindow.Message = LanguageResources.Resource.CDRom_Not_Ready;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
}
}
else
{
errorwindow.Message = LanguageResources.Resource.CDRom_Error;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
The problem with the following is, an error message pops up twice in a row to indicate if there is no CD-ROM in the drive because my computer contains both a DVD and blu ray Drive. If there is a CD Rom that contains CSV file, it gets successfully imported but another message pops up because of the foreach loop that runs to the blu ray drive and pops up.
I only want to display one error message for each of these situations:
-If there is no CD Rom that is ready and contains csv in the drive
-If the CD Rom drive does not contain csv
I think my logic is too convoluted and I need help adjusting my logic statements.

You just need to keep track of whether at least one of the drives worked for you. If none of them did, then you want to output the error message. There's also some other stuff you could do (no need to do the Any/Where, no need to do .Equals(true), etc. And more specifically, no need to continually check if its the right kind of drive. The cdRoms collection will only contain drives with the right type because that's what you specify in your Where clause.
// Gets all the drives
DriveInfo[] allDrives = DriveInfo.GetDrives();
// Get all the cd roms
var cdRoms = allDrives.Where(x=>x.DriveType==DriveType.CDRom);
if (cdRoms.Count() > 0)
{
bool found = false;
// Loop through the cd roms collection
foreach(var cdRom in cdRoms)
{
Console.WriteLine("Drive {0}", cdRom.Name);
Console.WriteLine(" File type: {0}", cdRom.DriveType);
if (cdRom.IsReady == true)
{
DirectoryInfo di = new DirectoryInfo(cdRom.RootDirectory.Name);
var file = di.GetFiles("*.csv", SearchOption.AllDirectories).FirstOrDefault();
if (file == null)
{
errorwindow.Message = LanguageResources.Resource.File_Not_Found;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
else
{
foreach (FileInfo info in di.GetFiles("*.csv", SearchOption.AllDirectories))
{
Debug.Print(info.FullName);
ImportCSV(info.FullName);
found = true;
break; // only looking for the first one
}
}
}
else
{
Debug.Print(string.Format("Drive {0} is not ready", cdRom.Name));
}
}
if (!found)
{
errorwindow.Message = LanguageResources.Resource.CDRom_Not_Ready;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
}
else
{
errorwindow.Message = LanguageResources.Resource.CDRom_Error;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}

Your code can be rewritten to following:
var cdRoms = allDrives.Where(x => x.DriveType == DriveType.CDRom && x.IsReady);
if (cdRoms.Any())
{
foreach(var cdRom in cdRoms)
{
Console.WriteLine("Drive {0}", cdRom.Name);
Console.WriteLine(" File type: {0}", cdRom.DriveType);
var di = new DirectoryInfo(cdRom.RootDirectory.Name);
var file = di.GetFiles("*.csv", SearchOption.AllDirectories).FirstOrDefault();
if (file == null)
{
errorwindow.Message = LanguageResources.Resource.File_Not_Found;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
else
{
foreach (var info in di.GetFiles("*.csv", SearchOption.AllDirectories))
{
Debug.Print(info.FullName);
ImportCSV(info.FullName);
break;
}
}
}
}
else
{
errorwindow.Message = LanguageResources.Resource.CDRom_Error;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
Changes:
No need to use Where and Any like you did, filter the CD-Rom drives from all the drives and see if any exist
Only select drives that are CD-Rom drives and are ready
Use var where possible, let the compiler do the job

This is my approach to your problem:
bool anyCdrom = false;
bool anyReady = false;
bool fileFound = false;
// Loop through the cd roms collection
foreach(var cdRom in DriveInfo.GetDrives().Where(drive => drive.DriveType == DriveType.CDRom))
{
anyCdrom = true;
Console.WriteLine("Drive {0}", cdRom.Name);
Console.WriteLine(" File type: {0}", cdRom.DriveType);
if (cdRom.IsReady) // You may want to put in into the intial where
{
anyReady = true;
foreach (string file in Directory.EnumerateFiles(cdRom.RootDirectory.Name, "*.csv", SearchOption.AllDirectories))
{
fileFound = true;
Debug.Print(file);
ImportCSV(file);
break; // only looking for the first one
}
if(fileFound)
break;
}
}
if(!anyCdrom)
{
errorwindow.Message = LanguageResources.Resource.CDRom_Error;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
else if(!anyReady)
{
errorwindow.Message = LanguageResources.Resource.CDRom_Not_Ready;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
else if(!fileFound)
{
errorwindow.Message = LanguageResources.Resource.File_Not_Found;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
It only prints an error when:
there is no cdrom
there is no cdrom ready
there is no csv file in any ready cdrom

Related

Printing listbox Items in order of occurence

I have an application that I have built and is just sort of printing app.
First I populate ListBox and format it then goto c:\somefolder
in some folder are pdf files it looks on listbox and see if there is any file name that matches an item on the listbox and sends it to the default printer.Everything is working great ,but say I have JohnDoe.pdf,ShahRukh.pdf,Vijay.pdf
how can I make it to send the files in that order, for now it works great ,but I want to be able to print ==> JohnDoe.pdf first, then ShahRukh.pdf and so on and so forth.Please if you have any idea to spare is much welcome.
Thanks in advance. This what I have right now it works great but print all items that match but randomly .I want it to respond or print matches in order of occurrence from top to bottom.
public class Pdf
{
public static Boolean PrintPDFs(string pdfFileName)
{
try
{
ProcessStartInfo stackOverflowHelp = new ProcessStartInfo();
stackOverflowHelp.Verb = "print";
stackOverflowHelp.FileName = pdfFileName;
stackOverflowHelp.CreateNoWindow = true;
stackOverflowHelp.WindowStyle = ProcessWindowStyle.Hidden;
Process gamingBoy = new Process();
gamingBoy.StartInfo = stackOverflowHelp;
gamingBoy.Start();
gamingBoy.WaitForInputIdle();
if (gamingBoy.HasExited == false)
{
gamingBoy.WaitForExit(20000);
//return true;
}
// System.Threading.Thread.Sleep(1000);
gamingBoy.EnableRaisingEvents = true;
gamingBoy.Close();
// return true;
//proc.Close();
//KillAdobe("AcroRd32");
return true;
}
catch
{
return false;
}
}
private void button2_Click(object sender, EventArgs e)
{
string dir = #"C:\slim\slimyyyy";//
if (Directory.Exists(dir))//If a directory defined above exists then do the followings
{
string[] pdf_Files = Directory.GetFiles(dir);
if (pdf_Files.Length > 0)
{
foreach (string file in pdf_Files)
{
string fileName = Path.GetFileName(file);
foreach (object item in listBox1.Items)
{
if (fileName == line.ToString())
{
Pdf.PrintPDFs((file));
}
}
}
}
}
}
Just reverse the order of your foreach loops:
foreach (object item in listBox1.Items)
{
foreach (string file in pdf_Files)
{
string fileName = Path.GetFileName(f);
if (fileName == line.ToString())
{
Pdf.PrintPDFs((file));
}
}
}
The easy answer is to change the order of your loops. That is, change your loop to:
foreach (var item in listBox1.Items)
{
var fname = item.ToString();
if (pdf_files.Contains(fname))
{
Pdf.PrintPDFs(fname);
}
}

Access Denied on accessing the system folder of any drive like system volume information

I have the following recursion code to get all the folders and files of a selected directory. But when I select a drive, for example E:\\ .., I am getting an error message of
"Access denied in accessing E:\system volume information"
Is it possible to bypass the system volume information folder?
This is the code I am using:
private static ArrayList GenerateFileList(string Dir)
{
ArrayList fils = new ArrayList();
bool Empty = true;
foreach (string file in Directory.GetFiles(Dir)) // add each file in directory
{
fils.Add(file);
Empty = false;
}
if (Empty)
{
if (Directory.GetDirectories(Dir).Length == 0)
// if directory is completely empty, add it
{
fils.Add(Dir + #"/");
}
}
foreach (string dirs in Directory.GetDirectories(Dir)) // recursive
{
foreach (object obj in GenerateFileList(dirs))
{
fils.Add(obj);
}
}
return fils; // return file list
}
private static ArrayList GenerateFileList(string Dir)
{
ArrayList fils = new ArrayList();
bool Empty = true;
try
{
foreach (string file in Directory.GetFiles(Dir)) // add each file in directory
{
fils.Add(file);
Empty = false;
}
}
catch(UnauthorizedAccessException e)
{
// I believe that's the right exception to catch - compare with what you get
return new ArrayList();
}
if (Empty)
{
if (Directory.GetDirectories(Dir).Length == 0)
// if directory is completely empty, add it
{
fils.Add(Dir + #"/");
}
}
foreach (string dirs in Directory.GetDirectories(Dir)) // recursive
{
foreach (object obj in GenerateFileList(dirs))
{
fils.Add(obj);
}

Denied access to User Folder

I Need to find my pictures in my User folder. But I get the runtime error Access Denied
Here is my code
static void Main(string[] args)
{
string pic = "*.jpg";
string b = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string appdata = Path.Combine(b, "AppData"); // I Dont want search in this folder.
string data = Path.Combine(b, "Data aplikací"); // Here also not.
foreach (string d in Directory.GetDirectories(b))
{
try
{
if ((d == data) || (d == appdata))
{
continue;
}
else
{
foreach (string f in Directory.GetFiles(d, pic))
{
//...
}
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
}
Running the application as admin doesn't work either. How to avoid this?
check if the folder is read only (in windows) if it is, just clear the read only flag.
if it isn't read only, make sure that the admin user has full rights on that folder. You can check this by right clicking on the folder --> properties --> security
check out this link for more information on how to set it programatically:
C# - Set Directory Permissions for All Users in Windows 7
Oh, don't go changing your directory/folder permissions - that's just asking for future pain.
There's no "one-liner" solution here - basically, you need to recursively walk through the folder structure looking for the files you care about, and absorbing/eating the UnauthorizedAccessExceptions along the way (you could avoid the exception altogether by checking DirectoryInfo.GetAccessControl, but that's a whole different question)
Here's a blob o'code:
void Main()
{
var profilePath = Environment
.GetFolderPath(Environment.SpecialFolder.UserProfile);
var imagePattern = "*.jpg";
var dontLookHere = new[]
{
"AppData", "SomeOtherFolder"
};
var results = new List<string>();
var searchStack = new Stack<string>();
searchStack.Push(profilePath);
while(searchStack.Count > 0)
{
var path = searchStack.Pop();
var folderName = new DirectoryInfo(path).Name;
if(dontLookHere.Any(verboten => folderName == verboten))
{
continue;
}
Console.WriteLine("Scanning path {0}", path);
try
{
var images = Directory.EnumerateFiles(
path,
imagePattern,
SearchOption.TopDirectoryOnly);
foreach(var image in images)
{
Console.WriteLine("Found an image! {0}", image);
results.Add(image);
}
var subpaths = Directory.EnumerateDirectories(
path,
"*.*",
SearchOption.TopDirectoryOnly);
foreach (var subpath in subpaths)
{
searchStack.Push(subpath);
}
}
catch(UnauthorizedAccessException nope)
{
Console.WriteLine("Can't access path: {0}", path);
}
}
}

C# WIA System.InvalidOperationException

I have a problem with scanning with WIA.
public List<Image> Scan(string scannerId)
{
var images = new List<Image>();
var hasMorePages = true;
while (hasMorePages)
{
// select the correct scanner using the provided scannerId parameter
var manager = new DeviceManager();
Device device = null;
foreach (DeviceInfo info in manager.DeviceInfos)
{
if (info.DeviceID == scannerId)
{
// connect to scanner
device = info.Connect();
break;
}
}
// device was not found
if (device == null)
{
// enumerate available devices
string availableDevices = "";
foreach (DeviceInfo info in manager.DeviceInfos)
{
availableDevices += info.DeviceID + "n";
}
// show error with available devices
throw new Exception("The device with provided ID could not be found. Available Devices:n" +
availableDevices);
}
Item item = device.Items[1];
try
{
// scan image
ICommonDialog wiaCommonDialog = new CommonDialog();
var image = (ImageFile) wiaCommonDialog.ShowTransfer(item, WiaFormatBmp, true); // <--- exception goes from there
// save to temp file
string fileName = "test.bmp";//Path.GetTempFileName();
File.Delete(fileName);
image.SaveFile(fileName);
image = null;
// add file to output list
images.Add(Image.FromFile(fileName));
}
catch (Exception exc)
{
throw exc;
}
finally
{
item = null;
//determine if there are any more pages waiting
Property documentHandlingSelect = null;
Property documentHandlingStatus = null;
foreach (Property prop in device.Properties)
{
if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_SELECT)
documentHandlingSelect = prop;
if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_STATUS)
documentHandlingStatus = prop;
}
// assume there are no more pages
hasMorePages = false;
// may not exist on flatbed scanner but required for feeder
if (documentHandlingSelect != null)
{
// check for document feeder
if ((Convert.ToUInt32(documentHandlingSelect.get_Value()) && WIA_DPS_DOCUMENT_HANDLING_SELECT.FEEDER) != 0)
{
hasMorePages = ((Convert.ToUInt32(documentHandlingStatus.get_Value()) &&
WIA_DPS_DOCUMENT_HANDLING_STATUS.FEED_READY) != 0);
}
}
}
}
return images;
}
When the scanning is completed i get an exception: "Dynamic operations can only be performed in homogenous AppDomain.". Can someone explain me what im doing wrong? I tried to use it in another Thread but still get the same exception.
Scanner: DSmobile 700D.

How to avoid using foreach loop to get the filelist for different reason

Here what am trying to do:
I have a remote server (e.g:svr01,svr02,svr03). Using GetFileList to read the directory get all the files and match with the file name I have then copy to my local drive.
If any files matched then am adding them to an XML file also.
I was trying to do like below
class Program
{
static void Main(string[] args)
{
var getfiles = new fileshare.Program();
string realname = "*main*";
string Location = "SVR01";
bool anymatch = false;
foreach (var file in getfiles.GetFileList(realname,Location))
{anymatch=true;}
if (anymatch == true)
{ baseMeta(); }
foreach (var file in getfiles.GetFileList(realname,Location))
{getfiles.copytolocal(file.FullName); }
}
private FileInfo[] GetFileList(string pattern,string Location)
{
try
{
switch (Location)
{
case "SVR01":
{
var di = new DirectoryInfo(#"\\SVR01\Dev");
return di.GetFiles(pattern);
}
case "SVR02":
{
var di = new DirectoryInfo(#"\\SVR02\Dev");
return di.GetFiles(pattern);
}
case "SVR03":
{
var di = new DirectoryInfo(#"\\SVR03\Prod");
return di.GetFiles(pattern);
}
default: throw new ArgumentOutOfRangeException();
}
}
catch(Exception ex)
{ Console.Write(ex.ToString());
return null;
}
}
private void copytolocal(string filename)
{
string nameonly = Path.GetFileName(filename);
File.Copy(filename,Path.Combine(#"c:\",nameonly),true);
}
private void baseMeta()
{
XmlWriter xmlWrite = XmlWriter.Create(#"c:\basexml");
xmlWrite.WriteStartElement("job");
xmlWrite.WriteElementString("Name", "test");
xmlWrite.WriteElementString("time", DateTime);
xmlWrite.Close();
}
}
but this piece of code worries me because am doing the same process two times, any one please guide me how to avoid this.
foreach (var file in getfiles.GetFileList(realname,Location))
{
anymatch=true;}
if (anymatch == true)
{
baseMeta();
}
foreach (var file in getfiles.GetFileList(realname,Location))
{
getfiles.copytolocal(file.FullName);
}
}
Even am trying to find out if it match anyfile then i quit the first foreach loop generate the basemeta() then goes to next foreach loop to do the rest of the process.
Using LINQ you should be able to easily change your posted code into:
var getfiles = new fileshare.Program();
string realname = "*main*";
string Location = "SVR01";
var fileList = getFiles.GetFileList(realname, Location);
var anymatch = fileList.Any();
if (anymatch) // Or possibly `if (fileList.Any())` if anymatch isn't
// really used anywhere else
baseMeta();
foreach (var file in getfiles.GetFileList(realname,Location))
getfiles.copytolocal(file.FullName);
You'll get the greatest benefit by replacing your GetFileList method with:
private IEnumerable<FileInfo> GetFileList(string pattern,string Location)
{
string directory = string.Empty;
switch (Location)
{
case "SVR01":
directory = #"\\SVR01\Dev";
break;
case "SVR02":
directory = #"\\SVR02\Dev";
break;
case "SVR03":
directory = #"\\SVR03\Prod");
break;
default:
throw new ArgumentOutOfRangeException();
}
DirectoryInfo di = null;
try
{
di = new DirectoryInfo(directory);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
yield break;
}
foreach(var fi in di.EnumerateFiles(pattern))
yield return fi;
}
Use this
var files = getfiles.GetFileList(realname, Location);
if (files.Length > 0)
{
baseMeta();
foreach(var file in files)
{
getfiles.copytolocal(file.FullName);
}
}
Try this:
Create method to check the file existence and do all in single loop.
your statement is not much clear that when you will copy or not.. use
your condition on which you want to copy or create xml entry..
What is your AnyMatch?? If you want to check that Is there any file then use
var fileList = getfiles.GetFileList(realname,Location);
if( fileList.Count() > 0)
{
baseMeta();
}
foreach (var file in fileList)
{
// copy the file if match does not exist..
getfiles.copytolocal(file.FullName);
}
But Foreach loop through collection if it have any item. so you need not to care about the count of the files..
If you want to do entry on every copy as per your code then why you need to check anyMatch etc. It will create entry on every file copy.
foreach (var file in getfiles.GetFileList(realname,Location))
{
baseMeta();
// copy the file
getfiles.copytolocal(file.FullName);
}

Categories

Resources