Compare subfolders name - c#

I'm not sure what the correct question for my case would be but I'll try to describe as good as I can. I have to mention that I don't have much knowledge of this language, I'm using it strictly for the executable of my appplication, mainly I mess around with Java. So I have an app that only starts up if it finds java in my PC. I'm using something like this:
ProcessStartInfo startJava = new ProcessStartInfo("java", JavaProcessArguments());
startJava.CreateNoWindow = !client.ShowConsole;
startJava.UseShellExecute = false;
But, let's say I want to use openJDK, then I would have to change "java" to something like this:
ProcessStartInfo startJava = new ProcessStartInfo
(#"C:\Program Files (x86)\Java\openJDK_1.7\bin\java.exe", JavaProcessArguments());
Moving on, I wanted to start openJDK FIRST, even if java is present, so I wrote a condition that does that:
private void StartTheProcess()
{
string pathJDK = #"C:\Program Files (x86)\Java\openJDK_1.7\bin\";
bool isDirJDK7 = Directory.Exists(pathJDK);
if (isDirJDK7)
{
ProcessStartInfo startJava = new ProcessStartInfo(#"C:\Program Files (x86)\Java\openJDK_1.7\bin\java.exe", JavaProcessArguments());
startJava.CreateNoWindow = !client.ShowConsole;
startJava.UseShellExecute = false;
try
{
using (Process p = Process.Start(startJava))
{
p.WaitForExit();
}
}
catch (Win32Exception ex)
{
some error...
}
catch (Exception e)
{
some error...
}
}
else
{
ProcessStartInfo startJava = new ProcessStartInfo("java", JavaProcessArguments());
startJava.CreateNoWindow = !client.ShowConsole;
startJava.UseShellExecute = false;
try
{
using (Process p = Process.Start(startJava))
{
p.WaitForExit();
}
}
catch (Win32Exception ex)
{
some error...
}
catch (Exception e)
{
some error...
}
}
}
Now let's suppose I have more openJDK versions in the "C:\Program Files (x86)\Java\" folder: openJDK_1.7, openJDK_1.7_u1, openJDK_1.8, so on, and I want to start the latest one. How should I accomplish this? I think one method would be to compare the subfolders names found there but I don't really know how to. The content of all the subfolders is identical and the names of the subfolders have the same construction (openJDK_1.X / openJDK_1.X_uYZ). Could you help me, based on this poorly (most likely) code? :D

There are a few things you could try,
Split the directory name string by
var version = string.split('_'), and then the version would be version[1] = "1.7", you can convert all of these into doubles/decimals/floats,etc and just sort the data out, get the latest version (the one with the highest number and get its directory back
The second thing you can try is checking the Directory.GetLastWriteTime(String), which you can compare, and find the last one, please not that this is not reliable at all since the folder can be changed by anything.

Related

Exclude System Hardlinks from File.Copy

So my problem is that I want to export my user account.
But inside C:\%user%\AppData\Local\ are System Hardlinks e.g.: Application Data which I obviously have no right to use them.
Is there a way to exclude those System Hardlinks from the copying process?
I'm not sure what you mean with hard links, but this might help you
foreach (var dir in new DirectoryInfo(#"c:\users\xxxxxx\AppData\Local").GetDirectories())
{
if (dir.Attributes.HasFlag(FileAttributes.ReparsePoint))
{
Console.WriteLine(dir.Name + " is symbolic, skip it");
}
else
{
//do your copy here
}
}
So I fixed the issue with Exception handling, doing it this way:
FileInfo[] sourceFiles = null;
try {
sourceFiles = new DirectoryInfo(sourcePath).GetFiles();
} catch (Exception ex) {
WriteLog(LogPath, ex + "");
return;
}
Since I'm a bit new to exception handling, I couldn't work it out for the first few hours on this problem.

Scan uploaded files C# ASP.net

I'm trying to do a virus scan on uploaded files.
I have no control over the installed virus scanner, the product hosted by multiple parties with different scanners.
I tried the following library but it always returns VirusNotFound on the eicar file.
https://antivirusscanner.codeplex.com/
Do you know any other solutions?
ClamAV has pretty bad detection scores.
VirusTotal is not on premises.
I decided to create CLI wrappers for multiple scanners, nuget packages can be found here: https://www.nuget.org/packages?q=avscan
And its documentation and source code available at https://github.com/yolofy/AvScan
I used this library for .net (It uses the VirusTotal public api):
https://github.com/Genbox/VirusTotal.NET
A little example from github :
static void Main(string[] args)
{
VirusTotal virusTotal = new VirusTotal("INSERT API KEY HERE");
//Use HTTPS instead of HTTP
virusTotal.UseTLS = true;
FileInfo fileInfo = new FileInfo("testfile.txt");
//Create a new file
File.WriteAllText(fileInfo.FullName, "This is a test file!");
//Check if the file has been scanned before.
Report fileReport = virusTotal.GetFileReport(fileInfo).First();
bool hasFileBeenScannedBefore = fileReport.ResponseCode == 1;
if (hasFileBeenScannedBefore)
{
Console.WriteLine(fileReport.ScanId);
}
else
{
ScanResult fileResults = virusTotal.ScanFile(fileInfo);
Console.WriteLine(fileResults.VerboseMsg);
}
}
A full example can be found here :
https://github.com/Genbox/VirusTotal.NET/blob/master/VirusTotal.NET%20Client/Program.cs
Clam AV is pretty good.
https://www.clamav.net/downloads
C# Api here:
https://github.com/michaelhans/Clamson/
I just tried various ways, But some didn't work.
Then I decided to use ESET NOD32 command line tools .
It works fine for me:
public bool Scan(string filename)
{
var result = false;
try
{
Process process = new Process();
var processStartInfo = new ProcessStartInfo(#"C:/Program Files/ESET/ESET Security/ecls.exe")
{
Arguments = $" \"{filename}\"",
CreateNoWindow = true,
ErrorDialog = false,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false
};
process.StartInfo = processStartInfo;
process.Start();
process.WaitForExit();
if (process.ExitCode == 0) //if it doesn't exist virus ,it returns 0 ,if not ,it returns 1
{
result = true;
}
}
catch (Exception)
{ //nothing;
}
return result;
}

C# Linq for files user has read access to

How would I use Linq on list.Items = directoryInfo.GetFiles("\\server\share\folder\"); to include only the files the user has read access to?
...
So far only suggestions are using try/catches, or APIs that are obsolete in .NET 4.0? I'd prefer something to read the ACL's and see if the specific user or a group the user is a member of has been granted read access. I'm trying to do this for simplified management of granting reports to users on a website that won't be high traffic, so the logic that "who knows if you can actually read it when you try to open the file" doesn't pertain to this case. I sense that Microsoft should really make this task easier.
You run the risk of a race condition if you check for read permission prior to opening the file.
If you're attempting to read all of the files you have access to in a folder, better to just try opening each one and catch the UnauthorizedAccessException.
See:
how can you easily check if access is denied for a file in .NET?
How do you check for permissions to write to a directory or file?
just try this out .should work .haven't tested though
var fw = from f in new DirectoryInfo("C:\\Users\\User\\Downloads\\").GetFiles()
where SecurityManager.IsGranted(new FileIOPermission
(FileIOPermissionAccess.Write, f.FullName))
select f;
EDIT if it is just read only files then try this
var fe = from f in new DirectoryInfo("C:\\Users\\ashley\\Downloads\\").GetFiles()
where f.IsReadOnly==true
select f
Note: I haven't tested it, but in theory it should work
First, define a predicate to determine read access
bool CanRead(FileInfo file)
{
try {
file.GetAccessControl();
//Read and write access;
return true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
//read-only access
return true;
}
return false;
}
}
Then, it should be a simple case of using a where clause in a linq query
from file in directoryInfo.GetFiles("\\server\share\folder\")
where HaveAccess(f) == true
select f;
Tested and working, but will return false if the file is in use
void Main()
{
var directoryInfo = new DirectoryInfo(#"C:\");
var currentUser = WindowsIdentity.GetCurrent();
var files = directoryInfo.GetFiles(".").Where(f => CanRead(currentUser, f.FullName));
}
private bool CanRead(WindowsIdentity user, string filePath)
{
if(!File.Exists(filePath))
return false;
try
{
var fileSecurity = File.GetAccessControl(filePath, AccessControlSections.Access);
foreach(FileSystemAccessRule fsRule in fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
{
foreach(var usrGroup in user.Groups)
{
if(fsRule.IdentityReference.Value == usrGroup.Value)
return true;
}
}
} catch (InvalidOperationException) {
//File is in use
return false;
}
return false;
}

How to get musicbrainz track information from audio file

Can anyone tell me how to get track information from the MusicBrainz database from an audio file (mp3, wav, wma, ogg, etc...) using audio fingerprinting. I'm using MusicBrainz Sharp library, but any other library is ok.
I've seen that you must use the libofa library, that you can't use MusicBrainz Sharp to get puid from the audio file, but I can't figure out how to use libofa with C#.
Please show some examples and code snippets to help me, because I can't find them anywhere.
Thanks in advance!
The thing is that you can probably use libofa to get a fingerprint of the audio file, but if the file has no PUID available, you will be stuck and will have to use something like genpuid to submit the audio fingerprint to AmpliFIND and wait about a day to get a PUID.
That being said, I tried something similar about two years ago, but kinda lost interest in the project when I failed to write the IDv3 tags, if I remember correctly. However, the source code is available on Bitbucket.
I basically wrapped libofa using a DllImport and also wrapped genpuid (ie. read the output XML) to be able to read the fingerprint and submit the file for fingerprinting if I did not get one from libofa. I also wrote some code that reads information from MusicBrainz using MusicBrainz Sharp.
Well, at least that was what I planned back then, I think. :) I hope this helps you to solve your problem and I'd love to see an update on this.
Edit: I just noticed that I created a bug report for myself, which basically says that I still needed an implementation for my decoder which is probably why I created this question in SO. So I guess I did not implement the genpuid fingerprinter just to be able to do the fingerprint/get the guid, because I did not get the libofa fingerprinter to work correctly.
I did the wrapped genpuid approach suggested above.
private string GetPUID(string fileName)
{
Process p;
ProcessStartInfo si;
string outRow;
string puidReturned;
string gendPuidPath = #"C:\Program Files\genpuid\genpuid.exe";
string gendPuidKey = "your key here";
System.Text.RegularExpressions.Regex puidRex = new System.Text.RegularExpressions.Regex( #"puid: (\S+)" ); // sample: puid: 3c62e009-ec93-1c0f-e078-8829e885df67
System.Text.RegularExpressions.Match m;
if (File.Exists(gendPuidPath))
{
try
{
si = new ProcessStartInfo(gendPuidPath, gendPuidKey + " \"" + fileName + "\"");
si.RedirectStandardOutput = true;
si.UseShellExecute = false;
p = new Process();
p.StartInfo = si;
p.Start();
puidReturned = "";
while ((outRow = p.StandardOutput.ReadLine()) != null)
{
m = puidRex.Match(outRow);
if (m.Success)
puidReturned = m.Groups[1].Value;
Debug.WriteLine(outRow);
}
p.WaitForExit();
p.Close();
return puidReturned;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
throw new Exception("Unexpexted Error obtaining PUID for file: " + fileName, ex);
}
}
else
{
Debug.WriteLine("genpuid.exe not found");
return "";
}
}

TFS / File Checkout from C#

I don't have a great deal of experience with TFS, other than using it for source control. I am working on a C# application that will need to modify files that are being controlled by TFS. From within my C# application, how can I check out a file that is controlled via TFS?
Thanks - Randy
You can use PendEdit to make your files writables, make your changes to it, then you add it to the pending changes, and finally check it in.
Here is some code where a folder structure is created and then checked in (Very similar to what you will need).
private static void CreateNodes(ItemCollection nodes)
{
using (var tfs = TeamFoundationServerFactory.GetServer("http://tfsserver:8080"))
{
var versionControlServer = tfs.GetService(typeof (VersionControlServer)) as VersionControlServer;
versionControlServer.NonFatalError += OnNonFatalError;
// Create a new workspace for the currently authenticated user.
var workspace = versionControlServer.CreateWorkspace("Temporary Workspace", versionControlServer.AuthenticatedUser);
try
{
// Check if a mapping already exists.
var workingFolder = new WorkingFolder("$/testagile", #"c:\tempFolder");
// Create the mapping (if it exists already, it just overides it, that is fine).
workspace.CreateMapping(workingFolder);
// Go through the folder structure defined and create it locally, then check in the changes.
CreateFolderStructure(workspace, nodes, workingFolder.LocalItem);
// Check in the changes made.
workspace.CheckIn(workspace.GetPendingChanges(), "This is my comment");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Cleanup the workspace.
workspace.Delete();
// Remove the temp folder used.
Directory.Delete("tempFolder", true);
}
}
}
private static void CreateFolderStructure(Workspace workspace, ItemCollection nodes, string initialPath)
{
foreach (RadTreeViewItem node in nodes)
{
var newFolderPath = initialPath + #"\" + node.Header;
Directory.CreateDirectory(newFolderPath);
workspace.PendAdd(newFolderPath);
if (node.HasItems)
{
CreateFolderStructure(workspace, node.Items, newFolderPath);
}
}
}
Using the other solution gave me permission problems.
Here's an alternative way to checkout your files using tf.exe:
//Checkout file
Process proc = new Process();
proc.StartInfo =
new ProcessStartInfo(
#"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe",
string.Format("checkout \"{0}\"", fileLocation)
);
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
For those looking to use the first solution and resolve the permission issue you can use the following code to use the current credentials, this replaces the "TeamFoundationServerFactory.GetServer" call then use the TfsTeamProjectCollection (tmPrjColl) to get the VersionControlServer:
using Microsoft.TeamFoundation.Client;
using MTVC = Microsoft.TeamFoundation.VersionControl.Client;
using MVSC = Microsoft.VisualStudio.Services.Common;
MVSC.VssCredentials creds = new MVSC.VssCredentials(new MVSC.WindowsCredential(true));
using (TfsTeamProjectCollection tmPrjColl = new TfsTeamProjectCollection(new Uri("<source control URL>"), creds))
{
MTVC.VersionControlServer verCtrlSvr = tmPrjColl.GetService<MTVC.VersionControlServer>();
...
}

Categories