Telling Puppet to only run an install if registry key is not present
The user manbart found the answer 7 months ago with this question
Exec onlyif registry value is not present
calling reg.exe to query the registry in an exec resource.
Puppet: Conditional exec using unless-option
Make sure you are not subject to registry redirection or file system redirection. This is usually the case - if you are on a 64-bit Windows OS, it is preferred that you use a 64-bit version of Puppet.
We've noted file system redirector and workarounds in troubleshooting. We've also touched on registry redirection for custom facts. In your case, it could be you are subject to file system redirection as you are attempting to call c:\windows\system32\cmd.exe
.
The short of it is, you should ensure that you are using the 64 bit version of cmd.exe, which is either in c:\windows\sysnative
or c:\windows\system32
. This is addressed by the $system32
fact starting with Puppet 3.7.3:
exec { 'example':
path => "$system32',
command => 'something',
unless => 'reg query "HKEY_LOCAL_MACHINE\Software\My key" /f 5.1',
}
c# Setting new registry value only if registry value name already exists
Use the Registry.GetValue() method:
Retrieves the value associated with the specified name, in the specified registry key. If the name is not found in the specified key, returns a default value that you provide, or null if the specified key does not exist.
If you want to test whether the keyName
exists, test for null:
var myValue
= Registry.GetValue(@"HKEY_CURRENT_USER\missing_key", "missing_value", "hi");
// myValue = null (because that's just what GetValue returns)
If you want to test whether the valueName
exists, test for your default value:
var myValue
= Registry.GetValue(@"HKEY_CURRENT_USER\valid_key", "missing_value", null);
// myValue = null (because that's what you specified as the defaultValue)
If the path could be invalid, you could try surrounding it with a try/catch
block:
try
{
var myValue = Registry.GetValue( ... ); // throws exception on invalid keyName
if (myValue != null)
Registry.SetValue( ... );
}
catch (ArgumentException ex)
{
// do something like tell user that path is invalid
}
How to execute logic on Optional if not present?
With Java 9 or higher, ifPresentOrElse
is most likely what you want:
Optional<> opt = dao.find();
opt.ifPresentOrElse(obj -> obj.setAvailable(true),
() -> logger.error("…"));
Currying using vavr or alike might get even neater code, but I haven't tried yet.
Execute create_resource after everything has finished or after exec has finished
Like all Puppet functions, create_resources()
runs during catalog building. Each catalog is completely built before any resource declared in it is applied, and often on a different machine than the one for which it is intended. What you appear to be after is not modulating the behavior of create_resources()
, but rather managing the relative order of application of the resources it adds to the catalog.
And that you can readily do with a chain operator and a resource collector. For example, add
Exec['I need to run first'] -> Do::Something<||>
to the body of class do::foo
. There are a lot of possible variations on that, and also a few alternative approaches, but I would need details of the specific use case to make stronger or more specific recommendations.
Triggering dependent resources in a interation loop
I believe I need to add some dependencies using
subscribe
andrefreshonly
.
I'm not so sure that you need to add dependencies, because without explicit dependencies, resources should be applied in the relative order in which they appear in the manifest. Additionally, refreshonly
does not declare a dependency, and subscribe
is probably not appropriate for this particular task. Furthermore, although refreshonly
works in conjunction with dependencies, it's probably not appropriate for this task, either, because notify
/ subscribe
is not right for it.
In a general sense, the key issues are these:
the hive must be loaded before you can attempt to sync any registry entries, so you cannot know whether any given registry resource is out of sync without loading the hive first;
if the hive is loaded then it must also be unloaded;
but the hive must not be unloaded before all the registry entries are synced.
You cannot make Exec['load_registry_hive']
refreshonly because there is no resource that would signal it. You can, however, check whether $base_windows::registry
has any elements as a precondition for doing any of the work. If it does, then you definitely need to load the hive.
You can set up explicit dependencies, and I'm generally inclined to do that, as it protects against surprises when a resource is affected by dependency edges that are not apparent at the point of its declaration. So I would suggest this:
$temp_hive_name = $base_windows::temp_hive_name
if ! $base_windows::registry.empty() {
# LOAD REGISTRY HIVE
exec { 'load_registry_hive' :
command => template('base_windows/Load-RegHive.ps1.erb'),
unless => template('base_windows/Test-HiveLoadState.ps1.erb'),
provider => powershell,
logoutput => true,
}
# MODIFY REGISTRY, ITERATING OVER HIERA DATA
$base_windows::registry.each | $key, $value | {
registry::value { "registry_${key}" :
key => "${value['key']}\\${temp_hive_name}\\${value['subkey']}",
type => $value['type'],
data => $value['data'],
value => $value['value'],
require => Exec['load_registry_hive'],
before => Exec['unload_registry_hive'],
}
}
# UNLOAD REGISTRY HIVE
exec { 'unload_registry_hive' :
command => template('base_windows/Unload-RegHive.ps1.erb'),
onlyif => template('base_windows/Test-HiveLoadState.ps1.erb'),
provider => powershell,
logoutput => true,
}
}
Note that you will necessarily both load and unload the hive on each Puppet run, because you cannot determine whether any entries need to be updated without doing so.
How to allow user to install only if a given registry key doesn't have a certain value?
You'll need a post build JScript for your MSI file. Or you can do it manually in Orca.
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var filespec = WScript.Arguments(0);
var msiOpenDatabaseModeTransact = 1;
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
Execute("INSERT INTO `AppSearch` (`Property`, `Signature_`) VALUES ('SOMESOFTWAREVERSION', 'SomeSoftwareVersion')");
Execute("INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) VALUES ('SomeSoftwareVersion', 2, 'SOFTWARE\\Some Manufacturer\\SomeSoftware', 'SomeSoftwareVersion', 2)");
Execute("INSERT INTO `LaunchCondition` (`Condition`, `Description`) VALUES ('SOMESOFTWAREVERSION <> \"#1\"', 'This application cannot be installed with SOMESOFTWARE v1. Setup now will exit.')");
function Execute(sql) {
view = database.OpenView(sql);
view.Execute();
view.Close();
}
It will check Wow6432Node on 64-bit Windows just as WiX does
Related Topics
Post Redirect Get Pattern in Rails
Accessing a Has_One Associations' Attributes
Ruby How to Merge Two CSV Files with Slightly Different Headers
How to Set Up the Recipient Id in Public Activity
Rmagick Error After Installing Os X Mavericks
Ruby or Rails Sort on Two/Multiple Date Fields
Rails 3 and PDFkit. How to Specify Page Size
Importing CSV Data into Rails App, Using Something Other Then the Association "Id"
Building Gem, Executable Not Found
Fast-Stemmer Installation Problems
Ruby Private Attr_Accessor and Unexpected Nil
Triple Single Quote VS Triple Double Quote in Ruby
Why Is My Ruby Git Script Hook Run with the Wrong $Path
Ruby Converting Utc to User's Time Zone
Sort an Array in Ruby Ignoring Articles ("The", "A", "An")
How to Access Current_User Object in Model
Could Not Find Gem 'Logstash-Devutils (>= 0) Ruby' in Any of the Gem Sources