-
Notifications
You must be signed in to change notification settings - Fork 1
Redstone Class
The Redstone class is a helper class that makes some things a little easier in a way that only a class object can do.
None of the functions in PSRedstone rely on the class itself.
However, using the class can augment functionality.
You just need to provide a settings.json
and a Redstone Block ( ͡° ͜ʖ ͡°) at the top of your script to use the module:
Redstone can be instantiated in one of three ways:
- Without parameters:
New-Redstone
- With a parameter:
New-Redstone $fullPathToSettingsJson
; where the parameter can be cast as[IO.FileInfo]
, so a UNC path will not work. - With parameters:
New-Redstone $Publisher $Product $Version $Action
; where all of those parameters are[string]
s.
If Redstone is instantiated with no parameters, a settings.json
must exist.
The parameters and data in the settings.json
are just used to make some decisions easier.
Redstone will look for the case-insensitive JSON file named settings.json
file in the following order:
- In the current working directory using
$PWD
. - In the same directory where the executing script is; the
$PSScriptRoot
of the file that instantiated Redstone. - In the parent of the current working directory using
$PWD
. - In the parent of the directory where the executing script is; the
$PSScriptRoot
of the file that instantiated Redstone.
If a settings.json
is provided Redstone will import the data to $Redstone.Settings.JSON.Data
.
To make the data more accessible, Redstone will output the JSON data as the second item of the returned array.
That's why we suggest setting up the Redstone Block the way we have.
At a minimum, the following structure is required:
{
"Publisher": "Acme",
"Product": "Rocket",
"Version": "1.2.3"
}
Assuming your Redstone Block was set up the same as our example above, Publisher
should be accessed via:
$redstone.Settings.JSON.Data.Publisher
$settings.Publisher
ℹ: If you instantiate with parameters, the
$settings
variable will be empty.
Anything else in the settings.json
is arbitrary and is purely for use in your scripts.
See the Quick Start for an example.
This exploration assumes that you've already installed PSRedstone.
For this article, we'll have an installer for Acme Rocket 1.2.3 that we're working on.
Here's our settings.json
:
{
"Publisher": "Acme",
"Product": "Rocket",
"Version": "1.2.3",
"Installer": {
"UserName": "VertigoRay",
"CompanyName": "PSRedstone & Co.",
"SerialNumber": "bfa7409e-485c-45cf-bd42-1652c2c84e17"
}
}
This is the start of our install script, install.ps1
:
#region Redstone Block
#Requires -Modules PSRedstone
$redstone, $settings = New-Redstone
#endregion Redstone Block
Redstone Env contains calculated versions of environment variables. It gives you what you likely want from the environment variable without worrying if the process you're in is 32 or 64 bit or if the OS is 32 or 64 bit. Here are values for each situation:
- 64-bit process:
-
CommonProgramFiles
:C:\Program Files\Common Files
-
CommonProgramFiles(x86)
:C:\Program Files (x86)\Common Files
-
PROCESSOR_ARCHITECTURE
:AMD64
-
ProgramFiles
:C:\Program Files
-
ProgramFiles(x86)
:C:\Program Files (x86)
-
System32
:C:\WINDOWS\System32
-
SysWOW64
:C:\WINDOWS\SysWOW64
-
- 32-bit process on 64-bit OS:
-
CommonProgramFiles
:C:\Program Files\Common Files
-
CommonProgramFiles(x86)
:C:\Program Files (x86)\Common Files
-
PROCESSOR_ARCHITECTURE
:AMD64
-
ProgramFiles
:C:\Program Files
-
ProgramFiles(x86)
:C:\Program Files (x86)
-
System32
:C:\WINDOWS\SysNative
-
SysWOW64
:C:\WINDOWS\SysWOW64
-
- 32-bit OS:
-
CommonProgramFiles
:C:\Program Files\Common Files
-
CommonProgramFiles(x86)
:C:\Program Files\Common Files
-
PROCESSOR_ARCHITECTURE
:x86
-
ProgramFiles
:C:\Program Files
-
ProgramFiles(x86)
:C:\Program Files
-
System32
:C:\WINDOWS\System32
-
SysWOW64
:C:\WINDOWS\System32
-
This saves you from having to do an if
statement like this:
if ([System.Environment]::Is64BitOperatingSystem) {
# x64 OS
if ([System.Environment]::Is64BitProcess) {
# x64 Process
$arch = $env:PROCESSOR_ARCHITECTURE
} else {
# Running as x86 on x64 OS
$arch = $env:PROCESSOR_ARCHITEW6432
}
} else {
# x86 OS
$arch = $env:PROCESSOR_ARCHITECTURE
}
If you want the process/OS dependent values, just use $env:
.
PS > $redstone.OS
Name Value
---- -----
IsServerOS False
MachineDNSDomain
ProductType 1
Name Microsoft Windows 10 Enterprise|C:\Windows|\Device\Harddisk0\Partition2
IsWorkStationOS True
MachineWorkgroup WORKGROUP
Is64BitProcess True
IsDomainControllerOS False
LogonServer
ServicePack
ProductTypeName Workstation
MachineDomainController
Version 10.0.19041.0
UserDomain WORKGROUP
IsMachinePartOfDomain False
MachineADDomain
ShorterName Windows 10
Is64BitOperatingSystem True
Is64BitProcessor True
ShortName Windows 10 Enterprise
UserDNSDomain
PS > $redstone.ProfileList
Name Value
---- -----
ProfilesDirectory C:\Users
ProgramData C:\ProgramData
Profiles {System.Collections.Hashtable, System.Collections.Hashtable, System.Collections.Hashtable, System.Collections.Hashtable...}
Default C:\Users\Default
Public C:\Users\Public
PS > $redstone.ProfileList.Profiles
Name Value
---- -----
Username SYSTEM
Path C:\Windows\system32\config\systemprofile
Domain NT AUTHORITY
SID S-1-5-18
Username LOCAL SERVICE
Path C:\Windows\ServiceProfiles\LocalService
Domain NT AUTHORITY
SID S-1-5-19
Username NETWORK SERVICE
Path C:\Windows\ServiceProfiles\NetworkService
Domain NT AUTHORITY
SID S-1-5-20
Username WDAGUtilityAccount
Path C:\Users\WDAGUtilityAccount
Domain A6FB6907-F9CA-4
SID S-1-5-21-2047949552-857980807-821054962-504
Username ContainerAdministrator
Path C:\Users\ContainerAdministrator
Domain User Manager
SID S-1-5-93-2-1
Username ContainerUser
Path C:\Users\ContainerUser
Domain User Manager
SID S-1-5-93-2-2
If an override is allowed via a Registry value, the same override can be done via an environment variable.
Just prepend the environment variable with PSRedstone
.
For example:
Override KeyRoot:
- Registry:
RegistryKeyRoot
- Environment:
PSRedstoneRegistryKeyRoot
This setting stores important registry keys.
All of these, including the KeyRoot
, can be overridden in the registry.
All of these can be overridden with an environment variable.
Overrides via an environment variable take precedence over the registry.
- Default Value:
HKEY_LOCAL_MACHINE\SOFTWARE\com.github.VertigoRay\PSRedstone
- Override Environment Variable:
PSRedstoneRegistryKeyRoot
The location where PSRedstone core settings are configured. If you override this setting, then it affects where all other settings are pulled from. If nothing is overridden here than all default configurations are used. You can see all overriddable settings by exploring the Redstone class.
Redstone Vars (aka PrivateVars in a former life) contains organizational-specific, publisher-specific, and product-specific variables that you define in the Windows registry.
This is hierachal meaning that the settings applied in the order mentioned in the previous sentence.
If a settings with the same name is applied in both Org and Product, then the Product one is used.
Don't worry, you can still access all of the Vars in $redstone.Settings
.
There's a fundamental flaw that I haven't addressed yet. If there's a value and sub-key with the same name at the same key level, the sub-key won't be processed.
There's a GetVar
function that is purely designed to make things easier when getting a Var using a path in string form.
It has the added benefit of returning a provided default value if the path doesn't exist.
Here's an example Vars
structure:
$redstone.Vars = @{
Thing1 = 1
Thing2 = @{
This1 = 21
This2 = @{
That1 = 221
That2 = 222
That3 = 223
That4 = $null
}
This3 = 23
}
Thing3 = 3
Here's some examples of pulling data out of Vars
:
$redstone.Vars.Thing1
# Returns: 1
$redstone.Vars.Thing2.This2.That1
# Returns: 221
$redstone.Vars.Thing2.This4
# Returns: $null
$redstone.Vars.Thing2.This2.That4
# Returns: $null
$redstone.GetVar('Thing1')
# Returns: 1
$redstone.GetVar('Thing2.This2.That1')
# Returns: 221
$redstone.GetVar('Thing2.This4')
# Returns: $null
$redstone.GetVar('Thing2.This2.That4')
# Returns: $null
$redstone.GetVar('Thing2.This4', 'nope')
# Returns: 'nope'
$redstone.GetVar('Thing2.This2.That4', 'nope')
# Returns: $null
# GetVar() is just shorthand for Get-RedstoneHashtableValue:
Get-RedstoneHashtableValue -Hashtable $redstone.Vars -Path 'Thing2.This2.That4' -Default 'nope'
# Returns: $null
What if I want to use GetVar
to access a registry value with a dot?
Don't use
GetVar
.$valueWithDots = $redstone.Vars.'Value.With.Dots'If you're wanting to use the default value feature, you'll just have to write the logic yourself:
$valueWithDots = if ($redstone.Vars.Keys -contains 'Value.With.Dots') { $redstone.Vars.'Value.With.Dots' } else { 'Default Value' }
- Default Value:
HKEY_LOCAL_MACHINE\SOFTWARE\com.github.VertigoRay\PSRedstone\Org
- If KeyRoot has been overridden than this becomes
${KeyRoot}\Org
.
- If KeyRoot has been overridden than this becomes
- Override:
RegistryKeyOrg
- Recurse:
$true
- Override: Key
RegistryKeyOrgRecurse
- Override: Key
I expect Org to be a relatively simple/flat key. While there may be more things there, in my org I only care about the root of that key.
HKEY_LOCAL_MACHINE\SOFTWARE\MyOrg
However, I didn't want to force my design decisions on you, so I gave you the ability to override recursiveness.
- Default Value:
HKEY_LOCAL_MACHINE\SOFTWARE\com.github.VertigoRay\PSRedstone\${Publisher}
- The
$Publisher
is defined in settings or during instantiation. - If KeyRoot has been overridden than this becomes
${KeyRoot}\${Publisher}
.
- The
- Override:
RegistryKeyPublisherParent
- Recurse:
$false
- Override:
RegistryKeyPublisherRecurse
- Override:
I expect Publisher to be a relatively simple/flat key. While there may be more things there, on my endpoints the subkeys are the products.
The registry keys may look something like this for Microsoft
and VMware
:
-
HKEY_LOCAL_MACHINE\SOFTWARE\MyOrg\Software\
Microsoft
VMware
However, I didn't want to force my design decisions on you, so I gave you the ability to override recursiveness.
- Default Value:
HKEY_LOCAL_MACHINE\SOFTWARE\com.github.VertigoRay\PSRedstone\${Publisher}\${Product}
- The
$Publisher
and$Product
are defined in settings or during instantiation. - If KeyRoot has been overridden than this becomes
${KeyRoot}\${Publisher}\${Product}
.
- The
- Override:
RegistryKeyProductParent
- Recurse:
$true
- Override:
RegistryKeyProductRecurse
- Override:
I expect Product to be the deepest key. So, if you have sub-keys here you likely want them.
The registry keys may look something like this for Microsoft VS Code
and VMware Horizon Client
:
-
HKEY_LOCAL_MACHINE\SOFTWARE\MyOrg\Software\
-
Microsoft
VS Code
-
VMware
Horizon Client
-
However, I didn't want to force my design decisions on you, so I gave you the ability to override recursiveness.