append to path for all users in windows programmatically. - windows

I am appending to windows path in chef but it only reflects for administrator (uses to administrator to append to path)
# append dnx.exe to %PATH%
windows_path '%USERPROFILE%\\.dnx\\runtimes\\dnx-coreclr-win-x64.1.0.0-rc1-update1\\bin' do
action :add
end
Is there a command to append to path and make it available for all users of windows programmatically ?

I don't have experience with Chef, but the canonical way to add something to the PATH environment variable for all users is to append it to the variable in the machine environment rather than the user environment. In PowerShell you do it like this:
$path = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
$path += ';%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x64.1.0.0-rc1-update1\bin'
[Environment]::SetEnvironmentVariable('PATH', $path, 'Machine')
If you want to merge that into a single statement it'd look somewhat like this:
[Environment]::SetEnvironmentVariable('PATH', ([Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x64.1.0.0-rc1-update1\bin'), 'Machine')
However, you may not want to simply append to the variable, as that might keep adding the path to the variable over and over again. To avoid that you could do something like this:
$dir = '%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x64.1.0.0-rc1-update1\bin'
$path = [Environment]::GetEnvironmentVariable('PATH', 'Machine') -split ';' |
Where-Object { $_ -ne $dir }
$path += $dir
[Environment]::SetEnvironmentVariable('PATH', ($path -join ';'), 'Machine')
Edit: I just realized that [Environment]::SetEnvironmentVariable() can't be used in your case. While the method will set the variable to the string you pass into it, that string will be stored as a REG_SZ value in the registry. Which will prevent variables inside the string (like %USERPROFILE%) from being expanded when the path is looked up, kinda making the whole thing pointless.
To avoid this pitfall you must ensure that the path is stored in a REG_EXPAND_SZ value, e.g. like this:
$regkey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
Set-ItemProperty -Path $regkey -Name 'Path' -Value $path -Type ExpandString

Related

Adding directory to Systemvariables Path in CMD

Iam trying to add a directory permanently to Path via CMD. When i try to use the command:
setx path "%path%;C:\Program Files (x86)\chromedriver\chromedriver.exe"
it only saves it to the uservariables Path. Is there a way to add it to the systemvariables Path by using CMD?
This is PowerShell code. There is probably some way to do it with a cmd-only reg.exe, but I have not been down that path. If you are on a supported Windows system, PowerShell will be available.
To do this, you will want to retrieve the current variable values before interpolation (resolving). To do that for the user PATH variable:
(Get-Item -Path 'HKCU:\Environment').GetValue(
'PATH', # the registry-value name
$null, # the default value to return if no such value exists.
'DoNotExpandEnvironmentNames' # the option that suppresses expansion
)
To get the system PATH variable:
(Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment').GetValue(
'PATH', # the registry-value name
$null, # the default value to return if no such value exists.
'DoNotExpandEnvironmentNames' # the option that suppresses expansion
)
Once you have the current, pre-interpolation PATH variable value, it can be changed before using Set-Item or setx.exe. Setting the system path will probably require Administrator permission, or should.

Set java home on windows registry level

I'm trying to execute either a powershell or batch file on a remote WIndows 2012 server to set java home & path permanently on a system level. I'm from Linux background, so finding it kind of challenging to get a solution.
I tried below powershell on my local, but of no use, I don't see JAVA on the Path or JAVA_HOME system variable created.
install_java.ps1
[System.Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\myfolder\ZuluJDK8")
$oldSysPath = (Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path
$newSysPath = $oldSysPath + ";$($Env:JAVA_HOME)\bin"
Set-ItemProperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path -Value $newSysPath
I referred to https://sites.google.com/site/forthenerdwithin/cool-scripts/cool-command-scripts but felt it's an overkill for my purpose.
To set environment variables permanently, use the [EnvironmentVariableTarget]::Machine parameter (for short just the string 'Machine')
# set the JAVA_HOME environment variable
$javaPath = 'C:\myfolder\ZuluJDK8'
[Environment]::SetEnvironmentVariable("JAVA_HOME", $javaPath, "Machine")
# get the current PATH string, split it on ';' and add the new path to the array
$newPath = ([Environment]::GetEnvironmentVariable("Path", "Machine") -split ';' |
Where-Object { $_ -match '\S' }) + "$javaPath\bin" | Select-Object -Unique
# set the updated PATH environment variable by joining the array back again with ';'
[Environment]::SetEnvironmentVariable("Path", ($newPath -join ';'), "Machine")
Hope that helps
Setting an environment variable directly through the registry works, but you'd have to login again to see the effect.

%USERPROFILE% in registry

I am scripting a solution that requires passing %USERPROFILE% to the registry in local_machine. For example
DotJetFolder=%USERPROFILE%\JetFolder
But it seems like registry doesn't understand this format. Looking for ideas on how to implement it. This for an RDS solution where we can't pre-determine the user profile.
Is there any way to pass this sort of variable to the registry.
You need to create the value as a REG_EXPAND_SZ value if you want environment variables in the string to be expanded when Windows reads the value. In PowerShell the creation of such a value would look somewhat like this:
$key = 'HKLM:\some\where'
$name = 'DotJetFolder'
$value = '%USERPROFILE%\JetFolder'
Set-ItemProperty -Path $key -Name $name -Value $value -Type ExpandString
From what I understand, you want to have a sub for "%USERPROFILE%"
$temp = "$env:USERPROFILE" + "\Jet"
Write-Host $temp
Hope it Helps!
BR

In PowerShell, how can I extract a file from HKEY_Users from all SIDs?

I am writing a PowerShell module to look for data that each user who has logged onto the computer at some point might have in their directory in HKEY_USERS. My initial thought was to mount HKEY_USERS, find a way to store each user's SID in a string variable, and then loop through all folders like so:
dir HKU\<STRING VARIABLE HOLDING SID>\Software\MyApp\Mydesireddata
Is there a way I can avoid having to loop through SIDs (because I won't know them ahead of time), and extract that file info from each SID on the system while remembering which SID it came from?
EDIT: Here is an example of the key I'm trying to extract from each user's SID using regedit (vncviewer's EulaAccepted)
Use Get-ChildItem to retrieve each user-specific subkey:
$UserHives = Get-ChildItem Registry::HKEY_USERS\ |Where-Object {$_.Name -match '^HKEY_USERS\\S-1-5-21-[\d\-]+$'}
Then loop over each entry and retrieve the desired registry value:
foreach($Hive in $UserHives)
{
# Construct path from base key
$Path = Join-Path $Hive.PSPath "SOFTWARE\MyApp\DataKey"
# Attempt to retrieve Item property
$Item = Get-ItemProperty -Path $Path -Name ValueName -ErrorAction SilentlyContinue
# Check if item property was there or not
if($Item)
{
$Item.ValueName
}
else
{
# doesn't exist
}
}
I tackled this issue a slightly different way; preferring to make use of a conspicuously placed wildcard.
Get-ItemProperty -Path Registry::HKEY_USERS\*\SOFTWARE\TestVNC\viewer\ -Name EulaAccepted |
Select-Object -Property #{n="SID";e={$_.PSPath.Split('::')[-1].Split('\')[1]}},EulaAccepted
The wildcard will automatically check all available paths and return what you need as well as the SID from the parent path.
As for the username (which is probably more useful than a SID), you didn't specifically ask for it, but I added it in for grins; this should cover local and domain accounts.
mind the line breaks
Get-ItemProperty -Path Registry::HKEY_USERS\*\SOFTWARE\TestVNC\viewer\ -Name EulaAccepted |
Select-Object -Property #{n="SID";e={$_.PSPath.Split('::')[-1].Split('\')[1]}},EulaAccepted |
Select-Object -Property #{n="User";e={[System.Security.Principal.SecurityIdentifier]::new($_.SID).`
Translate([System.Security.Principal.NTAccount]).Value}},SID,EulaAccepted
Getting the username is just ugly; there's likely a cleaner way to get it, but that's what I have in my head. The double-select really makes my skin crawl - there's something unpleasant about it. I could just do a one shot thing, but then it gets so unwieldly you don't even know what you're doing by looking at it.
I've included a screenshot of the registry below, and a screenshot of the screen output from running the few lines.

How to set the Environment path variable ignoring the current user's path variable

I'm currently having an issue we're I'm trying to update the system path variable via powershell using the tutorial found in this link (http://blogs.technet.com/b/heyscriptingguy/archive/2011/07/23/use-powershell-to-modify-your-environmental-path.aspx), but unfortunately, it'll sometimes not do anything due to the fact that the value is already in the current user's path. Is there some way to ignore the current user's path and only set the system one?
$AddedFolder = 'C:\Directory'
$OldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
IF ($ENV:PATH | Select-String -SimpleMatch $AddedFolder)
{
Return ‘Folder already within $ENV:PATH'
}
$NewPath=$OldPath.Trim(";")+’;’+$AddedFolder
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $NewPath
Check $OldPath instead of $env:Path then. I'd also recommend splitting the value at semicolons and checking if $AddedFolder is contained in that array, otherwise you might get false positives if a subfolder is already listed in the PATH.
if ($OldPath.Split(';') -contains $AddedFolder) {
Return 'Folder already within $ENV:PATH'
}

Resources