I have written my own screensaver, which makes use of additional files located at the same directory as the screensaver executable (.scr file).
If I right-click on the screensaver and select 'Test', all is well, those extra files are found.
But if I right-click and click on 'Install' to install the screensaver, it seems to not be able to find those files anymore.
Does the installation process make another copy of screensaver, or maybe change the working directory? If so, what directory is it in?
It's a Windows 7 desktop.
So far I have searched in Windows folder, Program Files, Program Files (x86).
UPDATE:
So, I added the following bit of code to determine the executable's location.
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
It appears that the screensaver is running from the directory where I put it, from the original file. However, after installing it, the only way I can reach files in the same folder from the executable is if I use full paths. If I run it as Test, I can simply use filenames only.
This should be a clue as to what is going on, I think. The above function, if I run it as Test, returns long file names, but if I run it as Installed, it returns short file names. I think that when Installed, it runs as some kind of a special process, or maybe a child process, which also interferes with file access.
What is going on?
I added a piece of code to determine the current working directory, and found that when running the screensaver in Installed mode, the current working directory becomes C:\Windows\system32, which would of course explain how files are referenced.
Environment.CurrentDirectory
Related
I'm getting mad with what (in my mind) should be an easy task:
On my desktop (but could be anywhere) I have a folder "project", a "console.msc" and another folder "files" inside.
"console.msc" have a task that runs file1.bat and it works if I use full paths but it doesn't with relative ones.
c:\users\user1\Desktop\project\files\file1.bat WORKS
.\files\file1.bat
DOESN'T WORK
I see that all the time, the custom mmc is lauched with elevated privileges (good, I want it) but the relative path used to call file1.bat just doesn't work and the error returned is "Windows cannot find [..]"
Does anybody know how to tell Windows to keep the current folder the mmc is run? Any clues welcomed! :-)
Running a process with elevated privileges might result in different working directory for that process, that's why relative paths are not working.
If you do not want to use absolute paths, you have to find a way to get path to a directory where your application is located, and then append the relative paths to that.
You don't specify how you are running your tasks, but if it's from another .BAT file, then full path to the batch file's directory is stored under %~dp0 variable. You can look up answers to this question for more details.
And you can also always use tool like Process Explorer to view information about your running process, including working directory (it's called Current directory there).
So I have been trying to build an installer for my game with NSIS. For the most part it works fine but just noticed that it seems to be skipping certain files for no reason. Or no reason I can figure out.
At first I was using this line to gather up all the files in the source folder:
File /r "${NSISDIR}\game\source\*.*"
However, I noticed that this didn't get everything. Granted it found all sub-folders and kept the hierarchy correct. There didn't seem to be any rhyme or reason to what it skipped. Then I tried listing all files and directories separately and found out why. Example:
File "${NSISDIR}\OWTD-DE\source\pygame.math.pyd"
This produces the following error:
File: "C:\Program Files (x86)\NSIS\game\source\pygame.math.pyd" -> no files found.
But that file exists, I can see it in the source folder. This was the case for all missing files. At first I thought it may be the two periods in the name, but various files have that naming convention and they are added fine. I cannot figure out how to get it to recognize these files. Any ideas?
${NSISDIR} is a define used to access the UI resources in the Contrib subfolder, you are not supposed to put your files there. Your source files should not be in Program Files, only installed files should be located there. Also, on 64-bit systems there are two Program Files folders and there are some compatibility hacks in Windows related to %ProgramFiles% so putting your source files there is not optimal. Just because you see that file there does not mean it is actually in Program Files, it could be UAC Virtualization/VirtualStore tricking you...
Normally you would keep your .nsi somewhere in the same directory tree as the rest of your files so you can use relative paths but you can also use a define if you really want to:
!define MYSOURCE "c:\foo\bar"
...
Section
File /r "${MYSOURCE}\*.*"
SectionEnd
If it still misses some files I would suggest trying Process Monitor so you can see the low-level details...
Weirdly enough, this process did not work very well on Windows Home 64-Bit but did on Windows Professional 64-Bit. I'm not sure if this an issue with NSIS itself or what, but nothing was different between the two except the OS. And there really isn't much difference between those two operating systems. However, perhaps some configuration differences between the two was the real issue.
While marked solved, I'm not really sure what the actual issue and solution could be.
I have an old program that saves its files to Program Files. We are updating it to run properly on Windows 7. The problem is that we now can't find our saved files. Windows 7 allowed our program to save to program files, but obviously put the files somewhere else. We can't find that 'somewhere else'. Does anybody know where Windows 7 places its files when we save in Program Files?
Update:
We've looked in program files, in program files (x86), we've used Windows Explorer search function to try and find the directory name. Nothing works, but when we check to see if the directory we are making already exists in our application, we find it and put up our error dialog box.
Look in C:\Users\[USERNAME]\AppData\Local\VirtualStore\Program Files\[APPNAME]
Possibly program files (86) if your application is a 32 bit app. The place they should be saved is in the users directory though (or even better, give the user the choice of where to save).
I have a Ruby application I'm installing (along with a packaged ruby interpreter) under Program Files on Windows 7 with an NSIS-built installer. In order to debug it, I edited one of the files to add some debugging statements. After that, I uninstalled the package and ran a new version of the installer which includes a new copy of the edited file, without debugging statements.
Now, I can't get the new copy to load into ruby. If I run type <filename> in cmd.exe, or open the file in Notepad.exe or Firefox, I see the new version. If I run ruby -e "puts File.read('<filename>')", or open the file in emacs, I see the old version.
If, in Windows Explorer, I copy the file to a new filename, everything can see the new contents at that filename. If I delete the original file and rename the copy to replace the original, the split personality returns.
This situation survives a reboot, so it's not a simple matter of a file being accidentally held open.
What on earth is going on here? Is there some aspect of the install process that might be checkpointing the file in a way I can revert, or at least switch off while I'm debugging the installer?
update
If I run ruby -e "puts File.read('<filename>')" in a console that is run as administrator, I see the correct, new contents. How should I be managing this file?
I think it has to do with UAC file system virtualization. Check whether your file exists in C:\Users\<username>\AppData\Local\VirtualStore. If it does, delete it from the VirtualStore.
The fact you see the correct file when running Administrator console proves that it's because of virtualization: UAC virtualization is turned off for elevated processes.
In general, do not put files you plan to change a lot in Program Files. From Vista onward, there is an interesting way things work to "allow" you to write to a protected file, but it really gets stored in your app data directories, not actually in Program Files. So, utilities that go through the Windows API find the "new" version of the file correctly, but utilities that are more low-level (ruby.exe) only find the existing version. If you navigate to that folder, do you see a "Compatibility Files" button right above the contents? Press that and you'll see your updated version.
Scott Hanselman wrote a good article about this when it was introduced in Vista.
You can only write to the real file when you're logged on as Administrator.
I have a Windows service application on Vista SP1 and I've found that users are renaming its executable file (while it's running) and then rebooting, thus causing it to fail to start on next bootup because the service manager can no longer find the exe file since it's been renamed.
I seem to recall that with older versions of Windows you couldn't do this because the OS placed a lock on the file. Even with Vista SP1 I still cannot copy over the existing file when it's running - Windows reports that the file is in use - makes sense. So why should I be allowed to rename it? What happens if Windows needs to page in a new code page from the exe but the file has been renamed since it was started? I ran Process Monitor while renaming the exe file, etc, but Process Mon didn't report anything strange and just logged changing the filename like any other file.
Does anyone know what's going on here behind the scenes? It's seem counter intuitive that Windows would allow a running process' filename (or its dependent DLLs) to be changed. What am I missing here?
your concept is wrong ... the filename is not the center of the file-io universe ... the handle to the open file is. the file is not moved to a different section of disk when you rename it, it's still in the same place and the part of the disk the internal data structure for the open file is still pointing to the same place. bottom line is that your observations are correct. you can rename a running program without causing problems. you can create a new file with the same name as the running program once you've renamed it. this is actually useful behavior if you want to update software while the software is running.
As long as the file is still there, Windows can still read from it - it's the underlying file that matters, not its name.
I can happily rename running executables on my XP machine.
The OS keeps an open handle to the .exe file,. Renaming the file simply changes some filesystem metadata about the file, without invalidating open handles. So when the OS goes to page in more code, it just uses the file handle it already has open.
Replacing the file (writing over its contents) is another matter entirely, and I'm guessing the OS opens with the FILE_SHARE_WRITE flag unset, so no other processes can write to the .exe file.
Might be a stupid question but, why do users have access to rename the file if they are not suppose to rename the file? But yeah, it's allowed because, as the good answers point out, the open handle to the file isn't lost until the application exits. And there are some uses for it as well, even though I'm not convinced updating an application by renaming its file is a good practice.
You might consider having your service listen to changes to the directory that your service is installed in. If it detects a rename, then it could rename itself back to what it's supposed to be.
There are two aspects to the notion of file here:
The data on the disk - that's the actual file.
The file-name (could be several or none) which you can give that data - called directory entries.
What you are renaming is the directory entry, which still references the same data. Windows doesn't care about your doing so, as it still can access the data when it needs to. The running process is mapped to the data, not the name.