Windows 7 Environment Variable for System32 or SysWOW64 - c#

Is there an environment variable to directly access System32 or SysWOW64 folder, respectively, in Windows 7 32bit or 64bit?
I know of a workaround by using %WINDIR%\System32 which is not working for me.
I have to re-compile an EXE that refers to some OCX that should be registered in System32 folder. The problem I am facing is that I have to install it in a 64bit system where the OCX got registered in SysWOW64 folder and not getting registered in System32 folder.
What should I try? Thanks for your help!
Edit:
I figured out that the solution has a reference to a dll which refers to flash10h.ocx. For this flash10h.ocx has to be registered. I could get it registered in SysWOW64 folder but not in System32. My system already has a flash player v11.xx. Will this not work?
Please help!

The following method will retrieve the path to the 32-bit system directory and, optionally, place it in the environment variable SYSDIR32.
public static String Get32BitSystemDirectory (Boolean placeInEnvironmentVariable = true)
{
String sysDir = "";
if (Environment.Is64BitOperatingSystem) sysDir = Environment.ExpandEnvironmentVariables("%windir%\\SysWOW64");
else sysDir = Environment.ExpandEnvironmentVariables("%windir%\\System32");
if (placeInEnvironmentVariable) Environment.SetEnvironmentVariable("SYSDIR32", sysDir, EnvironmentVariableTarget.User);
return sysDir;
}

Related

What is the odbcjt32.dll real path, System32 or SysWOW64 to check it's parameters

I'm trying to create a ODBC connection programmatic, via registry.
When using Windows ODBC tool, I noticed that for ODBC 32, "Microsoft Access Driver (*.mdb)" is using odbcjt32.dll and the entry in registry would point to this location:
"Driver"="C:\\Windows\\system32\\odbcjt32.dll"
But when I search for the file, it exists, but is located in other folder:
C:\Windows\SysWOW64
I need to know why because:
I need to create connection from C#, I presume I should put the entry like ODBC tool does, to C:\Windows\system32
I want to check this DLL version from C#, so I should check C:\Windows\SysWOW64\odbcjt32.dll ??
There is a magic redirection for this DLL in Windows ?
Thanks for clarification,
See the super user question "System32 and SysWOW64 on Windows 7" for some background info on SysWoW64 and system32. So yes, there is a "magic redirection" on windows for 32 bit and 64 bit DLLs.
The file odbcjt32.dll in C:\Windows\SysWOW64 is a 32 bit version. The path C:\Windows\system32\ is redirected to C:\Windows\SysWOW64\ for a 32 bit program. What is the current solution platfrom of your program? x86, x64 or Any CPU? I think it should be x86 so that it can use the 32 bit driver.
Take a look at Environment.GetFolderPath method with Environment.SpecialFolder.SystemX86 so that you do not need to hardcode the path.
Additional info on the magic redirection
To see the bitness of a DLL you can use dumpbin.I use "odbc32.dll" in my examples below. Open the Developer Command Prompt of your Visual Studio version and execute the following command:
dumpbin /headers c:\windows\syswow64\odbc32.dll
The output will contain the following line:
FILE HEADER VALUES
14C machine (x86)
Now execute dumpbin for the DLL in the system32 directory:
dumpbin /headers c:\windows\system32\odbc32.dll
which outputs
FILE HEADER VALUES
8664 machine (x64)
As you can see there is a x64 ("64 bit") and a x86 ("32 bit") version of the same DLL on the machine. Windows does the magic redirection depending on the bitness of the program that is running. A 64 bit program gets the DLL from C:\Windows\system32 and a 32 bit program gets it from C:\Windows\SysWoW64.
But why create a DSN?
You can do this:
string MyCon = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};dbq=C:\\Test2\\test44.accdb";
DataTable MyTable = new DataTable();
OdbcDataAdapter MyData = new OdbcDataAdapter("select * from tblHotels", MyCon);
MyData.Fill(MyTable);
MessageBox.Show("Records = " + MyTable.Rows.Count.ToString() );
We only need:
using System.Data;
using System.Data.Odbc;
I mean, your utility might be wanting to create a DSN, but if you just looking to create a connection, then the above is fine. As long as ACE32, or ACE 64 bit version is installed, then this will work.
Note that odbcjt32.dll is a x32 bit ONLY component. You will never find or see a x64 bit version - it don't exist. And installing ACE x64 will not install that .dll either.
However, it not clear why you need to create the DSN connection as opposed to having a setting in your application (or some setup file) that simply has the above connection string? Attempting to create a DSN will often require elevated rights, but in place of the DSN you can use a simple connection string for ODBC as per above. There is no speical references required for the above code snip to work - it just uses the ODBC parts built into the net framework.

C# + LibreOffice SDK

I am developing a desktop application in .NET (C# + WPF) and my machine works correctly, I can make the LibreOffice call, open a file and customize the interface all through my .NET application, but in order to work, it is necessary the version of the SDK is the same as that of LibreOffice installed on the machine, and the architecture of the application should be the same as that of LibreOffice (32 or 64 bits).
To work the integration, I had to add in the references of my project the DLLs that comes along with the SDK:
cli_basetypes.dll
cli_cppuhelper.dll
cli_oootypes.dll
cli_ure.dll
cli_uretypes.dll
So at first all right, but my question is this: I developed the application using LibreOffice 6.1 along with the SDK of the same version and now I need the application to run on another machine with a lower version of LibreOffice, which I can not currently get, with the following error occurring:
System.IO.FileNotFoundException: Could not load file or assembly 'cli_cppuhelper.dll' or one of its dependencies. The specified module could not be found.
Is it possible to run the application on another machine with a different version of LibreOffice? How? Also, is it possible to avoid errors because the application is developed in 64bit and LibreOffice installed is 32bit for example?
After many attempts I was able to solve the problem.
It was necessary to override the AssemblyResolve event to fetch the LibreOffice DLLs from the GAC (C:\Windows\Microsoft.NET\assembly).
In addition the application must run with the same LibreOffice architecture installed so it was necessary to generate two executables, one 32bits and another 64bits (checking/unchecking the "32-bit Preferred" project property) so that the AssemblyResolve event finds the right DLL in GAC.
Another necessary change was necessary to set in the environment variable "UNO_PATH" that can be found in the Windows registry;
string unoPath = "";
RegistryKey hkcuView32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.CurrentUser, RegistryView.Default);
RegistryKey hkcuUnoInstallPathKey = hkcuView32.OpenSubKey(#"SOFTWARE\LibreOffice\UNO\InstallPath", false);
if (hkcuUnoInstallPathKey != null && hkcuUnoInstallPathKey.ValueCount > 0)
{
unoPath = (string)hkcuUnoInstallPathKey.GetValue(hkcuUnoInstallPathKey.GetValueNames()[hkcuUnoInstallPathKey.ValueCount - 1]);
}
else
{
RegistryKey hklmView32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
RegistryKey hklmUnoInstallPathKey = hklmView32.OpenSubKey(#"SOFTWARE\LibreOffice\UNO\InstallPath", false);
if (hklmUnoInstallPathKey != null && hklmUnoInstallPathKey.ValueCount > 0)
{
unoPath = (string)hklmUnoInstallPathKey.GetValue(hklmUnoInstallPathKey.GetValueNames()[hklmUnoInstallPathKey.ValueCount - 1]);
}
}
Environment.SetEnvironmentVariable("UNO_PATH", unoPath, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + #";" + unoPath, EnvironmentVariableTarget.Process);
After this steps, my application worked perfectly!

find the installation path (with exe file there but not currently running) in win 7 from C# VS2013

From C# VS2013, I would like to get the whole path of an application that has been indtalled on win 7.
The post with 7 methods at:
http://stackoverflow.com/questions/6041332/best-way-to-get-application-folder-path
cannot help me because I do Not need the path of the current running application.
I need the path of an application that has been installed (but currently not running).
I have tried
string [] allfiles = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
at
http://stackoverflow.com/questions/23736343/recursive-search-for-files-in-root-directory-and-subfolders
But got:
Additional information: Access to the path 'C:\Program Files\MSSomeApp\DATA' is denied.
My C# code:
FileInfo executableFileInfo = new FileInfo("MyApplication.exe"); // It has been installed on win 7.
string executableDirectoryName = executableFileInfo.DirectoryName;
This just returned my current VS2013 working directory. But, actually, "MyApplication.exe" was installed at C:\MyPath.
I need to get the full file path C:\MyPath\, where all libs and exe files (of MyApplication) are there.
Any suggestions ? thanks
Well You can use something like:
string[] paths =
System.IO.Directory.GetFiles(System.Environment.SpecialFolder.ProgramFiles,
"MyApplication.exe", System.IO.SearchOption.AllDirectories);
This will look the Program Files Folder and all its Sub Folders for the file named MyApplication.exe and will return the full path of all of matches

File exists in Windows Explorer and notepad, but is not accessable in my program

Why does the following problem happen?
Scenario:
Make sure that IIS is installed
Execute "notepad
%WINDIR%\System32\inetsrv\config\applicationHost.config" using admin
account
Actual Result: the file is successfully opened in notepad
Execute the following code in admin account's context:
string filePath = #"%WINDIR%\System32\inetsrv\config\applicationHost.config";
Console.WriteLine(File.Exists(Environment.ExpandEnvironmentVariables(filePath)));
Actual Result: False
Expected Result: True
The problem is if you are running a 32-bit application on a 64-bit OS, the .Net framework automatically redirects the request from %WINDIR%\System32 to %WINDIR%\SysWOW64.
If you change your project to target 64-bit, this will solve your problem.
You can also resolve the problem by changing System32 to sysnative, but only if you leave the application as a 32-bit app:
string filePath = #"%WINDIR%\sysnative\inetsrv\config\applicationHost.config";
This might be due to file system redirection. AFAIK t happens either for 32/64 bit mismatch or in case of low-privilege (UAC) processes.
I know of now way of disabling that behavior using managed APIs. You need to use http://msdn.microsoft.com/en-us/library/windows/desktop/aa365743(v=vs.85).aspx and/or be a high privilege process.
If you change your project to target 64-bit, this is likely to solve your problem.
I can't reproduce your result. When I run this from an administrator command line prompt, I get exists = True.
string s = #"%WINDIR%/System32\inetsrv\config\applicationHost.config";
bool exists = File.Exists(Environment.ExpandEnvironmentVariables(s));
Console.WriteLine("exists = {0}", exists);
I'm running Windows Server 2008, 64-bit. .NET 4.0.

Getting the path of the home directory in C#?

Okay, I've checked Environment.SpecialFolder, but there's nothing in there for this.
I want to get the home directory of the current user in C#. (e.g. c:\documents and settings\user under XP, c:\users\user under Vista, and /home/user under Unix.)
I know I can read enviroment variables to find this out, but I want to do this in a cross-platform way.
Is there any way I can do this with .NET (preferably using mscorlib)?
UPDATE: Okay, this is the code I ended up using:
string homePath = (Environment.OSVersion.Platform == PlatformID.Unix ||
Environment.OSVersion.Platform == PlatformID.MacOSX)
? Environment.GetEnvironmentVariable("HOME")
: Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%");
You are looking for Environment.SpecialFolder.UserProfile which refers to C:\Users\myname on Windows and /home/myname on Unix/Linux:
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
Note that Environment.SpecialFolder.Personal is My Documents (or Documents in win7 and above), but same as home directory on Unix/Linux.
Environment.SpecialFolder.Personal doesn't actually return the home folder, it returns the My Documents folder. The safest way to get the home folder on Win32 is to read %HOMEDRIVE%%HOMEPATH%. Reading environment variables is actually very portable to do (across Unix and Windows), so I'm not sure why the poster wanted to not do it.
Edited to add: For crossplatform (Windows/Unix) C#, I'd read $HOME on Unix and OSX and %HOMEDRIVE%%HOMEPATH% on Windows.
I believe what you are looking for is:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)
For reference, it is infact contained in mscorlib.
In DotNetCore 1.1 System.Environment.SpecialFolder does not exist. It might exist in 2.0-beta. Until then, to do this you can use the following:
var envHome = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "HOMEPATH" : "HOME";
var home = Environment.GetEnvironmentVariable(envHome);`
The bottom line answer is No. The is no simple System based method in .NET to get the Home directory such that we could expect an implementation in both .NET on Windows and in Mono.
You will need to do some OS detection and branch to OS specific code.
When you say cross-platform way, what other OSs do you need to support? You may need to do some simple OS detection to select the method for finding the home directory if you're running on a non-Windows OS.
This website seems to give a way to do what you need in Windows.
This can be done using GetEnvironmentVariable in System.IO:
public string GetUserHome() {
var homeDrive = Environment.GetEnvironmentVariable("HOMEDRIVE");
if (!string.IsNullOrWhiteSpace(homeDrive))
{
var homePath = Environment.GetEnvironmentVariable("HOMEPATH");
if (!string.IsNullOrWhiteSpace(homePath))
{
var fullHomePath = homeDrive + Path.DirectorySeparatorChar + homePath;
return Path.Combine(fullHomePath, "myFolder");
}
else
{
throw new Exception("Environment variable error, there is no 'HOMEPATH'");
}
}
else
{
throw new Exception("Environment variable error, there is no 'HOMEDRIVE'");
}
}
Then it produces under windows: C:\\\\Users\\myusername\\myFolder
Note that if you use
var fullHomePath = Path.Combine(homeDrive.ToString(), homePath.ToString())
it fails because it produces: \\Users\\myusername\\myFolder
I don't have a machine to test it on, but %HOMESHARE% might work for you. Otherwise, here's a pretty good list of environment variables.
Just for future reference, the list of pre-defined variables in Windows 10, taken from Windows 10 default environment variables.
VARIABLE
WINDOWS 10
%ALLUSERSPROFILE%
C:\ProgramData
%APPDATA%
C:\Users{username}\AppData\Roaming
%CD%
Current directory full path.(cmd only)
%CMDCMDLINE%
Returns exact command line used to start current cmd.exe session.(cmd only)
%CMDEXTVERSION%
Number of current command processor extensions.(cmd only)
%CommonProgramFiles%
C:\Program Files\Common Files
%CommonProgramFiles(x86)%
C:\Program Files (x86)\Common Files
%CommonProgramW6432%
C:\Program Files\Common Files
%COMPUTERNAME%
The computer name of the current local system.
%COMSPEC%
C:\Windows\System32\cmd.exe
%DATE%
Current date in format determined by Date command.(cmd only)
%ERRORLEVEL%
Number defining exit status of previous command or program.(cmd only)
%HOMEDRIVE%
C:|
%HOMEPATH%
C:\Users{username}
%LOCALAPPDATA%
C:\Users{username}\AppData\Local
%LOGONSERVER%
\{domain_logon_server}\MicrosoftAccount
%NUMBER_OF_PROCESSORS%
8
%OS%
Windows_NT
%PATH%
C:\Windows;C:\Windows\System32;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0
%PathExt%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
%PROCESSOR_ARCHITECTURE%
AMD64
%PROCESSOR_IDENTIFIER%
Intel64 Family 6 Model 158 Stepping 9, GenuineIntel
%PROCESSOR_LEVEL%
6
%PROCESSOR_REVISION%
9e09
%PROGRAMDATA%
C:\ProgramData
%PROGRAMFILES%
C:\Program Files
%ProgramW6432%
C:\Program Files
%PROGRAMFILES(X86)%
C:\Program Files (x86)
%PROMPT%
Code for current command prompt format.Code is usually $P$G(cmd only)
%PSModulePath%
C:\Windows\system32\WindowsPowerShell\v1.0\Modules|
%PUBLIC%
C:\Users\Public
%RANDOM%
To get random number between 0 and 32767.(cmd only)
%SessionName%
When logging on directly to machine, returns "Console".When client connects via terminal server session, is combinationof connection name, followed by pound symbol {#} and session number.
%SystemDrive%
C:
%SystemRoot%
C:\Windows
%TEMP%
C:\Users{username}\AppData\Local\Temp
%TMP%
C:\Users{username}\AppData\Local\Temp
%TIME%
Current time in format determined by Time command.(cmd only)
%USERDOMAIN%
The network domain name associated with the current user.
%USERDOMAIN_ROAMINGPROFILE%
The network domain name associated with the current roaming profile.
%USERNAME%
{username}
%USERPROFILE%
C:\Users{username}
%WINDIR%
C:\Windows

Categories

Resources