I am very new to C# and i have written the following class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace PrinterManager
{
class CheckFilesExist
{
public class CheckFilesExist
{
public static bool check(bool isThere)
{
DirectoryInfo di = new DirectoryInfo("c:\temp");
FileInfo[] TXTFiles = di.GetFiles("*.xml");
if (TXTFiles.Length == 0)
{
return isThere;
}
foreach (var fi in TXTFiles)
//return (fi.Exists);
return (fi.Exists);
return check;
}
}
}
}
It should check the directory for *.xml files and add them to an array. If it doesnt find any files then it should return false. It will go through the array and return true or false based on "check".
But i am getting the following error:
Cannot convert method group 'check' to non-delegate type 'bool'. Did
you intend to invoke the method?
It doesnt seem to like, "return check;" at the end.
I basically want to return a check to see if files exists in the folder.
Any ideas why mine isnt working?
Thanks
You can make a one-liner out of your method:
return new DirectoryInfo(#"c:\temp").EnumerateFiles("*.xml").Any();
Note that you are either have to use a literal string (prefixed by #) or properly escape the directory name, i.e. "C:\\temp".
No, it doesn't like return check; at the end - what did you want it to do? Your method is check - so "return true or false based on check" doesn't really make sense. Did you actually mean to return isThere instead?
It's not clear what the parameter is even really meant to be there for, to be honest... and if you've asked a DirectoryInfo for the files in that directory, I'd personally expect them to exist - otherwise why would they be returned?
Oh, and your directory name contains a tab where I suspect you actually want a backslash followed by a t.
I suspect your method would be better as:
public static bool TempDirectoryContainsXmlFiles()
{
DirectoryInfo di = new DirectoryInfo(#"c:\temp");
return di.GetFiles("*.xml").Length > 0;
}
or using LINQ for clarity:
public static bool TempDirectoryContainsXmlFiles()
{
DirectoryInfo di = new DirectoryInfo(#"c:\temp");
return di.GetFiles("*.xml").Any();
}
(You can use EnumerateFiles as shown by BrokenGlass which is more efficient for a large directory, but it's only available in .NET 4 and upwards.)
At a first glance, the problem as to be with the fact of your "check" variable having the same name as your function...
try like this....
private static bool Check_file_Existence(string sFileName)
{
try
{
return File.Exists(sFileName);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
Related
Here is my code:
private static bool checkifDirectoryContainsFilesWithSpecifiedExtention(string path, string fileExestention) //Like C:\\smth, *.html
{
foreach (string f in Directory.GetFiles(path,fileExestention))
{
return true;
}
foreach (string d in Directory.GetDirectories(path))
{
return checkifDirectoryContainsFilesWithSpecifiedExtention(d,fileExestention);
}
return false;
}
In this function the program returns every file with specified extention BUT If I contain only one file with the specified extention in the last folder, the function returns false, which makes no sence because it exists
My question is why it does that...
Try it out. I can't really find the bug.
The problem is the "return" inside the foreach (string d in Directory.GetDirectories(path)) loop. It will only check the first directory per level. You need something like this (not nice, but keeping your style/format)
bool ok = false;
foreach (string d in Directory.GetDirectories(path))
{
ok = ok || checkifDirectoryContainsFilesWithSpecifiedExtention(d,
fileExestention);
}
return ok;
Better yet, use the linq that Marc provided.
Turned this into a LINQ query
private static bool CheckifDirectoryContainsFilesWithSpecifiedExtention(string path, string fileExestention)
//Like C:\\smth, *.html
{
return Directory.GetFiles(path, fileExestention).Any() ||
Directory.GetDirectories(path)
.Select(d => CheckifDirectoryContainsFilesWithSpecifiedExtention(d, fileExestention))
.FirstOrDefault();
}
Tried it on the a few debug folders using *.exe as the mask and it returns true. It traverses sub folders as well. Not sure what you meant by one file in the last folder.
See if it works for you.
this works for me
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StackOverflowSnippets
{
class Program
{
static void Main(string[] args)
{
String path = #"C:\smth"; String pattern = "*.html";
Console.WriteLine("__" + checkifDirectoryContainsFilesWithSpecifiedExtention(path, pattern));
Console.ReadLine();
}
private static bool checkifDirectoryContainsFilesWithSpecifiedExtention(string path, string fileExestention) //Like C:\\smth, *.html
{
foreach (string f in Directory.GetFiles(path, fileExestention))
{
return true;
}
foreach (string d in Directory.GetDirectories(path))
{
if (checkifDirectoryContainsFilesWithSpecifiedExtention(Path.Combine(path, d), fileExestention))
{
return true;
}
}
return false;
}
}
}
I am trying to determine whether a C# assembly is a GUI or a Console application in order to build a tool which will automatically recreate lost short cuts.
Currently, I have a routine which recursively steps all directories in Program Files (and the x86 directory).
For each EXE it finds, the tool calls IsGuiApplication, passing the name of the EXE.
From there, I create an Assembly object using LoadFrom.
I want to check whether this assembly is has a GUI output, but I'm unsure how to test this in C#.
My current idea is to use GetStdHandle, but I'm not sure how to apply this to an assembly outside of the running application.
My experience with reflection in C# is limited, so any help would be appreciated.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace BatchShortcutBuild
{
class Program
{
//I'm uncertain that I need to use this method
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
static void Main(string[] args) {
BuildShortcuts();
Console.ReadLine();
}
public static void BuildShortcuts() {
String dirRoot = "C:\\Program Files\\";
processRoot(dirRoot);
dirRoot = "C:\\Program Files (x86)\\";
processRoot(dirRoot);
Console.WriteLine("Finished enumerating files");
Console.ReadLine();
}
public static void processRoot(String path) {
try {
foreach (String theDir in Directory.EnumerateDirectories(path)) {
processRoot(theDir);
}
foreach (String theFile in Directory.EnumerateFiles(path, "*.exe")) {
if (IsGuiApplication(theFile)) {
//I would generate a shortcut here
}
}
} catch { }
}
public static bool IsGuiApplication(String filePath) {
Console.WriteLine(filePath);
Assembly a = Assembly.LoadFrom(filePath);
//How to get the program type from the assembly?
return false;
}
}
}
Just to be safe here, the method suggested by #Killany and #Nissim suggest is not 100% accurate, as console applications can reference the System.Windows.* dlls (either by mistake or by a need of other functionality given by the 'System.Windows' assembly).
I'm not sure a 100% method exist, as some applications can be given a parameter to run with/without ui (i.e. silently)
As several times mentioned before, you can read the Subsystem Field.
private PEFileKinds GetFileType(string inFilename)
{
using (var fs = new FileStream(inFilename, FileMode.Open, FileAccess.Read))
{
var buffer = new byte[4];
fs.Seek(0x3C, SeekOrigin.Begin);
fs.Read(buffer, 0, 4);
var peoffset = BitConverter.ToUInt32(buffer, 0);
fs.Seek(peoffset + 0x5C, SeekOrigin.Begin);
fs.Read(buffer, 0, 1);
if (buffer[0] == 3)
{
return PEFileKinds.ConsoleApplication;
}
else if (buffer[0] == 2)
{
return PEFileKinds.WindowApplication;
}
else
{
return PEFileKinds.Dll;
}
}
}
Use GetReferencedAssemblies() to get all referenced assemblies and look for the system.windows.forms assembly
AssemblyName[] referencedAssemblies = assm.GetReferencedAssemblies();
foreach (var assmName in referencedAssemblies)
{
if (assmName.Name.StartsWith("System.Windows"))
//bingo
}
A basic idea to detect GUI apps is that GUI apps always use assembly System.Windows.*.
bool isGui(Assembly exeAsm) {
foreach (var asm in exeAsm.GetReferencedAssemblies()) {
if (asm.FullName.Contains("System.Windows"))
return true;
}
return false;
}
This will detect all .NET applications that are windows forms, or even WPF
One thing you could check is the .subsystem of the file's PE header. If you open up the file in ILDASM and check the manifest, you'll see this if it uses the Windows GUI subsystem:
I don't think there's any method in the Assembly class to check this, so you'll probably need to check the file itself.
Another way to check would be to go through the types in the assembly and see if any of them derive from System.Windows.Forms.Form (Windows Forms) or System.Windows.Window (WPF):
private static bool HasGui(Assembly a)
{
return a.DefinedTypes
.Any(t => typeof(System.Windows.Forms.Form).IsAssignableFrom(t) ||
typeof(System.Windows.Window).IsAssignableFrom(t));
}
Note that you'll need to add references to System.Windows.Forms.dll and PresentationFramework.dll to gain access to these types.
You can use Assembly.LoadFrom(string) to load the assembly. I tested this method myself and it seemed a bit slow so perhaps you can make it faster by involving Parallel.ForEach.
I want to check if a certain feature is installed on a certain machine.
I have a powershell code that checks this, and now I want to check this from .net code.
I can see that in the cmdlet, the code checks if there is an invalid namespace error.
When searching the web, I found the following code:
ManagementClass myClass = new ManagementClass(scope, path, getOptions);
try
{
myClass.get();
}
catch (System.Management.Exception ex)
{
if (ex.ErrorCode == ManagementStatus.InvalidNamespace)
{
return true;
}
}
...
I want to clean this code a bit, so basically I have 2 questions:
Is there another way to check for an InvalidNamespace error? (The code I've copied was later used to invoke some method within myClass, so I wonder if I can somehow achieve my goal in a more direct way)
Do I really need the parameter getOptions?
To get all the wmi namespaces, you must first connect to the root namespace and then query for all the __NAMESPACE instances, and for each instance recursively repeat this process. about the getOptions parameter which is a ObjectGetOptions class is not necessary in this case, so can be null.
Check this code to get all the wmi namespaces (you can populate a list with that info and then check if the namespace exist in the machine)
using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
namespace MyConsoleApplication
{
class Program
{
static private void GetWmiNameSpaces(string root)
{
try
{
ManagementClass nsClass = new ManagementClass( new ManagementScope(root), new ManagementPath("__namespace"), null);
foreach (ManagementObject ns in nsClass.GetInstances())
{
string namespaceName = root + "\\" + ns["Name"].ToString();
Console.WriteLine(namespaceName);
//call the funcion recursively
GetWmiNameSpaces(namespaceName);
}
}
catch (ManagementException e)
{
Console.WriteLine(e.Message);
}
}
static void Main(string[] args)
{
//set the initial root to search
GetWmiNameSpaces("root");
Console.ReadKey();
}
}
}
Lets say a have some path:
C:\Temp\TestFolder1\TestFolder2
And I have some template:
C:\Temp
So I want to write function that will delete all subdirectories by template
void DeleteSubdirectories(string tlt, string path) {}
If I call this function with given parameters
DeleteSubdirectories("C:\Temp", "C:\Temp\TestFolder1\TestFolder2");
It must delete TestFolder1\TestFolder2 subdirectories from 'C:\Temp
What is the best way to write this function?
If you desire to delecte "C:\Temp" too, use this:
System.IO.Directory.Delete(#"C:\Temp", true);
If you just want to delete the sub directories use this:
foreach (var subDir in new DirectoryInfo(#"C:\Temp").GetDirectories()) {
subDir.Delete(true);
}
System.IO.Directory.Delete("Path", true);
Just use Directory.Delete - the overload I linked has a boolean value that indicates if subdirectories should also be deleted.
What you're describing sounds wierd, but try this:
using System;
using System.IO;
static void DeleteSubDirectories(string rootDir, string childPath)
{
string fullPath = Path.Combine(rootDir, childPath);
Directory.Delete(fullPath);
string nextPath = Path.GetDirectoryName(fullPath);
while (nextPath != rootDir)
{
Directory.Delete(nextPath);
nextPath = Path.GetDirectoryName(nextPath);
}
}
Use it like:
DeleteSubdirectories("C:\Temp", "TestFolder1\TestFolder2");
Obviously, you'll have to implement the exception handling.
Is there a way to delete all files & sub-directories of a specified directory without iterating over them?
The non elegant solution:
public static void EmptyDirectory(string path)
{
if (Directory.Exists(path))
{
// Delete all files
foreach (var file in Directory.GetFiles(path))
{
File.Delete(file);
}
// Delete all folders
foreach (var directory in Directory.GetDirectories(path))
{
Directory.Delete(directory, true);
}
}
}
How about System.IO.Directory.Delete? It has a recursion option, you're even using it. Reviewing your code it looks like you're trying to do something slightly different -- empty the directory without deleting it, right? Well, you could delete it and re-create it :)
In any case, you (or some method you use) must iterate over all of the files and subdirectories. However, you can iterate over both files and directories at the same time, using GetFileSystemInfos:
foreach(System.IO.FileSystemInfo fsi in
new System.IO.DirectoryInfo(path).GetFileSystemInfos())
{
if (fsi is System.IO.DirectoryInfo)
((System.IO.DirectoryInfo)fsi).Delete(true);
else
fsi.Delete();
}
Why is that not elegant? It's clean, very readable and does the job.
Well, you could always just use Directory.Delete....
http://msdn.microsoft.com/en-us/library/aa328748%28VS.71%29.aspx
Or if you want to get fancy, use WMI to delete the directory.
Here's an extension method based on the OPs original code, which I think is just fine and a bit more readable than other options.
I agree it would be nice to have a single method in the framework to delete the contents of a directory without deleting the directory, but in my opinion, this is the next best thing.
using System;
using System.IO;
namespace YourNamespace
{
public static class DirectoryInfoExtensions
{
public static void EmptyDirectory(this DirectoryInfo di)
{
if (di.Exists)
{
foreach (var file in di.GetFiles())
{
file.Delete();
}
foreach (var directory in di.GetDirectories())
{
directory.Delete(true);
}
}
}
}
}