Application.Executablepath in C# has mixed separator characters - unc

I'm using someone else's code (licensed) on two different machines. On one machine, the Application.ExecutablePath returns the result the programmer must have expected, on the other it does not. Both are Windows 7 machines.
On my machine, the Application.ExecutablePath returns something like:
"C:\\Dir1\\Dir2\\Dir3/bin/Debug/APP.EXE"
On the other machine, it returns
"C:\\Dir1\\Dir2\\Dir3\\bin/Debug/APP.EXE"
The programmer obviously expected the second return string, because the code does this:
string path = Application.ExecutablePath;
short found = (short)path.LastIndexOf(#"\");
if (found > -1)
{
path = path.Substring(0, found);
}
try
{
foreach (string File in Directory.GetFiles(path + #"\Res\Patterns\", "*.xml"))
{
found = (short)File.LastIndexOf(#"\");
if (found > -1)
//... use files found
and the directory of files is present in both machines under Dir3, so it is found on the other machine but not on mine. I can't find any information on when and where Windows decides to return the forward slash (like a URL path) vs. the UNC path using "\". Why would this code work differently on different machines?

I am guessing that the path you simplified to C:\\Dir1\\Dir2\\Dir3/bin/debug actually had a hash (#) in the Dir3 name.
This is a quirk with Application.ExecutablePath apparently. You can use Assembly.GetEntryAssembly().Location instead, which returns consistent results.

Related

Visual Studio sorting JSON properties wrong

I've run into a weird problem with Visual Studio 2017 (Enterprise, version 15.5.2) that I can only replicate on one specific machine. The problem doesn't occur on other development machines.
Given a file foo.resources.json with the following contents:
{
"FooReparatur": "Reparatur",
"FooVerlust": "Verlust",
"FooWema": "Wema"
}
Applying the quick action Sort Properties results in the keys being in the wrong order:
{
"FooReparatur": "Reparatur",
"FooWema": "Wema",
"FooVerlust": "Verlust"
}
The configured language for Visual Studio is English, there is no schema selected for the given file. The configured language for Windows is Estonian, but the sorting order is wrong by that alphabet as well.
I checked for any funny unicode characters or anything similar via a hexdump, but found nothing of the like either. As mentioned before, the file sorts correctly on all other machines.
I've tried disabling all the (default) extensions the installation has, but that doesn't resolve the problem either.
I've looked through most of the settings for both general text editing and the specific file type, but I can't find a setting that could cause this. What could be the issue? How can I debug this further?
This is a property of Estonian collation where 'V' and 'W' are treated as the same character. Hence, the next character that differs will be the significant one. As can be demonstrated by this C# code using .Net.
var words1 = new[] { "FooR", "FooVer", "FooWem" };
var words2 = new[] { "FooR", "FooVa", "FooWb" };
var estonianCultureInfo = new System.Globalization.CultureInfo("et-EE");
var estonianComparer = StringComparer.Create(estonianCultureInfo, false);
var sortedWords = words1.OrderBy(x => x, estonianComparer);
foreach (var word in sortedWords)
{
Console.WriteLine(word);
}
Console.WriteLine("[-----]");
sortedWords = words2.OrderBy(x => x, estonianComparer);
foreach (var word in sortedWords)
{
Console.WriteLine(word);
}
Output:
FooR
FooWem
FooVer
[-----]
FooR
FooVa
FooWb
Try to use this plugin to sort :
https://marketplace.visualstudio.com/items?itemName=richie5um2.vscode-sort-json
If dosn't work, try to install again the visual studio and choose language English to test if it work
Good Chance.

Google Drive Windows App to/from fileId - items with same names, and multiple parents

I'm trying to translate from a Google Drive link on the web (well, the fileId anyway) to the Windows Google Drive app's path on the hard disk, and back again.
It would be helpful if there was something in the API for this (eg produce a path excluding the C:\Users\[User]\Google Drive\ from a file/folder ID, and vice versa), but there isn't.
So far I do:
Windows Path to ID: get the first folder of the path and (starting from the root) look for a matching folder, then repeat until finished (possibly with a file name). PROBLEM: Items can be called the same thing, whether files or folders or combinations of both, which is tricky in Windows. The app adds a number ' (1)' and so on, which I have to catch, but how can I know which item ID is the correct one? I believe that numbering is based on date but I'm not sure. So I can potentially end up with multiple results and no way to tell which is which.
ID to Windows Path: take the name of the file/folder from the ID, then keep adding the parent folder(s) until I build up a path. PROBLEM: same as 1 above, if there are multiple matching items then I can't tell which I should use when translating to Windows. PROBLEM: Apparently items in Google Drive can have more than one parent. Not sure how that works in the Windows app.
Can anyone help me fine tune how I do this, or tell me the exact details of how the Google Drive app does it? Code is welcome but not required, and I in turn can provide the code I use if needed.
I'm not sure if I fully understand the question, but I try to smack an answer anyway:
1/ assuming you have a Windows path,
C:\Users\User\Google Drive\myfile.ext
you create a file with a similar path on GooDrive iterating your path's tokens
recursively creating a tree structure on GooDrive. If the tree nodes (folders/files) exist, return ID's, otherwise create the objects. The main difference in GooDrive is that title query may return multiple objects (list of folders/files). Bad luck, you either use the first one or quit with an error.
global path = "C:\Users\User\Google Drive\myfile.ext"
createTree(String path) {
rootFolderId = create your root or use GooDrive root
fileId = iterate (firstToken(path, "\"), rootFolderId);
}
iterate(title, parentFolderId) {
ID (or multiple IDs) = search for title in parentFolderId
if (multiple IDs exist)
BOOM - report error and quit or use the first one
if (token not last) {
if (single ID for title exists) {
folderId = found ID
} else {
folderId = createFolder with title and parentFolderId metadata
}
iterate(nextToken(path, "\"), folderId)
} else { (last token represent file)
if (single ID for title exists) {
fileId = found ID
} else {
fileId = createFile with title and parentFolderId metadata
}
return fileId
}
}
You did not specify the language, but in case it is Java, you can see similar procedure here in the createTree() method (it is Android code, so there is a lot of Android specific goo there, sorry)
2/ assuming you have a Google Drive fileId, you construct the Windows path with this pseudocode (going from bottom up to the root). Again, you may have multiple parents you have to deal with (error or multiple paths with links to a single object)
String path = fileId's title
while () {
parentID = get fileId's parent
if (multiple parentIDs exist)
BOOM - report error and quit or construct multiple paths
(multiple paths would represent file/folder links)
if (parentID not valid or parentId's title not valid)
break
path = parentID's title + "\" + path
if (parentID's title is your root)
break
}
One more thing: You say "Folders and files can be called the same thing..."
In GooDrive, look at the MIME type, there is a specific MIME type "application/vnd.google-apps.folder" that tells you it is a folder. Also, any parentId metadata represents folder, since files can't be parents.
Good Luck

Redacted comments in MS's source code for .NET [duplicate]

The Reference Source page for stringbuilder.cs has this comment in the ToString method:
if (chunk.m_ChunkLength > 0)
{
// Copy these into local variables so that they
// are stable even in the presence of ----s (hackers might do this)
char[] sourceArray = chunk.m_ChunkChars;
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
What does this mean? Is ----s something a malicious user might insert into a string to be formatted?
The source code for the published Reference Source is pushed through a filter that removes objectionable content from the source. Verboten words are one, Microsoft programmers use profanity in their comments. So are the names of devs, Microsoft wants to hide their identity. Such a word or name is substituted by dashes.
In this case you can tell what used to be there from the CoreCLR, the open-sourced version of the .NET Framework. It is a verboten word:
// Copy these into local variables so that they are stable even in the presence of race conditions
Which was hand-edited from the original that you looked at before being submitted to Github, Microsoft also doesn't want to accuse their customers of being hackers, it originally said races, thus turning into ----s :)
In the CoreCLR repository you have a fuller quote:
Copy these into local variables so that they are stable even in the presence of race conditions
Github
Basically: it's a threading consideration.
In addition to the great answer by #Jeroen, this is more than just a threading consideration. It's to prevent someone from intentionally creating a race condition and causing a buffer overflow in that manner. Later in the code, the length of that local variable is checked. If the code were to check the length of the accessible variable instead, it could have changed on a different thread between the time length was checked and wstrcpy was called:
// Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= ret.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
///
/// imagine that another thread has changed the chunk.m_ChunkChars array here!
/// we're now in big trouble, our attempt to prevent a buffer overflow has been thawrted!
/// oh wait, we're ok, because we're using a local variable that the other thread can't access anyway.
fixed (char* sourcePtr = sourceArray)
string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
}
else
{
throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
}
}
chunk = chunk.m_ChunkPrevious;
} while (chunk != null);
Really interesting question though.
Don't think that this is the case - the code in question copies to local variables to prevent bad things happening if the string builder instance is mutated on another thread.
I think the ---- may relate to a four letter swear word...

Is there an easy way for cfengine3 to copy different files based on the OS its running

I have two different versions of linux/unix each running cfengine3. Is it possible to have one promises.cf file I can put on both machines that will copy different files based on what os is on the clients? I have been searching around the internet for a few hours now and have not found anything useful yet.
There are several ways of doing this. At the simplest, you can simply have different files: promises depending on the operating system, for example:
files:
ubuntu_10::
"/etc/hosts"
copy_from => mycopy("$(repository)/etc.hosts.ubuntu_10");
suse_9::
"/etc/hosts"
copy_from => mycopy("$(repository)/etc.hosts.suse_9");
redhat_5::
"/etc/hosts"
copy_from => mycopy("$(repository)/etc.hosts.redhat_5");
windows_7::
"/etc/hosts"
copy_from => mycopy("$(repository)/etc.hosts.windows_7");
This example can be easily simplified by realizing that the built-in CFEngine variable $(sys.flavor) contains the type and version of the operating system, so we could rewrite this example as follows:
"/etc/hosts"
copy_from => mycopy("$(repository)/etc.$(sys.flavor)");
A more flexible way to achieve this task is known in CFEngine terminology as "hierarchical copy." In this pattern, you specify an arbitrary list of variables by which you want files to be differentiated, and the order in which they should be considered, from most specific to most general. When the copy promise is executed, the most-specific file found will be copied.
This pattern is very simple to implement:
# Use single copy for all files
body agent control
{
files_single_copy => { ".*" };
}
bundle agent test
{
vars:
"suffixes" slist => { ".$(sys.fqhost)", ".$(sys.uqhost)", ".$(sys.domain)",
".$(sys.flavor)", ".$(sys.ostype)", "" };
files:
"/etc/hosts"
copy_from => local_dcp("$(repository)/etc/hosts$(suffixes)");
}
As you can see, we are defining a list variable called $(suffixes) that contains the criteria by which we want to differentiate the files. All the variables contained in this list are automatically defined by CFEngine, although you could use any arbitrary CFEngine variables. Then we simply include that variable, as a scalar, in our copy_from parameter. Because CFEngine does automatic list expansion, it will try each variable in turn, executing the copy promise multiple times (one for each value in the list) and copy the first file that exists. For example, for a Linux SuSE 11 machine called superman.justiceleague.com, the #(suffixes) variable will contain the following values:
{ ".superman.justiceleague.com", ".superman", ".justiceleague.com", ".suse_11",
".linux", "" }
When the file-copy promise is executed, implicit looping will cause these strings to be appended in sequence to "$(repository)/etc/hosts", so the following filenames will be attempted in sequence: hosts.superman.justiceleague.com, hosts.justiceleague.com, hosts.suse_11, hosts.linux and hosts. The first one to exist will be copied over /etc/hosts in the client, and the rest will be skipped.
For this technique to work, we have to enable "single copy" on all the files you want to process. This is a configuration parameter that tells CFEngine to copy each file at most once, ignoring successive copy operations for the same destination file. The files_single_copy parameter in the agent control body specifies a list of regular expressions to match filenames to which single-copy should apply. By setting it to ".*" we match all filenames.
For hosts that don't match any of the existing files, the last item on the list (an empty string) will cause the generic hosts file to be copied. Note that the dot for each of the filenames is included in $(suffixes), except for the last element.
I hope this helps.
(p.s. and shameless plug: this is taken from my upcoming book, "Learning CFEngine 3", published by O'Reilly)

How can I access the information associated to an object from a Mercurial plugin?

I am trying to write a small Mercurial extension, which, given the path to an object stored within the repository, it will tell you the revision it's at. So far, I'm working on the code from the WritingExtensions article, and I have something like this:
cmdtable = {
# cmd name function call
"whichrev": (whichrev,[],"hg whichrev FILE")
}
and the whichrev function has almost no code:
def whichrev(ui, repo, node, **opts):
# node will be the file chosen at the command line
pass
So , for example:
hg whichrev text_file.txt
Will call the whichrev function with node being set to text_file.txt. With the use of the debugger, I found that I can access a filelog object, by using this:
repo.file("text_file.txt")
But I don't know what I should access in order to get to the sha1 of the file.I have a feeling I may not be working with the right function.
Given a path to a tracked file ( the file may or may not appear as modified under hg status ), how can I get it's sha1 from my extension?
A filelog object is pretty low level, you probably want a filectx:
A filecontext object makes access to data related to a particular filerevision convenient.
You can get one through a changectx:
ctx = repo['.']
fooctx = ctx['foo']
print fooctx.filenode()
Or directly through the repo:
fooctx = repo.filectx('foo', '.')
Pass None instead of . to get the working copy ones.