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
Related
I know that there are restrictions to file operations, but SpecialFolder.LocalApplicationData is supposed to be for application use.
string _myFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MyFile.txt"); //Line1
Console.WriteLine(_myFilePath); //Line2
Console.WriteLine(File.Exists(_myFilePath)); //Line3
Console.WriteLine(File.Create(_myFilePath)); //Line4
This is the console output:
The program stops at the 4th line and VS 2022 shows this error:
How can I create or delete files/folders in SpecialFolder.LocalApplicationData ? Or which folder is recommended for this kind of file/folder operations?
Using Windows 11, VS 2022 17.2.0 Preview 5.0 and NET 6.0 without administrator privileges:
Your code worked fine for me.
Output:
C:\Users\Edgar\AppData\Local\MyFile.txt
False
System.IO.FileStream
But here is my suggestion:
Check the ACLs of your directory: Is your account permitted for creating new files?
(Right-click the directory -> Properties -> Security -> Select your own user and check your permissions.)
Usually you should not create files directly under your %localappdata% directory.
If you need a temp-file, I would recommend to use Path.GetTempFileName() for getting a unique file name.
If you want to store files for a longer time, then I would recommend to create a directory for your application in %localappdata% and save the files there.
Sample:
string myApplicationDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MyApplication");
string myApplicationFile = Path.Combine(myApplicationDirectory, "myFile.txt");
if (!Directory.Exists(myApplicationDirectory)) {
Console.WriteLine($"Creating directory: {myApplicationDirectory}");
Directory.CreateDirectory(myApplicationDirectory);
}
File.Create(myApplicationFile);
Console.WriteLine($"File created: {myApplicationFile}");
Output:
Creating directory: C:\Users\Edgar\AppData\Local\MyApplication
File created: C:\Users\Edgar\AppData\Local\MyApplication\myFile.txt
I have already switch on the telnet option on control panel - program/features.
Though telnet worked fine manually, but when I run below from my C# library, I am getting this error :
"'telnet' is not recognized as an internal or external command,
operable program or batch file."
This is the code I use to start Telnet:
Process.Start("cmd", "/k telnet")
What makes the difference between this and running it from the command prompt manually and how do I overcome this difference?
Telnet is a program, always installed in the system folder. Which also means, it's always in the path. You don't need to start cmd.exe in order to start telnet.exe. Just use
Process.Start("telnet.exe");
Use the arguments parameter to pass arguments to telnet itself, eg the host, log file etc:
Process.Start("telnet.exe","localhost 80 -f mylog.txt");
There other, probably better options.
Use a Telnet Library
You can use a Telnet library and connect to a server directly, eg using the Telnet NuGet package :
using (Client client = new Client("localhost",80, new System.Threading.CancellationToken()))
{
await client.WriteLine("abcd");
string response = await client.ReadAsync();
Console.WriteLine(response);
}
Use PowerShell
Telnet is often used to test connectivity to a web server, not to actually send commands. In this case, you could use PowerShell's Test-NetConnection to receive diagnostics about the connection:
using System.Management.Automation;
var ps = PowerShell.Create()
.AddCommand("test-netconnection")
.AddArgument("localhost")
.AddParameter("CommonTCPPort", "HTTP");
var results = cmd.Invoke();
foreach (dynamic result in results)
{
Console.WriteLine($"{result.TcpTestSucceeded} {result.SourceAddress}");
}
Make sure you add the correct Powershell NuGet package, Microsoft.PowerShell.5.ReferenceAssemblies, not the unsupported and abandoned System.Management.Automation package
The advantage of PowerShell is that you can chain commands and scripts together just by adding more AddComand, AddScript calls. Each command will receive the output of the previous one. You could use Import-CSV to read a list of servers and ports from a file and pipe the output to Test-NetConnection
On installing Telnet Client via Control Panel - Programs and Features - Turn Windows features on or off there is installed telnet.exe into directory %SystemRoot%\System32.
The directory %SystemRoot%\System32 is for 64-bit applications on 64-bit Windows. Therefore the installed executable telnet.exe is also the 64-bit version. This directory contains also the 64-bit version of cmd.exe.
System environment variable PATH contains %SystemRoot%\System32 which is responsible for finding %SystemRoot%\System32\cmd.exe and %SystemRoot%\System32\telnet.exe when being executed without file extension and without path.
But there is additionally the directory %SystemRoot%\SysWOW64 for 32-bit applications containing the 32-bit versions of the executables.
Microsoft explains with the documentation pages WOW64 Implementation Details and File System Redirector how a file system access to %SystemRoot%\System32 by a 32-bit application is redirected automatically to %SystemRoot%\SysWOW64.
There is no 32-bit version of telnet.exe installed into %SystemRoot%\SysWOW64 on installing Telnet Client.
So what happens on:
Process.Start("cmd", "/k telnet")
When the C# library is compiled as 64-bit library used by a 64-bit application, 64-bit Windows finds and starts %SystemRoot%\System32\cmd.exe which finds and then starts %SystemRoot%\System32\telnet.exe.
But when the C# library is compiled as 32-bit library used by a 32-bit application, 64-bit Windows finds and starts via file system redirector %SystemRoot%\SysWOW64\cmd.exe which cannot find telnet.* with a file extension listed in environment variable PATHEXT in current directory or any directory of environment variable PATH because there is no file telnet.exe in directory %SystemRoot%\SysWOW64.
The best solution is definitely to use a static (or dynamic) telnet library in the C# library to be independent on telnet.exe as suggested by Panagiotis Kanavos. In my point of view it is a shame for every C# programmer using external executables via a process call for which C# code can be quite easily also written by the programmer. Using any world wide web search engine with the search term C# telnet returns lots of pages with solutions, for example C# Telnet Library on Stack Overflow.
Of course it is also possible to get first value of environment variable SystemRoot using GetEnvironmentVariable method to get path to Windows directory, or even better using GetWindowsDirectory or GetSystemWindowsDirectory method.
Then concatenate this string value with "\\System32\\telnet.exe" to a new string and check if the file with that full path exists using File.Exists method. If that file exists on 32-bit Windows with 32-bit version of telnet.exe installed if C# application is also a 32-bit application or on 64-bit Windows with 64-bit telnet.exe installed if C# application is a 64-bit application, then this file name with full path and file extension can be used in a process call.
Otherwise concatenate the Windows directory path with "\\Sysnative\\telnet.exe" and check if file with that full path exists. If this is true on 64-bit Windows with 64-bit version of telnet.exe installed if C# application is a 32-bit application, it would be possible to run from within 32-bit application the 64-bit telnet client executable using this path.
But if that fails also, telnet.exe is not installed at all which is the reason why usage of telnet.exe from within a C# code application is in general not advisable.
Honestly, I don't understand why to have code in a C# library which just starts a command process executing telnet.exe without options and therefore requiring user input and which keeps the command process running after telnet client session terminated. The C# library function can be replaced by a shortcut to telnet.exe on Windows desktop or in Windows start menu of the user.
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
When I'm trying to call this method from windows server 2003 SP2 Enterprise Edition KN x86:
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
I am getting the current directory rather than the program files directory, for example, my application is installed in this location:
C:\Program Files\Company\ApplocationName\SomeApp.exe
When calling:
string x = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
x value will be: C:\Program Files\Company\ApplocationName
Is it a known issue? is there any ideas about this?
Copied from MSDN
"On an x86 system, passing the ProgramFilesX86 member to the Environment.GetFolderPath method returns String.Empty; use the ProgramFiles member instead. You can determine whether Windows is a 32-bit operating system by calling the Environment.Is64BitOperatingSystem property."
So you should use
string x = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
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.