Since Vista, there's a junction called "C:\Documents and Settings" which points to the "C:\Users" folder. There's a symbolic link from "C:\Users\All Users" to "C:\ProgramData", and one from "C:\Users\Default User" to "C:\Users\Default". There are various others within each user profile. These were added so that programs which used hard-coded paths wouldn't break when the folders were reorganised to make the full paths shorter.
Some applications - possibly including Windows Explorer - don't understand these links, and will list the files from both the original location and the junction.
For example, "C:\ProgramData\test.txt" could be listed as:
"C:\Documents and Settings\All Users\test.txt"
With nested junctions, the number of times the same file can be listed will grow dramatically.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
I've got an MFC program that I've been developing for, well, since Windows 2000. We heavily leverage threads in this app - multiple background worker threads at a low priority, a rendering thread at a higher (but still below-normal) priority, then the main threads at a regular priority for the app to remain responsive to the user interaction with the GUI.
It's worked great for W2K, WinXP, Vista, 7, and even 8 along with various flavour of each (though I didn't test much in Win 8). Now, with Win10, the GUI and in fact the entire operating system seems to be lethargic when the low priority threads are working - appearing to defeat the purpose of setting thread priorities.
My threading library code hasn't changed, only the OS. And if I take the current build and run it on Win7, it behaves as expected. I've done a cursory review and can't find what's changed in the API to correct this. Did Microsoft change/break basic thread priorities in Windows 10, or am I missing something else?
Double-clicking an image file in Windows (File) Explorer in Windows 10 ... how can I get this to open in a program of my choice? Going through the Settings, either default programs or file associations makes no difference.... I've Googled this and found no solution. Anyone here have one?
i want to format my laptop from windows 10 to ubunto , but i want to format just disk C and keeping all my E disk files , is it possible doing that while changing to ubunto and having access to them there ? and vise versa if i want to go back to windows could i keep some files ...
This is not a question - I just need to get some frustration out. And as a warning to other people about the problem.
I have this utility generating a batch file for setting environment variable values. (The need arises because under the Bamboo build system, any environment setting is lost from one job step to the next; each job step must set the environment variables anew - but this is of minor importance to the problem). PATH and SET commands are written to a file named on the command line - I usually name it setenv.bat - and then executed in every job step.
Only that some users, running this utility on their desktop machines, ended up with crazy environment settings, not at all those that the utility shold have generated. But the debugger showed the correct commands to be written to the file. The .bat file appeared to, in mysterious ways, being modified between being written and being executed on the next command line.
The problem occured on PCs running cmd.exe in the default working directory, that of cmd.exe itself - C:\Windows\System32. (Most users change the CWD of cmd.exe to C:\ or some project directory, but those who rarely use CLI systems may not care to.) Running the utility from any other directory worked fine, but not from C:\Windows\System32. setenv.bat was not written to the directory; it never appeared.
I suspected access right problems, but creating the file caused no error/exception. Maybe the physical file was not accessed (causing the exception) until the file was flushed? So I flushed the file explicitly before closing it. Still no exception.
After closing I checked for File.Exists("C:\Windows\System32\setenv.bat"). True - file exists. I tried to open it: Once again - successful. I could read the correctly written contents. The file was completely absent from C:\Windows\System32\, yet I could create it, write to it, close it, open it again and read C:\Windows\System32\setenv.bat... What the... ???
So I searched the entire file system for the file setenv.bat. The first occurence explained how the crazy, incorrect settings could be made: Some completely unreated job had left a setenv.bat file in a directory on the path. Then there was a second setenv.bat occurence: In C:\Windows\SysWOW64, with a last written time stamp revealing that is was our guy.
I haven't yet sat down to learn the relationhship between System32 and SysWOW64 (but I sure will do now!). Appearently, System32 is interpreted as one core set of files, plus some extra - but the extras depend on who is asking. When a .net application (such as my utilitiy) asks, it gets the core+extras named SysWOW64, and new files are written to the extra part. When Explorer asks, it gets the core + another set of extras which do not overlap the extras of SysWOW64. When cmd.exe asks, in spite of being located in System32, does not get the SysWOW64 extras, but the same extras as Explorer. (Is it not a 32 bit program, in spite of its location?).
A simple workaround is to write to .\setenv.bat rather than setenv.bat. Even though CWD is identical in my utility and in cmd.exe, the .\setenv.bat generated is distinct from the .\setenv.bat executed on the next line. You then get an error message because C:\Windows\System32\setenv.bat, in the cmd.exe understanding, isn't there. But my utility cannot tell you in advance - to it, C:\Windows\System32\setenv.bat IS there!
Sure there are explanations, and frequently good ones. It can make sense to give a 64 bit application a different file than the one you give to a 32 bit application, especially if we talk about executable code. This logic may be the very best for the intended use.
My utility will write the file wherever the user tells it to write - it treats any file name as a plain string and does NOT have a list of directories given special treatment. I have no particular interest in writing to System32 - but if the user asks me to (in the command line parameter), I will do so. If the write fails, I'll report it. If it succeeds (which it does), and the file can be read back by the utility from System32, I would expect that the user's script could also read it back from System32. It can't. That's the frustrating point.
The user doesn't have an expressed wish to write to System32 - that's just were he ends up when starting cmd.exe. So he says: "Place the file here; it will be deleted in a second anyway". He doesn't want to know that he must specify ..\Sysnative to write them to his current working directory, named System32. The other alternative, that the next line in his script runs the file, which was written to System32, from ..\SysWOW64, is not significantly better. The user should not need to be concerned about the utility runing under dotNET! Trying to explain such things to users is not likely to make you a lot of new friends among them...
The end result is that if I want my utility to work (or even to give an error message / error return) for all users, even those running it from special directories, my utility will have to mess with the path, and be aware of all the paths that need to be messed with.
One funny detail I discovered after beginning to understand what happens: Start cmd.exe from \Windows\System32. Start cmd.exe from \Windwos\SysWOW64, and tell it to CD ..\System32. With the two command shells running from the same directory, give both a DIR command. The two directory lists, produced by the same command in the same current directory are neverhteless quite different.
The directory name might fool you to think that \Windows\System32\cmd.exe is a 32 bit program. It is not. It is a 64 bit program, while the one in SysWOW64 is a 32 bit program.
I guess that if we had a 64 bit implementation of dotNet, it would go to the same locations as e.g. Explorer does, so they would see the same set of files. As far as I know, dotNet is a 32 bit implementation (correct me if I am wrong). But I fear that the day we see a 64 bit dotNet, a number of applications will run into problems because the mapping of certain directories will be changed from the 32 bit version.
I suspect that lots of programmers are not aware of the issues this redirecting raises, and would run into the same problem as I did, without knowing why. Maybe the long term solution is to migrate dotNet to 64 bits.
Ok, I wasn't aware of the 64 bit dotNET. Thanks for the correction.
Obviously that isn't the default choice. Or at least was not under Windows7, which still is used on most of our machines.
I will be looking into the possibility of switching to 64-bit dotNet. My gut feeling is that it might require a little more work, for 100+ PCs, than you can accomplish before lunch. And that there may be more than one compatibility/porting issue to be solved.
Still, that is the way to go in the long run.
Of course I do not intentionally want to put files into \Windows\System32!
But my utility is agnostic with respect to the file name specified on the call line. If the user sits in \Windows\System32\ and specifies plain filename, with no path, the utility accepts that - it does not make any specific check for \Windows\System32 saying "I think you shouldn't write to this directory". That is the responsibility of the user.
There are other directories where I really don't want to leave .bat files, such as C:\
For all practical purposes it doesn't matter: The desktop user really calls a small script that generates the file, executes it, and deletes it. The problem with \Windows\System32 is that the file generated under \Windows\System32 cannot be deleted (from the script) under that name, because it isn't there, it is in a different place, under a different name from the name it was created with!
When the user sits in \Windows\System32 and explicitly asks for writing a .bat file there, and it is automatically deleted immediately after running, then I do not see the big problem: The user has write access, then I will do what he asks for. In locations where the user has no write privleges, the utility fails - I'd be happy to see that in \Windows\System32. The problem is that you can create the file, but you can't delete it without knowing all the inner workings and give special treatment to a bunch of directory names that appears to be quite normal.
There are a number of such virtual directories in Windows, essentially for accessing user profile data. In those cases, line 1 and line 2 in a given script file sees the same real file when using identical names. That is not the case here: A .net application sees a different file from what cmd.exe sees. That is what creates the problems.
Nobody says it's the user's fault. The user specifies a file name, my utility writes to the file named by the user, and successfully reads it back, under the name given by the user. Everything is OK so far. Then the user tries to read it (i.e. execute the script) using the file name he gave to the utility, and which worked fine within the utility. But then the file isn't there!
Even if the user specifies the fully rooted name, both when giving it to the utility, and when trying to execute the generated script, the file isn't there. But it was when the utility wrote it (and later read it back), under that very same name.
Whose fault is that? The user's fault? The utility's fault? They both use the same name, even fully rooted, but the file nevertheless "disappears".
This has nothing to do with where the utility is installed (that's in a completely different directory). The situation described solely depends on a data file written to C:\Windows\System32\. If the writing is done by a dotNet program, or any other 32 bit program, the data file is written to C:\Windows\SysWOW64, and is not seen in C:\Windows\System32\ by neither Explorer, cmd.exe nor any other 64 bit program, but appears to have disappeared. (Unless you fully understand what is going on - but even seasoned system programmers may be weak in that respect.)
If the user makes a "CD \" before running the utility, everything works fine. Or if he specifies a file name that is NOT in C:\Windows\System32. This is not easy to make users see as reasonable or "right". Plain users really shoudn't be messing around in C:\Windows\System32\ at all - but in an out-of-the box Windows installation, that is exactly where the user is sent when he opens a command window. That is really the one to blame! If the default working directory for cmd.exe had been C:\ rather than C:\Widows\System32, there wouldn't have been a problem.
Well, obviously: If some system guy really has work to do in \Windows\System32, the problem would still be the same for that guy. But if he has a reason to fiddle with System32, then he is most likely competent to understand why the system behaves that way. The ordinary user is not.
Like I said before, you should really not be writing into Windows\System32. There are plenty of locations which would save you all this aggravation, and indeed the estimable OrignalGriff has an article which may be of some use: Where should I store my data?[^], and yes I know it's about data.
So what do you suggest that I do, when the user opens a command window and asks the utility to genereate the file setenv.bat? Should I say: "Sorry, I can't do what you ask of me - even though you have write permission to that directory?"
I am not making the choice where to store the data. The user is. The user is, inadvertently because that is where cmd.exe by default sends him, in System32. The user has write access. The file is deleted after a second in any case, after the script is run.
You shouldn't store .bat files, not even for a second, in C:\ either. If the user nevertheless asks for it, it works, without. Should the utilty say, when the user says "Use C:\", in a similar manner say "Sorry, I am not willing to do that for you; you shouln't be puttng files there"?
It is so simple to say "You shouldn't do that". When the user says "Do it!" you may blame the user, or you may blame the utility doing what it is being asked to. Or you may say: OK, if the user asks to use that directory, and permissions are OK, then the user asked for it, the user got it!
You may go out on a mission to explain (or maybe "excuse") to all users of the world the underlaying reasons for why their files disappear into that black SysWOW64 hole, so that every user understands that where cnd.exe by default sends them, is to a place where they shouldn't be, and shouldn't touch anything unless they are computer experts. Then you have cleansed your hands and can say: We have told you not to be in that place where we sent you! So get out of there! This is logical, da*mit! Get out of there, now!
Arguing like that to users make you sound like a Unix guru...
Just make sure you generate your .bat file somewhere that is not going to cause problems, as suggested in OriginalGriff's Tip. It's no good saying the error is caused by the user's lack of knowledge, it is your responsibility to protect the user from him/herself.