I'm using:
FileInfo(
System.Environment.GetFolderPath(
System.Environment.SpecialFolder.ProgramFiles)
+ #"\MyInstalledApp"
In order to determine if a program is detected on a users machine (it's not ideal, but the program I'm looking for is a right old kludge of a MS-DOS application, and I couldn't think of another method).
On Windows XP and 32-bit versions of Windows Vista this works fine. However, on x64 Windows Vista the code returns the x64 Program Files folder, whereas the application is installed in Program Files x86. Is there a way to programatically return the path to Program Files x86 without hard wiring "C:\Program Files (x86)"?
The function below will return the x86 Program Files directory in all of these three Windows configurations:
32 bit Windows
32 bit program running on 64 bit Windows
64 bit program running on 64 bit windows
static string ProgramFilesx86()
{
if( 8 == IntPtr.Size
|| (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
{
return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
}
return Environment.GetEnvironmentVariable("ProgramFiles");
}
If you're using .NET 4, there is a special folder enumeration ProgramFilesX86:
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
Environment.GetEnvironmentVariable("PROGRAMFILES(X86)") ?? Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
Note, however, that the ProgramFiles(x86) environment variable is only available if your application is running 64-bit.
If your application is running 32-bit, you can just use the ProgramFiles environment variable whose value will actually be "Program Files (x86)".
One way would be to look for the "ProgramFiles(x86)" environment variable:
String x86folder = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
I am writing an application which can run on both x86 and x64 platform for Windows 7 and querying the below variable just pulls the right program files folder path on any platform.
Environment.GetEnvironmentVariable("PROGRAMFILES")
One-liner using the new method in .NET. Will always return x86 Program Files folder.
Environment.Is64BitOperatingSystem ? Environment.GetEnvironmentVariable("ProgramFiles(x86)") : Environment.GetEnvironmentVariable("ProgramFiles"))
C# Code:
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
Output:
C:\Program Files (x86)
Note:
We need to tell the compiler to not prefer a particular build platform.
Go to Visual Studio > Project Properties > Build > Uncheck "Prefer 32 bit"
Reason:
By default for most .NET Projects is "Any CPU 32-bit preferred"
When you uncheck 32 bit assembly will:
JIT to 32-bit code on 32 bit process
JIT to 32-bit code on 64 bit process
Related
I am facing very strange issue:
I got a 64 bit c#.net application on 64 bit Windows Server 2008 R2 machine and it is being invoked by a Windows Service and it is started under Local System User, Moreover,this 64 bit c#.net application launches 32 bit java application and this java application has application data folder to C:\Windows\SysWOW64\config\systemprofile\AppData. 64 bit c#.net application has app data folder to C:\Windows\System32\config\systemprofile\AppData
So for 32 bit application app data folder is (in case of Local system User):-C:\Windows\SysWOW64\config\systemprofile\AppData
and for 64 bit application app data folder is(in case of Local system User):-C:\Windows\System32\config\systemprofile\AppData
Please Note: this is not typing mistake that they refer to opposite folders(it is a decision by microsoft for 64 bit OS), you can read https://msdn.microsoft.com/en-us/library/aa384187.aspx for detailed explanation.
Now, I need to write few files to 32 bit app data folder from 64 bit application as these files would be used by 32 bit java application.
So, I need to know How I can get 32 bit app data folder from 64 bit application using c#.net.
Important Note: this issue would be faced when application is launched under local system user (i.e. application has been launch by window services) and there won't be any issue when a user explicitly launches the application beacause in this case,user app data folder would be same for 64 bit and 32 bit application.
You first check if you actually are running inside of a 64 bit process on a 64 bit OS. And if so, you construct the path yourself. Otherwise you can just retrieve the system path and append your target path.
String path;
//detect if the current application is 64 bit and running on a 64 bit system
//NOTE: needs .NET Framework 4 to work
if (Environment.Is64BitOperatingSystem && Environment.Is64BitProcess)
{
path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysWOW64");
}
else
{
path = Environment.GetFolderPath(Environment.SpecialFolder.System);
}
//append your target path
path = Path.Combine(path, #"config\systemprofile\AppData");
Please note that using EnvironmentIs64BitOperatingSystem and Environment.Is64BitProcess requires at least .NET-Framework 4.
The simplest solution is to rebuild the C# application as 32-bit, or to use 64-bit Java.
If you can't do either, create a 32-bit application that does nothing but look up the application data path, and run it from your C# application. The 32-bit application could be written in C, C#, or Java.
Are you using "shortcut" keyword to point appdata directory, eg %APPDATA%? Could you use a direct path, eg #"C:\Users\%username%\AppData\Local"
This is the same answer as #2 above (via Sebastian Baumhekel), with some errors corrected. I am on Win 7 and have the same issue. As some have pointed out this may not be future OS safe... However it solves my current issue.
The issue is on 64bit Win7 when you run a 32bit Windows Service as Local System user and ask for this folder:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
It returns the 64bit version (with System32):
C:\Windows\System32\config\systemprofile\AppData\
Main point of clarification (as OP states):
SysWOW64 gets 32bit application data...
System32 gets 64bit application data...
This from OP link:
https://learn.microsoft.com/en-us/windows/desktop/WinProg64/file-system-redirector
I just wasted 4 hours of my life getting to the bottom of this so I wanted to clarify!
public 32bitWindowsServiceOn64bitWindows()
{
// Note: this service is configured to run as "Local System" user...
string appdata;
// need to do this, because this runs as Local System user...
// which gets the wrong SpecialFolder.ApplicationData (ie, System32 for 64bit apps) should be SysWOW64 (for 32bit apps)
if (Environment.Is64BitOperatingSystem && Environment.Is64BitProcess)
{
// the application is a 64 bit app
appdata = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "System32");
}
else
{
// the application is a 32 bit app
appdata = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysWOW64");
}
// Append your target path. Do you want Local or Roaming?
appdata = Path.Combine(appdata, #"config\systemprofile\AppData\Roaming\MyApp");
//appdata = Path.Combine(appdata, #"config\systemprofile\AppData\Local\MyApp");
...
I'm working on a 64 bits application coded with .Net 4.0, C#.
In this application, at some point, I need to start another exe file using the following code :
l_process.StartInfo.FileName = _sFullFilePath;
l_process.StartInfo.Verb = "Open";
l_process.StartInfo.CreateNoWindow = true;
l_process.StartInfo.Arguments = l_sParams;
l_process.Start();
Now, this external application being compiled under 32 bits environment (x86), I get the following error :
**The specified executable is not valid for this OS platform**
Is it even possible to do so ? If yes, how can I manage to start this application from mine without having troubles ?
Usually, no extra work is required to run a 32-bit program on 64-bit machine.
Try to run 32-bit program individually.
Read this: http://www.techsupportalert.com/content/how-windows7-vista64-support-32bit-applications.htm
I'm running a Windows 7 x64 machine when I do not compile for x64 I get an exception and my ListView just get populated with the first two non x64 processes.
That is I cannot access MainModule Property of a 64 bit process to get it's full path.
foreach(Process p in listaProcessi)
{
tempItem = new ListViewItem(p.Id.ToString());
tempItem.SubItems.Add(p.ProcessName);
tempItem.SubItems.Add(p.MainModule.FileName);
processiListView.Items.Add(tempItem);
}
I still can make it work compiling for x64 but suppose I want to compile just for x86, how do I avoid getting the excpetion ?
1) Is there any other way to discover those processes path ?
2) I could write a line like "You cannot get x64 Process path from x86 App", but still I don't have to run into the exception. How do I prevent this ? Can I check the process for a particular info so I can replace the text and avoid accessing MainModule ?
Thanks.
A 32 bit processes cannot access modules of a 64 bit process.
So it must be compiled for AnyCpu to be fully working in both x86 and x64 environments.
I have two applications running on W2k8 R2 x64, one is compiled as 64bit and the other one as 32bit as it has COM dependencies.
In both I'm trying to call:
Process p = Process.Start("telnet.exe", string.Format("{0} {1}", address, port));
In the x64 it works perfectly fine, however in the 32bit one I get a System.ComponentModel.Win32Exception ("The system cannot find the file specified")?
Any idea what's going on here? Even if I call
Process.Start(#"C:\Windows\System32\telnet.exe")
I get the same exception?
Thanks,
Tom
To launch a system32 located 64bit app from a 32bit app (at least on Vista,2k8,7, doesn't work on x64 XP or 2k3) run it from the sysnative directory, i.e. "C:\windows\sysnative\telnet.exe" (alternatively disable Wow64 but that is generally a bad idea).
This drove me crazy... had one project that would find "telnet.exe" without the full path and one that refused to find it (even with the path, or never figured it out). My dev machine is 64-bit.
The problem was the target platform in build.
If it's set to x86 it will not find telnet.
set it to Any CPU it will find telnet.
sometimes you need to set it to x86, this allows your applications to see 32-bit drivers (such as odbc drivers) on 64-bit platforms
Windows Server 2008 does not have a 32 bit telnet.exe client. It only installs a 64bit version in the windows\system32 folder.
\live.sysinternals.com\tools\procmon.exe and/or procexp always has the answer.
Have you looked at the path environment variable in the context of your process? Can you prefix it with the System\SysWow64 path to make it work?
copy telnet.exe to SysWow64 folder
How can I make my compilation optimized for Windows 64 bit?
You might also want to do a check at runtime, just to be sure:
using System;
using System.Runtime.InteropServices;
class SystemChecker
{
static bool Is64Bit
{
get { return Marshal.SizeOf(typeof(IntPtr)) == 8; }
}
}
A managed project is automatically built according to the architecture selected => default C# project created on AMD64 will be AMD64, X86 on X86. The native one is always 32-bit by default.
To explicitly set a platform:
1 open the solution explorer, select solution, right click->Configuration Manager.
2 go to 'Active Solution Platform', click New.
3 in the 'New Solution Platform' dialog that comes up select the new platform say Itanium. Set 'Copy Settings From' to 'Any CPU' which was the default setting in the 'Active Solution Platform'.
4 click OK.
This is from WebLog
As Patrick Desjardins said, with a little addition.
Beware if you have third party DLL which uses Interop and is compiled with 32 bit. In that case, you will specifically have to set all your assemblies which uses it to use x86 or all manner of weird things will happen.
You can compile for 64bit through the /platform-flag. Note that visual studio Express has no straightforward 64bit compile setting.
See here for more information, and here. Taken from the second source is the following information:
On a 64-bit Windows operating system:
Assemblies compiled with /platform:x86 will execute on the 32 bit CLR running under WOW64.
Executables compiled with the /platform:anycpu will execute on the 64 bit CLR.
DLLs compiled with the /platform:anycpu will execute on the same CLR as the process into which it is being loaded.
Runtime Check:
You can check the execution bit environment at runtime through one of the following options
bool is64BitProcess = IntPtr.Size == 8;
int bitProcess = IntPtr.Size*8;
//C# 4 provides System.Environment.Is64BitProcess
//TimothyP's solution:
bool is64BitProcess = Marshal.SizeOf(typeof(IntPtr)) == 8;