patternshellMinor
Settings JAVA_HOME with Powershell
Viewed 0 times
withpowershellsettingsjava_home
Problem
Previously in the Settings JAVA_HOME with batch post, I had created a script in bash to change my
The script has several options that provide different functionalities:
This is still a script that I use for my personal use so there are still things that are not robust. You can add a key with an empty value or an invalid one and the script will not stop you. I've tested every option and all the "happy paths" are working.
This is my first script in PowerShell, so there were a lot of googling and patching all around the script to make it work.
`
Param(
[Parameter(Mandatory=$True)]
[string]$action,
[string]$key,
[string]$value
)
function Output() {
Get-ChildItem Env:JAVA_HOME
}
function SetJavaHome([string]$value_to_set) {
[Environment]::SetEnvironmentVariable("JAVA_HOME", $value_to_set, "Process")
}
function GetValueFromFile([string]$key_in_file) {
$javaVersions = GetVersionsFromFile
if($javaVersions.ContainsKey($key_in_file)) {
$javaVersions.$key_in_file
} else {
Write-Host "The key does not exit in this file"
exit
}
}
function AddVersionToFile([string]$key_in_file, [string]$value_to_add) {
$javaVersions = GetVersionsFromFile
if (!$javaVersions.ContainsKey($key_in_file)) {
Add-Content $dir/java_versions.store "$key_in_file=$value_to_add"
} else {
Write-Host "Key already exist in the file"
exit
}
Write-Host "$key_in_file=$value_to_add"
}
func
JAVA_HOME env variable. Since then, I have been trying to use more and more PowerShell so I recreated the script with PowerShell.The script has several options that provide different functionalities:
eorecho: output the current value ofJAVA_HOME.
sorset: option to change the current value ofJAVA_HOME. You must provide the key you want to change to.
aoradd: add a key value pair to the store file that you can later on changed to.
lorlist: list the current value in the file.
rorremove: remove the key-value pair from the store file.
This is still a script that I use for my personal use so there are still things that are not robust. You can add a key with an empty value or an invalid one and the script will not stop you. I've tested every option and all the "happy paths" are working.
This is my first script in PowerShell, so there were a lot of googling and patching all around the script to make it work.
`
Param(
[Parameter(Mandatory=$True)]
[string]$action,
[string]$key,
[string]$value
)
function Output() {
Get-ChildItem Env:JAVA_HOME
}
function SetJavaHome([string]$value_to_set) {
[Environment]::SetEnvironmentVariable("JAVA_HOME", $value_to_set, "Process")
}
function GetValueFromFile([string]$key_in_file) {
$javaVersions = GetVersionsFromFile
if($javaVersions.ContainsKey($key_in_file)) {
$javaVersions.$key_in_file
} else {
Write-Host "The key does not exit in this file"
exit
}
}
function AddVersionToFile([string]$key_in_file, [string]$value_to_add) {
$javaVersions = GetVersionsFromFile
if (!$javaVersions.ContainsKey($key_in_file)) {
Add-Content $dir/java_versions.store "$key_in_file=$value_to_add"
} else {
Write-Host "Key already exist in the file"
exit
}
Write-Host "$key_in_file=$value_to_add"
}
func
Solution
For a beginner script there are some There might be more to cover but there are a few things here that could improve the script.
Variable and function naming
In general functions and cmdlets should follow the Verb-Noun naming convention. You have the verb and noun part down but the hyphens are not there. Not a must but I would expect you to see those on other scripts.
Variables generally follow camelCase (with first work in lower) or PascalCase. I use camelCase myself. In either case PowerShell were prefer if you use one of those over the joined by underscore method.
Parameter in functions / cmdlets you will always see use PascalCase.
PowerShell script help
You have a multiline command block that contains some information about the script and its creation. I used the same sort of thing for my old VBS scripts. PowerShell has a robust help system you could(should?) be using for this information.. Stealing the simple example from TechNet
This way you can give more explanation to what your script is doing to the users that might be running it. (I realize this is a personal script). Also is an easy way to explain how each parameter works and give some examples.
The power this gives you is using Get-Help in the shell against your script.
Single line comments
Too many ifs
If you find yourself with several if blocks there is probably a better way. You should be using a switch for this.
The above covers a couple of ways that you can work with multiple values of
Remember that
If the value matches multiple conditions, the action for each condition is executed. To change this behavior, use the Break or Continue keywords.
So it would not be uncommon to see
Advanced function parameters
This is another large topic that is covered in about_functions_advanced_parameters but one example to call out would be your
So now if you don't provide one of those values for
Cannot validate argument on parameter 'Action'. The argument "bagel" does not belong to the set "e,echo,s,set,a,add,l,list,r,remove" specified by the ValidateSet attribute. Supply an argument that
is in the set and then try the command again.
Parameter Sets
A continuation of advanced functions... Your
This gives better control over what is used when calling the function (or script). Running
This shows the acceptable ways to call this function. There is no need to
Variable and function naming
In general functions and cmdlets should follow the Verb-Noun naming convention. You have the verb and noun part down but the hyphens are not there. Not a must but I would expect you to see those on other scripts.
Variables generally follow camelCase (with first work in lower) or PascalCase. I use camelCase myself. In either case PowerShell were prefer if you use one of those over the joined by underscore method.
Parameter in functions / cmdlets you will always see use PascalCase.
PowerShell script help
You have a multiline command block that contains some information about the script and its creation. I used the same sort of thing for my old VBS scripts. PowerShell has a robust help system you could(should?) be using for this information.. Stealing the simple example from TechNet
This way you can give more explanation to what your script is doing to the users that might be running it. (I realize this is a personal script). Also is an easy way to explain how each parameter works and give some examples.
The power this gives you is using Get-Help in the shell against your script.
Single line comments
# You can also just use the number sign for single line comments instead of Too many ifs
If you find yourself with several if blocks there is probably a better way. You should be using a switch for this.
switch ($action){
{$_ -eq "e" -or $_ -eq "echo"}{
"Do Something."
}
{"s","set" -contains $_}{
"Do Something Else."
}
default {
"You typed '$_' and it is has no associated action"
}
}The above covers a couple of ways that you can work with multiple values of
$action that result in the same code being executed. There is more you can do with switches so I encourage to read up on them. You can use regex as well for your cases but I opted not to include it here for brevity. Remember that
If the value matches multiple conditions, the action for each condition is executed. To change this behavior, use the Break or Continue keywords.
So it would not be uncommon to see
break being used in examples on the web. Advanced function parameters
This is another large topic that is covered in about_functions_advanced_parameters but one example to call out would be your
$action parameter. You only support 10 values and the script will do nothing if the one of those values was not entered. Param
(
[parameter(Mandatory=$true)]
[ValidateSet("e", "echo","s","set","a","add","l","list","r","remove")]
[String]$Action
# Continue with other params
)So now if you don't provide one of those values for
$action PowerShell will throw an error stating just that. Cannot validate argument on parameter 'Action'. The argument "bagel" does not belong to the set "e,echo,s,set,a,add,l,list,r,remove" specified by the ValidateSet attribute. Supply an argument that
is in the set and then try the command again.
Parameter Sets
A continuation of advanced functions... Your
$action is looking one of a set of mutually exclusive choices. Why not convert those actions into parameter switches? Then, using parameter sets, you can define their use with the $key $value parameters. Ensuring that nothing will be called or used if the combination was not meant to be. Consider the following (ignore the name. I had to call it something) function:function Set-JavaHome{
[CmdletBinding(DefaultParametersetName="List")]
Param
(
[Parameter(ParameterSetName="Echo")]
[switch]$Echo,
[Parameter(ParameterSetName="Set")]
[switch]$Set,
[Parameter(ParameterSetName="Add")]
[switch]$Add,
[Parameter(ParameterSetName="List")]
[switch]$List,
[Parameter(ParameterSetName="Remove")]
[switch]$Remove,
[Parameter(ParameterSetName="Add",Mandatory=$true)]
[Parameter(ParameterSetName="Remove",Mandatory=$true)]
[Parameter(ParameterSetName="Set",Mandatory=$true)]
[string]$Key,
[Parameter(ParameterSetName="Add",Mandatory=$true)]
[string]$Value
)
switch($pscmdlet.ParameterSetName){
"Echo" {"Echo echo echo...."}
"List" {"Show me the list!"}
"Remove" {"Removing $key"}
"Set"{"Setting the value to $key"}
"Add"{"The new key:-$key- will be set to -$value-"}
}
}This gives better control over what is used when calling the function (or script). Running
Get-Command against this function will help explain.PS C:\Windows\system32> Get-Command Set-JavaHome -Syntax
Set-JavaHome [-List] []
Set-JavaHome [-Echo] []
Set-JavaHome -Key [-Set] []
Set-JavaHome -Key -Value [-Add] []
Set-JavaHome -Key [-Remove] []This shows the acceptable ways to call this function. There is no need to
Code Snippets
<#
.SYNOPSIS
The synopsis goes here. This can be one line, or many.
.DESCRIPTION
The description is usually a longer, more detailed explanation of what the script or function does. Take as many lines as you need.
.PARAMETER computername
Here, the dotted keyword is followed by a single parameter name. Don't precede that with a hyphen. The following lines describe the purpose of the parameter:
.PARAMETER filePath
Provide a PARAMETER section for each parameter that your script or function accepts.
.EXAMPLE
There's no need to number your examples.
.EXAMPLE
PowerShell will number them for you when it displays your help text to a user.
#># You can also just use the number sign for single line comments instead of <##>switch ($action){
{$_ -eq "e" -or $_ -eq "echo"}{
"Do Something."
}
{"s","set" -contains $_}{
"Do Something Else."
}
default {
"You typed '$_' and it is has no associated action"
}
}Param
(
[parameter(Mandatory=$true)]
[ValidateSet("e", "echo","s","set","a","add","l","list","r","remove")]
[String]$Action
# Continue with other params
)function Set-JavaHome{
[CmdletBinding(DefaultParametersetName="List")]
Param
(
[Parameter(ParameterSetName="Echo")]
[switch]$Echo,
[Parameter(ParameterSetName="Set")]
[switch]$Set,
[Parameter(ParameterSetName="Add")]
[switch]$Add,
[Parameter(ParameterSetName="List")]
[switch]$List,
[Parameter(ParameterSetName="Remove")]
[switch]$Remove,
[Parameter(ParameterSetName="Add",Mandatory=$true)]
[Parameter(ParameterSetName="Remove",Mandatory=$true)]
[Parameter(ParameterSetName="Set",Mandatory=$true)]
[string]$Key,
[Parameter(ParameterSetName="Add",Mandatory=$true)]
[string]$Value
)
switch($pscmdlet.ParameterSetName){
"Echo" {"Echo echo echo...."}
"List" {"Show me the list!"}
"Remove" {"Removing $key"}
"Set"{"Setting the value to $key"}
"Add"{"The new key:-$key- will be set to -$value-"}
}
}Context
StackExchange Code Review Q#152454, answer score: 5
Revisions (0)
No revisions yet.