Environment.GetFolderPath(Environment.SpecialFolder.SOMETHING) - c#

I've been trying out the most of the Enviroment.SpecialFolder enumeration, but I think there isn't any way of what I'd like to accomplish with the enumeration only. Using the string.Substring() method brought me the farest, yet.
I try to get just the system partition path, where windows is actually installed. On machine A it might be C:\, on machine B it might be D:\.
The most sufficent solution, I found so far was
var path = Environment.GetFolderPath(Environment.SpecialFolder.Windows)
.Substring(0, 3);
Is there a better way to do this? Thanks.

To get the drive, use Path.GetPathRoot. See http://msdn.microsoft.com/en-us/library/system.io.path.getpathroot.aspx
var root = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.Windows));

If you need "disk where Environment.SpecialFolder.Windows" your sample is ok.
You may want to use Path.GetPathRoot instead of Susbstring...
Note that you probably should not write anything to the root drive yourself (if your program is designed to behave nice).

Related

What's a performance friendly way to pre-store 412.000 strings so they're searchable in Unity?

I have a CSV file with 412.000 strings in that I would like to pre-store locally so that I can deploy to Android and iOS. The game must then be able to look through these strings to check if there's a match based on user input.
The only viable solution that I can see would be SQLite. I haven't come across a very good SQLite solution for Unity yet.
Is there a built-in solution in Unity that I am overlooking?
The solution has to work locally. No HTTP calls.
400,000 strings is absolutely trivial.
Just put them in a dictionary (list, whatever is relevant and that you prefer).
It's a total non-issue.
It's likely you would just load them from a text file, easy as pie.
public TextAsset theTextFile;
(Just drag to the link in the Inspector, like any texture or similar.)
you can then very easily read that file as, say, JSON. (Just use JsonUtility. You can find numerous examples of this in SO and elsewhere.) For example,
Blah bb = JsonUtility.FromJson< Blah >(ta.text);
yourDict = bb.fieldname.ToDictionary(i => i.tag, i => i);
Note that you mention "memory" and so on. It's totally irrelevant, the data you are talking about is the fraction of the size of any tiny image - ! , it's a non-issue, you don't have to think about it. The hardware/software system will handle it.
P.S. ...
If you literally want to use csv, it's totally easy. I suggest you ask a new question giving the details of your file and so on, so you can get an exact answer.
Note that you'd just use a HashSet rather than a Dictionary. It's even easier.
It's just something like:
var wordList = theTextFile.text.Split('\n');
You can google many examples!
https://stackoverflow.com/a/9791488/294884
http://answers.unity.com/answers/397537/view.html

How do I read the Windows NTFS $Secure file (and/or the $SDS stream) programmatically in C#

The methods in the .NET platform's DirectorySecurity namespace (e.g. GetAccessRules()) are far too slow for my purposes. Instead, I wish to directly query the NTFS $Secure metafile (or, alternatively, the $SDS stream) in order to retrieve a list of local accounts and their associated permissions for each file system object.
My plan is to first read the $MFT metafile (which I've already figured out how to do) - and then, for each entry therein, look up the appropriate security descriptor in the metafile (or stream).
The ideal code block would look something like this:
//I've already successfully written code for MFTReader:
var mftReader = new MFTReader(driveToAnalyze, RetrieveMode.All);
IEnumerable<INode> nodes = mftReader.GetNodes(driveToAnalyze.Name);
foreach (NodeWrapper node in nodes)
{
//Now I wish to return security information for each file system object
//WITHOUT needing to traverse the directory tree.
//This is where I need help:
var securityInfo = GetSecurityInfoFromMetafile(node.FullName, node.SecurityID);
yield return Tuple.Create(node.FullName, securityInfo.PrincipalName, DecodeAccessMask(securityInfo.AccessMask));
}
And I would like my output to look like this:
c:\Folder1\File1.txt jane_smith Read, Write, Execute
c:\Folder1\File1.txt bill_jones Read, Execute
c:\Folder1\File2.txt john_brown Full Control
etc.
I am running .NET version 4.7.1 on the Windows 10.
There's no API to read directly from $Secure, just like there is no API to read directly from $MFT. (There's FSCTL_QUERY_FILE_LAYOUT but that just gives you an abstracted interpretation of the MFT contents.)
Since you said you can read $MFT, it sounds like you must be using a volume handle to read directly from the volume, just like chkdsk and similar tools. That allows you to read whatever you want provided you know how to interpret the on-disk structures. So your question reduces to how to correctly interpret the $Secure file.
I will not give you code snippets or exact data structures, but I will give you some very good hints. There are actually two approaches possible.
The first approach is you could scan forward in $SDS. All of the security descriptors are there, in SecurityId order. You'll find there's at various 16-byte aligned offsets, there will be a 20-byte header that includes the SecurityId among other information, and following that there's the security descriptor in serialized form. The SecurityId values will appear in ascending order in $SDS. Also every alternate 256K region in $SDS is a mirror of the previous 256K region. To cut the work in half only consider the regions 0..256K-1, 512K..768K-1, etc.
The second approach is to make use of the $SII index, also part of the $Secure file. The structure of this is a B-tree very similar to how directories are structured in NTFS. The index entries in $SII have SecurityId as the index for lookups, and also contain the byte offset you can go to in $SDS to find the corresponding header and security descriptor. This approach will be more performant than scanning $SDS, but requires you to know how to interpret a lot more structures.
Craig pretty much covered everything. I would like to clear some of them. Like Craig, no code here.
Navigate to the node number 9 which corresponds to $Secure.
Get all the streams and get all the fragments of the $SDS stream.
Read the content and extract each security descriptor.
Use IsValidSecurityDescriptor to make sure the SD is valid and stop when you reach an invalid SD.
Remember that the $Secure store the security descriptors in self-relative format.
Are you using FSCTL_QUERY_FILE_LAYOUT? The only real source of how to use this function I have found is here:
https://wimlib.net/git/?p=wimlib;a=blob;f=src/win32_capture.c;h=d62f7d07ef20c08c9bec93f261131033e39b159b;hb=HEAD
It looks like he solves the problem with security descriptors like this:
He gets basically all information about files from the MFT, but not security descriptors. For those he gets the field SecurityId from the MFT and looks in a hash table whether he already has a mapping from this ID to the ACL. If he has, he just returns it, otherwise he uses NtQuerySecurityObject and caches it in the hash table. This should drastically reduce the amount of calls. It assumes that there are few security descriptors and that the SecurityID field correctly represents the single instancing of the descriptors

How to create a guaranteed invalid full path

I am testing software in C# and must ensure proper behavior (graceful failure) occurs when a program is given an invalid full path. Initially this is trivial,as I give something like "Q:\\fakepath" and since there is no Q drive mounted on the system, the program fails as expected.
However, I would like my test to be robust and want a way to generate a path that is guaranteed to not exist and to not be able to exist. The path must be full since if it doesn't start with a drive letter it will be treated relative to some directory, resulting in no failure.
Some approaches I have though of are to search for local drives that are mounted and then pick a drive letter that does not appear. This would work fine and I might end up using this, but I would prefer a more elegant solution such as using a drive letter that could not possibly exist.
Another (potential) option is to use invalid characters in the path name. However, using invalid characters is not preferred as it actually results in a different failure mode of the program.
So formally: How can I most elegantly generate a full path that is guaranteed not be invalid?
EDIT: The program I am testing will go ahead and create a directory (including parent directories) if it is on a valid drive but in a location that does not already exist. Hence, this path needs to be something that couldn't be created with something like Directory.CreateDirectory(<path>), not just something that doesn't already exist.
One method would be to use the Windows API to create a temporary folder. This might sound counterintuitive, but now you have a known empty folder, any path you specify inside it is guaranteed to not exist. For example:
//From https://stackoverflow.com/a/278457/1663001:
public string GetTemporaryDirectory()
{
string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
return tempDirectory;
}
public string GetNonexistantPath()
{
return Path.Combine(GetTemporaryDirectory(), "no-such-file");
}
One way to get a guaranteed invalid folder path is have a file that exists with the same name as part of the directory path.
public string Example()
{
string filePath = Path.GetTempFileName(); //Creates a uniquely named, zero-byte temporary file on disk.
var invalidDirectoryPath = Path.Combine(filePath, "CanNotExist");
Directory.CreateDirectory(invalidDirectoryPath); //throws a IOException
}
You could try using one of the reserved words, for instance C:\NUL (case-sensitive). Trying to create such directory will cause a DirectoryNotFoundException. More details here.
You can use some really long path (say a thousand characters). Your program won't probably be able to create it as it is invalid.
You can try this approach. Not sure though it would work or not but a worth try.
use path: Q:\asddsafkdjfkasjdfklahsjfhskdjfladjfhsafjklasdjfkashfkajsdfhasdklfjashdfkljasdhfklajdfajsdfklajsfkjasjfhadkfjasflhakldfjashdfklajsdjfhaksldjfahsdkljadfklajfkjlkajfkljagkjklfdjgklajdkfljgskljgklfjskgjfkljdsgkfsdgsfgsdfgsfggsdfgsfdgsgwesdfgdgjgfadfsfgffgfsdghijklm
Don't bother about counting the total number of letters, you can do the same using http://www.lettercount.com/
The trick is the max length of windows folder can be 260.
Though I tried in on Windows 10 and the max length allowed to me is 247.
Source_MAX_Length_Of_Folder_On_Windows
So, this folder is guaranteed to be never found. Cheers :)
Although, I think the most elegant solution is checking the mounted drives and generate a path afterwards that you have already mentioned and decided to keep it as a last option.

NetSpell spellchecker

Has anyone tried this library out? I cannot get it to work. For example, the spelling suggestions should work as follows.
But I am getting an empty list back.
I first got an exception saying
C:\Program Files (x86)\Common Files\microsoft
shared\DevServer\10.0\en-us.dic
is missing so I downloaded it from the web. The file I got has a list of thousands of english words and I even tried words from what it in the file and still no luck.
He is some code I tried.
Spelling s = new Spelling();
ArrayList items;
s.MaxSuggestions = 5;
s.SuggestionMode = Spelling.SuggestionEnum.PhoneticNearMiss;
s.Suggest(str);
items = s.Suggestions;
s.SuggestionMode = Spelling.SuggestionEnum.NearMiss;
s.Suggest(str);
items = s.Suggestions;
s.SuggestionMode = Spelling.SuggestionEnum.Phonetic;
s.Suggest(str);
items = s.Suggestions;
The Suggest method is supposed to get suggestions for 'str' and populate the Suggestions property. I am always getting 0 suggestions. I tried all three suggestion types that the library supports to see if that does anything as you can see, but that does not work either.
Even simple calls such as
s.TestWord("book")
give back "false". I think it is not able to use the dictionary file but not sure what else to do about it.
That is what it was, the dic file was not compatible. I just used the one that comes with when you download NetSpell and it works like a charm.
By the way, I switche to NHunspell and I like it much better than NetSpell. Easier to use and better suggestions.
http://www.crawler-lib.net/nhunspell

What is the way to apply extension methods?

When attempting to solve the problem
How many seven-element subsets (not repeatable) are there in a set of nine elements ?
I tried
IEnumerable<string> NineSet =new string[] {"a","b","c","d","e","f","g","h","i"};
var SevenSet =
from first in NineSet
from second in NineSet
where first.CompareTo(second)< 0 && first.Count() + second.Count()==7
select new { first, second };
What is the problem that prevents me from attempting to use first.Count() and second.Count()? I did not check whether it is the best solution for the problem.
As already stated, what you have written down will lead you to nowhere. This is a question of combinatorics. AFAIK there is nothing pre-made in the .NET framework to solve for you combinatorics problems, hence you will have to implement the correct algorithm. If you get stuck, there are solutions out there, e.g. http://www.codeproject.com/KB/recipes/Combinatorics.aspx, where you can look at the source to see what you need to do.
first and second are strings, so you'll count their characters (this compiles, but intellisence hides it).
You're looking for something like NineSet.Count(first.Equals)
Well...
You haven't shown the error message, so it's hard to know what's wrong
Every element is of length exactly one, so I'm not sure what you're expecting to happen
As you know that first and second are strings, why aren't you using first.Length and second.Length?
As a side issue, I don't think this approach is going to solve the problem for you, I'm afraid...

Categories

Resources