Why is this environment variable always null? - c#

I want to automatically get the directory: user\mydocuments
So I did:
t = Environment.GetEnvironmentVariable(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
But t is null all the time.

The source of the problem is that you are calling Environment.GetEnvironmentVariable when you really don't need to.
Your code successfully obtains the directory path but then you proceeded pass said directory path to GetEnvironmentVariable() which in turn, proceeds to look at the system's environment variables for an environment variable called "user\my_documents". Because no such environment variable exists the function will return null.
Simply do not pass the directory path to GetEnvironmentVariable() and your code should function as expected:
var foo =
Environment.GetFolderPath(Environment.SpecialFolder.Personal);

Related

C# CmdLet binary | add $env:Variable directly on import

i am writing a c# binary cmdlet. at end it should installed on machine for immediate using when starting the ISE or PS-Console without Import-Module.
now i want to provide machine-wide some own $env:Variables like ex. $env:ProgramFiles. how i can do this?
Thanks!
EDIT:
for a more descriptive example here a code sniped:
namespace InstallTools.UpdateEnvironment
{
[Cmdlet(VerbsData.Update, "Environment")]
[OutputType(typeof(UpdateEnvironment))]
public class UpdateEnvironment : PSCmdlet
{
[Parameter(Position = 1,
Mandatory = false,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
ParameterSetName = "ENVIRONMENT")]
public SwitchParameter SetEnvironment { get; set; }
protected override void ProcessRecord()
{
if(SetEnvironment .IsPresent)
{
Environment.SetEnvironmentVariable("CDir", this.MyInvocation.PSScriptRoot);
Environment.SetEnvironmentVariable("CurrentTime", DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss"));
}
}
}
}
if i call in PS Update-Environment -SetEnvironment all the doings will executed. in my case, Environment.SetEnvironmentVariable ("test", "testval") causes an $env:test to be available at runtime.
However, I want the variables to be initialized automatically when the ISE is opened, without calling Update-Environment.
Thanks at all!!
For immediate usage of your module when starting the ISE or PS-Console typing Import-Module you can modify the PSModulePath environment variable.
According to Modifying the PSModulePath Installation Path.
The PSModulePath environment variable stores the paths to the locations of the modules that are installed on disk. PowerShell uses this variable to locate modules when the user does not specify the full path to a module. The paths in this variable are searched in the order in which they appear.
When PowerShell starts, PSModulePath is created as a system environment variable with the following default value: $HOME\Documents\PowerShell\Modules; $PSHOME\Modules on Windows and $HOME/.local/share/powershell/Modules: usr/local/share/powershell/Modules on Linux or Mac, and $HOME\Documents\WindowsPowerShell\Modules; $PSHOME\Modules for Windows PowerShell.
This article also answered the second part of your question :
To add paths to the PSModulePath environement variable, use one of the 3 following methods:
1) To add a temporary value that is available only for the current session, run the following command at the command line:
$env:PSModulePath = $env:PSModulePath + "$([System.IO.Path]::PathSeparator)$MyModulePath"
2) To add a persistent value that is available whenever a session is opened, add the above command to a PowerShell profile file ($PROFILE)>
$profile.AllUsersAllHosts
C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
For more information about profiles, see about_Profiles.
3) To add a persistent variable to the registry, create a new user environment variable called PSModulePath using the Environment Variables Editor in the System Properties dialog box.
To add a persistent variable by using a script, use the .Net method SetEnvironmentVariable on the System.Environment class. For example, the following script adds the C:\Program Files\Fabrikam\Module path to the value of the PSModulePath environment variable for the computer. To add the path to the user PSModulePath environment variable, set the target to "User".
$CurrentValue = [Environment]::GetEnvironmentVariable("PSModulePath", "Machine")
[Environment]::SetEnvironmentVariable("PSModulePath", $CurrentValue + [System.IO.Path]::PathSeparator + "C:\Program Files\Fabrikam\Modules", "Machine")

Getting TeamCity (Docker Linux) parameters or system properties in Cake (C#) returns nothing

I'm trying to access the branch name in Cake on TeamCity running inside a Linux Docker container, but whenever I try to fetch any of the "Configuration Parameters", the values are returning nothing.
In my branch, the following build parameter values are visible on TeamCity:
Configuration parameters
vcsroot.branch: refs/heads/master
teamcity.build.branch: 5/merge
Environment variables
env.vcsroot.branch: 5/merge
The env.vcsroot.branchvariable has a value of %teamcity.build.branch%.
My cake script simply tries to spit out the values, and all of the ones below are coming back empty:
var branch = EnvironmentVariable("vcsroot.branch");
var tcbranch = EnvironmentVariable("teamcity.build.branch");
var agent = EnvironmentVariable("system.agent.name");
var confName = EnvironmentVariable("system.teamcity.buildConfName");
var buildId = EnvironmentVariable("teamcity.build.id");
var vcsRootBranch = EnvironmentVariable("vcsroot.Root_TemplatedVcsRoot1.branch");
var argOrEnv = ArgumentOrEnvironmentVariable("teamcity.build.branch", "vcsroot.branch", "Unfound");
Information($"vcsroot.branch = {branch}");
Information($"teamcity.build.branch = {tcbranch}");
Information($"system agent name = {agent}");
Information($"system TC build cof name= {confName}");
Information($"param buildId = {buildId}");
Information($"vcsroot template branch = {vcsRootBranch}");
Information($"test argument or env variables = {argOrEnv}");
The actual output:
[12:34:51][Step 1/2] vcsroot.branch =
[12:34:51][Step 1/2] teamcity.build.branch =
[12:34:51][Step 1/2] system agent name =
[12:34:51][Step 1/2] system TC build cof name=
[12:34:51][Step 1/2] param buildId =
[12:34:51][Step 1/2] vcsroot template branch =
[12:34:51][Step 1/2] test argument or env variables = Unfound
Oddly enough, on our non-docker Windows-based TeamCity agents, the values seem to return fine. I have a feeling I'm missing something here that's painfully simple, but I'm a relative novice when it comes to Cake, TeamCity, and Docker. Any help would be greatly appreciated. Thanks!
Edit: to claify, most of the environment variables are coming back as expected; the only one that I've noticed that doesn't is the one that references a configuration parameter.
For Environment variables TeamCity replaces non alpha numeric characters with "_"
I.e vcsroot.branch becomes vcsroot_branch
I figured it out...
First off, I missed the subtext on the TC project parameters page for Configuration Parameters; it states Configuration parameters are not passed into build, can be used in references only.
Secondly, I didn't realize that none of the System Properties were visible (don't know if that's an issue), but its subtext also states System properties will be passed into the build (without system. prefix), they are only supported by the build runners that understand the property notion.
Therefore, in order to get the Configuration Parameter value, I needed to create an Environment Variable using the Configuration Parameter as it's value:
env.TCBranch = %teamcity.build.branch%
It was a little unsettling that teamcity.build.branch didn't show up in the type-ahead when specifying the value, but it works.
This begs the question about why the Environment Value of env.vcsroot.branch didn't work, and I presume it's because the name of the variable is identical to a different Configuration Variable name. Considering these parameters aren't passed into the build, I don't see why that should matter, but I can't think of why else it wouldn't work. Anyway, thanks to #devlead for the suggestions (above).

C# Environment variable value doesn't get added [duplicate]

This question already has an answer here:
How to set system environment variable in C#?
(1 answer)
Closed 7 years ago.
I'm trying to add a value to the Path environment variable, but I can't seem to get it to work. I've went through a couple of similar questions and I'm pretty sure I have exactly the same code, but still it won't add the variable or I can't see it. I've checked both the administrator and local user account for changes. I've checked both during and after the running (debugging) of the application. I've also close VS2013 completely and checked.
Here's the code I'm using
string path = #"C:\Users\bono\Documents\Visual Studio 2013\Projects\3D-Scanner\AddEnviromentToPath\bin\Debug\AddEnviromentToPath.exe";
ProcessStartInfo process_start_info = new ProcessStartInfo();
process_start_info.FileName = path;
process_start_info.Verb = "runas";
process_start_info.WindowStyle = ProcessWindowStyle.Normal;
process_start_info.UseShellExecute = true;
process_start_info.Arguments = PATH_TO_PCL;
Process.Start(process_start_info); //Process that handles the adding of the value
AddEnviromentToPath program:
class Program {
static void Main(string[] args) {
//Just to make sure we're adding both
AddToEnvironmentPath(args[0], EnvironmentVariableTarget.User);
AddToEnvironmentPath(args[0], EnvironmentVariableTarget.Machine);
}
static void AddToEnvironmentPath(string pathComponent, EnvironmentVariableTarget target) {
string targetPath = System.Environment.GetEnvironmentVariable("Path", target) ?? string.Empty;
if (!string.IsNullOrEmpty(targetPath) && !targetPath.EndsWith(";")) {
targetPath = targetPath + ';';
}
targetPath = targetPath + pathComponent;
Environment.SetEnvironmentVariable("Path", targetPath, target);
}
}
Note that I'm running VS2013 and the main application as a standard user. When the AddEnviromentToPath program runs I get an admin verification panel. I log in here with an admin account.
Edit:
Other people seem to get it working with basically the same code:
How do I get and set Environment variables in C#?
Environment is not being set in windows using c#. Where am I going wrong?
Assuming that Environment.SetEnvironmentVariable calls the Win32 SetEnvironmentVariable function behind the scenes, this note is probably applicable:
Sets the contents of the specified environment variable for the
current process
...
This function has no effect on the system
environment variables or the environment variables of other processes.
If you want to change a global environment variable and have existing processes notice it, you need to:
Save it to the registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
Notify existing processes of the change with the WM_SETTINGCHANGE message.
See the MSDN Environment Variables documentation for more information.
ProcessStartInfo to the rescue!
You need to check this documentation out:
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.environmentvariables%28v=vs.110%29.aspx
The key text which addresses your concerns:
Although you cannot set the EnvironmentVariables property, you can
modify the StringDictionary returned by the property.

writing environment variable and reading it from the same process

I am trying to set environment variable from a console application by executing it from my windows application. I invoke console application and send the value of environment variable as parameter to it, then set the thread to wait for 10 seconds to proceed with next execution.
In the next step i try to load a new .exe which reads the value set to the environment variable.
The exe will not read the new value and continue to refer the value set earlier.
Once the solution of application is closed and open then it reads the new value i.e reload the vshost.
betting you set up the variable only for the current process. You should try this overload of the Environment.SetEnvironmentVariable method :
Environment.SetEnvironmentVariable("YourVar", "YourValue",
EnvironmentVariableTarget.User);
[Edit] Re-Reading your question, you said in the title "same process", and in the question "new exe". In term of Env varialble, spanning a new process implies a new process scope for env variables. They won't share env variables with process scope just because it's the same executable. Maybe you should explain what you are trying to do at a higher level.
[Edit2] not sure to understand why it fails... But you can specify env variable when spawning process using a ProcessStartInfo.EnvironmentVariables Property
Basically, it can be (not tested) :
var psi = new ProcessStartInfo {
FileName="yourExe"
};
psi.EnvironmentVariables.Add("YourVariable","YourValue");
var process = Process.Start(psi);

Get directory where executed code is located

I know that in the same directory where my code is being executed some files are located. I need to find them and pass to another method:
MyLib.dll
Target1.dll
Target2.dll
Foo(new[] { "..\\..\\Target1.dll", "..\\..\\Target2.dll" });
So I call System.IO.Directory.GetFiles(path, "*.dll"). But now I need to get know the path:
string path = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName)
but is there more short way?
You may try the Environment.CurrentDirectory property. Note that depending on the type of application (Console, WinForms, ASP.NET, Windows Service, ...) and the way it is run this might behave differently.
Environment.CurrentDirectory returns the current directory, not the directory where the executed code is located. If you use Directory.SetCurrentDirectory, or if you start the program using a shortcut where the directory is set this won't be the directory you are looking for.
Stick to your original solution. Hide the implementation (and make it shorter) using a property:
private DirectoryInfo ExecutingFolder
{
get
{
return new DirectoryInfo (
System.IO.Path.GetDirectoryName (
System.Reflection.Assembly.GetExecutingAssembly().Location));
}
}

Categories