Windows 7 registry %ProgramFiles% issue - windows

I have some kind of windows appilcation, running on Windows 7 32-bit. I'm trying to register particular file extension open command with my application using windows registry. Such file extension is my own and also registered by me. The application installed in particular subdirectory within Program Files. I want my installer to register application properly for both 32 and 64-bit platfroms, since actual Program Files directory names can be different on x86 and x64 platfroms, while I need to specify path to my application, I'm using registry redirection %ProgramFiles%. Here I reproduce what records I make to registry:
// file extension
HKEY_CURRENT_USER
Software
Classes
.myext
Default REG_SZ myapp.myext
// application
HKEY_CURRENT_USER
Software
Classes
.myapp.myext
Shell
Open
Command
Default REG_SZ "%ProgramFiles%\path\to\my\app\myapp.exe" -u -i "%1"
Actual path to program files dir in my test machine is C:\Program Files
With such registration I receive an error:
Windows cannot access the specified device path, or file. You may not
have the appropriate permissions to access the item.
If I replace %ProgramFiles% with actual C:\Program Files everything works fine. Also when I'm using same path: "%ProgramFiles%\path\to\my\app\myapp.exe" to run application from console everything works fine too. What can be reason of such issue.

%ProgramFiles% evaluates to the 32 bit program files dir in a 32 bit process and the 64 bit program files dir in a 64 bit process. However, the location of your executable does not depend on the bitness of the shell, which is the thing that reads those registry settings. You want to write the following value to the registry:
"C:\Program Files (x86)\path\to\my\app\myapp.exe" -u -i "%1"
where I assume that is the path to the 32 bit program files dir. You should not be writing an environment variable into this registry key. Your install program will already know the full path to the executable, and you should simply write that.
One issue that I think may be confusing you is that you may be under the believe that the program files directories are subject to file system redirection. They are not.
As an aside, if you ever need to write an environment variable into the registry, and want it to be expanded upon reading, use REG_EXPAND_SZ rather than REG_SZ.

Related

What is the reason for the error message "System cannot find the path specified"?

I have folder run in folder system32. When I run cmd from within Total Commander opening a command prompt window with C:\Users\admin as current directory and want to go into that folder, the following error message is output:
System cannot find the path specified.
When I open cmd directly in folder run, it works perfect. Why?
The command prompt window on opening in C:\Windows\System32\run:
C:\Windows\System32\run>cd..
C:\Windows\System32>cd run
C:\Windows\System32\run>
The command prompt window on simply running cmd:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Všetky práva vyhradené.
C:\Users\admin>cd..
C:\Users>cd..
C:\>cd windows
C:\Windows>cd system32
C:\Windows\System32>cd run
Systém nemôže nájst’ zadanú cestu.
The following worked for me:
Open the Registry Editor (press windows key, type regedit and hit Enter) .
Navigate to HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun and clear the values.
Also check HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun.
There is not only 1 %SystemRoot%\System32 on Windows x64. There are 2 such directories.
The real %SystemRoot%\System32 directory is for 64-bit applications. This directory contains a 64-bit cmd.exe.
But there is also %SystemRoot%\SysWOW64 for 32-bit applications. This directory is used if a 32-bit application accesses %SystemRoot%\System32. It contains a 32-bit cmd.exe.
32-bit applications can access %SystemRoot%\System32 for 64-bit applications by using the alias %SystemRoot%\Sysnative in path.
For more details see the Microsoft documentation about File System Redirector.
So the subdirectory run was created either in %SystemRoot%\System32 for 64-bit applications and 32-bit cmd is run for which this directory does not exist because there is no subdirectory run in %SystemRoot%\SysWOW64 which is %SystemRoot%\System32 for 32-bit cmd.exe or the subdirectory run was created in %SystemRoot%\System32 for 32-bit applications and 64-bit cmd is run for which this directory does not exist because there is no subdirectory run in %SystemRoot%\System32 as this subdirectory exists only in %SystemRoot%\SysWOW64.
The following code could be used at top of the batch file in case of subdirectory run is in %SystemRoot%\System32 for 64-bit applications:
#echo off
set "SystemPath=%SystemRoot%\System32"
if not "%ProgramFiles(x86)%" == "" if exist %SystemRoot%\Sysnative\* set "SystemPath=%SystemRoot%\Sysnative"
Every console application in System32\run directory must be executed with %SystemPath% in the batch file, for example %SystemPath%\run\YourApp.exe.
How it works?
There is no environment variable ProgramFiles(x86) on Windows x86 and therefore there is really only one %SystemRoot%\System32 as defined at top.
But there is defined the environment variable ProgramFiles(x86) with a value on Windows x64. So it is additionally checked on Windows x64 if there are files in %SystemRoot%\Sysnative. In this case the batch file is processed currently by 32-bit cmd.exe and only in this case %SystemRoot%\Sysnative needs to be used at all. Otherwise %SystemRoot%\System32 can be used also on Windows x64 as when the batch file is processed by 64-bit cmd.exe, this is the directory containing the 64-bit console applications (and the subdirectory run).
Note: %SystemRoot%\Sysnative is not a directory! It is not possible to cd to %SystemRoot%\Sysnative or use if exist %SystemRoot%\Sysnative or if exist %SystemRoot%\Sysnative\. It is a special alias existing only for 32-bit executables and therefore it is necessary to check if one or more files exist on using this path by using if exist %SystemRoot%\Sysnative\cmd.exe or more general if exist %SystemRoot%\Sysnative\*.
You just need to:
Step 1: Go home directory of C:\ with typing cd.. (2 times)
Step 2: It appears now C:\>
Step 3: Type dir Windows\System32\run
That's all, it shows complete files & folder details inside target folder.
Details: I used Windows\System32\com folder as example, you should type your own folder name etc. Windows\System32\run
*create a folder in desktop
*open its properties and check the location path as below
properties shows the location
we can find OneDrive(it can be something else in your pc) before the desktop
*Open cmd and run that before calling desktop
Loading OneDrive Before desktop
*Than We can call desktop and create directory without error
opening desktop and creating directory properly

Why can a double clicked batch file not find a registry value for deletion?

I wrote a bat file to delete an registry entry.
reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v VALUE /f
When I execute in cmd, it works.
But when I execute it by double click, it doesn't!!!
Error message:
Error: the system could not find the specified registry keys or values
Anyone else can tell me why!
On 64-bit Windows there is for automatic start of 64-bit applications
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
and for automatic start of 32-bit applications
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
If the batch file is executed by 32-bit cmd.exe in directory %SystemRoot%\System32\ being automatically redirected for 32-bit applications to %SystemRoot%\SysWOW64\, the registry path
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
is automatically redirected to
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
If the batch file is executed by 64-bit cmd.exe in directory %SystemRoot%\System32\, which can be called by 32-bit applications on Windows x64 using redirector %SystemRoot%\Sysnative\ instead of %SystemRoot%\System32\, the registry path
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
is indeed referencing
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
So I suppose that VALUE exists in Run key for 32-bit applications (below Wow6432Node), but the batch file on double click is executed by 64-bit cmd.exe because 64-bit Windows Explorer is used. Therefore the value cannot be found in Run key for 64-bit applications.
The solution is to use
%SystemRoot%\Sysnative\reg.exe delete HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run /v VALUE /f
Please note that special redirector %SystemRoot%\Sysnative\ exists only on 64-bit Windows and only for 32-bit applications, but does not exist on 32-bit Windows. Take that into consideration if the batch file should work also for 32-bit Windows.
For more information about redirections on Windows x64 read the Microsoft documentation pages:
Registry Redirector
File System Redirector
Make sure you run the batch file with elevated privileges. (Right click, "Run as Administrator")
It probably works in the command prompt because it is running itself with elevated privileges. For instance the command prompt shortcut might have its properties set to automatically run as an administrator.

Is it possible to properly execute qwinsta from a Cygwin ssh session?

I have Cygwin running on a Windows 7 machine and have the Cygwin ssh server running on it. On Linux I have a shell script where I want to do
ssh myuser#mymachine "qwinsta | grep Active"
to see who is logged in. This worked fine for a Windows Server 2008 R2 machine, but seems to have problems on Windows 7.
If I try this on the Windows 7 machine, I get:
bash: qwinsta: command not found
Now, here is where the weirdness begins...
If I login to the Windows 7 machine normally and look in C:\Windows\System32 with Windows Explorer, I see qwinsta.exe. If I open a CMD session and do a dir in C:\Windows\System32, I see qwinsta.exe. If I open a Cygwin shell and do a ls qwinsta.exe in /cygdrive/c/Windows/System32, I get:
ls: cannot access qwinsta.exe: No such file or directory
If I do a cmd /c dir C:\\\\Windows\\\\System32\\\\qwinsta.exe from the Cygwin shell, I get a "File Not Found"
If I copy qwinsta.exe into my Cygwin home directory, then it is visible in my home directory with ls. If I try to run this local copy of qwinsta from the Cygwin shell, it runs, but it also outputs a line:
{Message(): LoadString failed, Error 15105, (0x00003B01)}
What's up with qwinsta on Windows 7?
The problem is that qwinsta.exe is not actually located in C:\Windows\System32. It is actually found in
C:\Windows\winsxs\amd64_microsoft-windows-t..commandlinetoolsmqq_31bf3856ad364e35_6.XX.XXX.XXXX_none_XXXXXXXX\qwinsta.exe
Using the above path (or a softlink to the same) will run qwinsta.exe as it exists on any machine, and will not require you to copy the executable to your home directory.
The error message {Message(): LoadString failed, Error 15105, (0x00003B01)} is about the Multilinugal User Interface (localization) system not being able to find error message localization information for the program being run (see System Error Codes). In this case, it appears that the cygwin shell does not provide qwinsta.exe with the information it needs to find qwinsta.exe.mui in your language's locale folder (usually C:\Windows\System32\en-US or whatever your locale happens to be). Looking into this folder is somewhat misleading, as explorer will show the file in this directory, but when you run ls /cygdrive/c/Windows/System32/en-US, there is no qwinsta.exe.mui file. I suspect this has something to do with the new linking structure in NTFS (see mklink command), but I haven't figured out how to fix this part of the problem yet.
Solved:
First, go to C:\Windows\winsxs\amd64_microsoft-windows-t..commandlinetoolsmqq_31bf3856ad364e35_6.1.7600.16385_none_851e6308c5b62529
(Copy and pasting that location works just as well as manually finding it.)
You should find three files: Msg.exe , Quser.exe, and qwinsta.exe .
Copy these files to your C:\Windows\system32 folder
Next, go to C:\Windows\winsxs\amd64_microsoft-windows-t..etoolsmqq.resources_31bf3856ad364e35_6.1.7600.16385_en-us_7bef78d9f4a6a8ac
You should find three similarly named files, except these will end with .mui.
Copy all three of these files to your C:\Windows\system32\en-US folder.
Now try running the msg program. It should work without issue.
Windows 10
Following on from Erutan2099's answer, for Windows 10 it's a little trickier, since the files are compressed (binary delta compression, file signature 44 43 53 01). Trying to use them as is throws an Unsupported 16-Bit Application error:
The program or feature "\??\C:\Windows\System32\msg.exe" cannot start or run due to incompatibility with 64-bit versions of Windows. Please contact the software vendor to ask if a 64-bit Windows compatible version is available.
A specific tool has been made to decompress such files: SXSEXP (this post pointed me in the right direction)
Usage:
> sxsexp64.exe msg.exe expand\msg.exe
Processing target path msg.exe
msg.exe => expand\msg.exe
File size 12602 bytes
DCS_HEADER found.
NumberOfBlocks 1
UncompressedFileSize 26112
DCS_BLOCK #1
Block->CompressedBlockSize 0000312A
Block->DecompressedBlockSize 00006600
Operation Successful
> sxsexp64.exe msg.exe.mui expand\msg.exe.mui
Processing target path msg.exe.mui
msg.exe.mui => expand\msg.exe.mui
File size 2150 bytes
DCS_HEADER found.
NumberOfBlocks 1
UncompressedFileSize 7680
DCS_BLOCK #1
Block->CompressedBlockSize 00000856
Block->DecompressedBlockSize 00001E00
Operation Successful
These decompressed files can now be copied to C:\Windows\System32 and C:\Windows\System32\en-US respectively.
Example:
> msg * Hello, World!

Windows 7 32-bit Program Files path in a Batch file Issue

I have batch file that I am inheriting and I cannot get to work in a 64bit Windows 7 environment. The batch file makes a call to a java script, and passes two variables in it. The old on looked like this:
C:\Progra~1\salesf~1.com\ApexDa~2.0\bin\process.bat C:\Progra~1\*PATH* *VARIABLE*
This was run onm 32bit XP which has just the one program files. I have tried every way I can think of to change the being of the the path to Program fiels x86. I have tried SET PATH, SET ExecPath, %ProgrmaFiles(x86), but they all return cannot find the path specified. I am sure the answer is easy, and I know there is a much beeter way to do this, and it will be changed, but for the moment, I need this to work. Any help, much appreciated.
If you type
dir /x c:\
then this shows the directory listing in the 8.3 format. Program Files expands to PROGRA~1 and Program Files (x86) expands to PROGRA~2. So I think you'll need to change the script to use PROGRA~2
EDIT: I agree with Mark that this isn't ideal -- it depends how much you are able to change of the legacy scripts. On a Win7 machine you should be able to use %ProgramFiles% and %ProgramFiles(x86)% (note the trailing '%').
export JAVA_HOME=/cygdrive/c/Progra~1/java/jdk1.7.0_40/
This worked for me.

Commands Visibility at Command Prompty Not Using System32

Let's say I have a foo.exe file that I want to use it from windows command prompt. I will go to the folder which contains foo.exe and run it. Now, if I want global access for foo.exe from anywhere in the command prompt I will put foo.exe in System32 folder.
This process makes System32 a dump ground. I was wondering if there are any other ways of globally accessing the .exe or bat files without having to dump all of them in System32 folder.
Change your PATH environment variable. i.e. "set path=%path%;[newdir]"
where [newdir] is the new directory you want searched when you run commands.
The PATH Environment Variable
You can either do this programatically (StackOverFlow) or follow these instructions
How to set the path in Windows 2000 / Windows XP, another one.

Resources