In WiX how do I test for the existence of a registry key (not value) for Oracle ODP.Net - oracle

More specifically I want to test whether Oracle ODP.Net is installed on a machine. I want to do this by testing for the HKLM\SOFTWARE\ORACLE\ODP.NET registry key.
The actual values used by ODP.Net are stored in HKLM\SOFTWARE\ORACLE\ODP.NET\2.111.6.20 however I assume that this lower level key's name will change as updates are released by Oracle.
I have tried the following which fails, possibly because the (Default) value doesn't really exist or possibly because it is null (I'm not sure exactly how it's represented in the registry).
<Property Id="ORACLE_ODPNET">
<RegistrySearch Id="ODPNET_RegKey" Type="raw" Root="HKLM" Key="SOFTWARE\ORACLE\ODP.NET" Name="(Default)"/>
</Property>
<Condition Message="This setup requires ODP.Net to be installed.">
Installed OR ORACLE_ODPNET
</Condition>
So any of the following would be helpful to me:
A way to search for a registry key
with no values under it.
A way to search for a registry value
using a path containing wildcards
A better way to test for ODP.Net
being installed

OK, so thanks to Sascha's information it seems that the answer is "you can't" using the built-in WiX registry functions.
Now I also wanted this test to happen along with the other launch condition tests which makes it a bit harder. Getting this to work has taken me quite a while although it's fairly simple now I know how, so hopefully this will save someone else the same pain.
First create a property inside your WiX Product:
<Property Id="ODPNETINSTALLED">0</Property>
Next create a custom action to check for the key and set ODPNETINSTALLED to "1" if it exists. I'm not going to go into compiling and adding the custom action to the installer here but it's fairly simple if you use Votive in Visual Studio. The code for my custom action is:
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Win32;
namespace WiXCustomAction
{
public class CustomActions
{
[CustomAction]
public static ActionResult CheckOdpNetInstalled(Session xiSession)
{
xiSession.Log("Begin CheckOdpNetInstalled");
RegistryKey lKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\ORACLE\ODP.Net");
xiSession["ODPNETINSTALLED"] = lKey == null ? "0" : "1";
return ActionResult.Success;
}
}
}
Now you need to register and schedule the action, because I wanted the warning to appear along with my other launch conditions I had to add it to the InstallUISequence element:
<Binary Id="WiXCustomAction.dll" SourceFile="$(var.WiXCustomAction.TargetDir)$(var.WiXCustomAction.TargetName).CA.dll" />
<CustomAction Id="CheckOdpNet" BinaryKey="WiXCustomAction.dll" DllEntry="CheckOdpNetInstalled" Execute="immediate" />
<InstallUISequence>
<Custom Action="CheckOdpNet" Before="LaunchConditions">NOT Installed</Custom>
</InstallUISequence>
Finally add a launch condition to check the property:
<Condition Message="!(loc.OracleOdpCondition)">
Installed OR ODPNETINSTALLED="1"
</Condition>
Note that I believe that scheduling in InstallUISequence means the custom action won't be fired during non-UI installs. However, my installer must have UI install so it's not an issue for me.

Simply omit RegistrySearch/#Name to get the "(Default)" value. Unfortunately there's no way that I'm aware of to do a recursive search, you're going to need to pick a "known" registry key that will be stable between releases and base your search from that.
<Property Id="ORACLE_ODPNET">
<RegistrySearch Id="ODPNET_RegKey" Type="raw" Root="HKLM" Key="SOFTWARE\ORACLE\ODP.NET" />
</Property>
<Condition Message="This setup requires ODP.Net to be installed.">
Installed OR ORACLE_ODPNET
</Condition>

Related

wix custom action to remove http binding

I have a Wix installer to deploy my application in IIS. I want to remove HTTP binding when it deploys.
Below is the cmd command that helps in removing the HTTP binding:
“set site /site.name:"My Project Management" /-bindings.[protocol='http',bindingInformation='*:80:']”
I want the same thing happen via wix custom action.Something like below:
<CustomAction Name="RemoveHttp_Cmd" Schedule="Before" Reference="RemoveHttp" Condition="Installed">
<Definition Property="RemoveHttp" Execute="immediate" Value=""[WindowsFolder]system32\inetsrv\appcmd.exe" set site /name:"My Project Management" /-bindings:"http/*:80:"" />
</CustomAction>
<CustomAction Name="RemoveHttp" Schedule="Before" Reference="CreateAppPool" Condition="Installed">
<Definition BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" />
</CustomAction>
It should ideally remove the binding but actually, it is not.
Please suggest the right way to do.
You might want to look at the IIS Rewrite module. It's been my experience that you can use a bootstrapper to install the module if it isn't present and with just a little bit of XML in your applications web.config set up a rule to rewrite http to https or rewrite it to a not supported page. No installer work beyond making sure the rewrite module is present should be needed.

How To Remove Display Rule From a Ribbon Command in CRM Online?

I have a command for a button defined as follows:
<CommandDefinition Id="new.lead.CreditCheck.Command">
<EnableRules>
<EnableRule Id="new.lead.CreditCheck.EnableRule" />
</EnableRules>
<DisplayRules>
<DisplayRule Id="new.lead.CreditCheck.DisplayRule" />
</DisplayRules>
<Actions>
<JavaScriptFunction FunctionName="new.LeadDynamic.creditCheck" Library="$webresource:new_Lead_dyn.js" />
</Actions>
</CommandDefinition>
If I go and remove the Display Rule from the command, (but keep the actual Display Rule definition) it looks like this:
<CommandDefinition Id="new.lead.CreditCheck.Command">
<EnableRules>
<EnableRule Id="new.lead.CreditCheck.EnableRule" />
</EnableRules>
<DisplayRules />
<Actions>
<JavaScriptFunction FunctionName="new.LeadDynamic.creditCheck" Library="$webresource:new_Lead_dyn.js" />
</Actions>
</CommandDefinition>
I get an error when attempting to import (attempted to use the Ribbon Workbench and got the same error as well)
The ribbon item 'new.lead.CreditCheck.Command' is dependent on
.
I'm attempting to remove the dependency, but apparently I can't remove it since it exists! What am I missing?
I would consider this a bug in CRM, but in order to perform this operation, you have to delete the command, and then publish the solution! Once the command is deleted, you can delete the Display Rule. You can't do this in one step!
If your command is especially complicated, you can export the solution, delete the command, import the solution, remove the Display Rule and add back the command without the display rule and import.
Your solution has a CommandDefinition which depends on a DisplayRule with the ID "new.lead.CreditCheck.DisplayRule". You cannot remove the DisplayRule from the RibbonDiffXml as long there is a published and/or unpublished component depending on it, in this case the CommandDefinition.
Therefore you need to remove all references to the DisplayRule first and then publish these customizations. Having this done, you should be able to remove the DisplayRule itself.
The same procedure must be followed when you need to remove an obsolete attribute from an entity:
Remove the attribute from all forms, views etc.
Publish customizations
Remove the attribute from the entity model
Publish customizations
In this respect the behaviour of Dynamics CRM is i.m.o. 'by design'.

Wix and file search in installdir

I try to create installer for postgresql zip with binaries. On first installation I run initdb and it initializes postgresql cluster and create data folder. On removing my app this data directory doesn't remove. On next installation in the same dir initdb fails because directory is not empty.
I want to search file [INSTALLFOLDER]/PostgreSql/postgresql.conf and if it exists than ignore initdb custom action.
I can't use DirectorySearch because it is before INSTALLFOLDER exists. I read that there is a way to call directory search via custom action but I can't find any info about it.
How I can check that postgresql cluster has initialized already and skip init db custom action.
One solution would be to create an immediate execution custom action to check for the existence of the file. If so, set a property and use that property in a condition in your initialization custom action.
In the C# managed custom action example below, it takes the value of "SOMEPROPERTY" and if the corresponding directory exists, sets the property RUNINITDB=1. You could then use RUNINITDB in a condition in your initialization custom action. If the property RUNINITDB exists, then run your custom action.
[CustomAction]
public static ActionResult CheckInitDb(Session session)
{
session.Log("Begin CheckInitDb");
string dir = session["SOMEPROPERTY"]; //or you could figure this out programmatically
if(!Directory.Exists(dir))
{
session["RUNINITDB"] = "1";
session.Log("Setting RUNINITDB bit.");
}
return ActionResult.Success;
}
To create the custom action project above, create a new Visual Studio project and under the Windows Installer XML templates, select C# Custom Action Project.
To reference the custom action in your installer XML source code, assuming the custom action is in a dll named InstallHelper.CA.dll, you may have something similar to the code below. Note the custom action CallToRunInitDB will only run if the property RUNINITDB is set.
<Binary Id="InstallHelper" SourceFile="InstallHelper.CA.dll"/>
<CustomAction Id="CheckInitDb" BinaryKey="InstallHelper" DllEntry="CheckInitDb" Execute="immediate" Return="check"/>
<InstallExecuteSequence>
<Custom Action="CheckInitDb" Before="InstallInitialize">NOT (REMOVE ~= "ALL")</Custom>
<Custom Action="YourCallToRunInitDB" After="InstallInitialize">RUNINITDB</Custom>
</InstallExecuteSequence>
If you are unfamiliar with WiX managed custom actions you may be able to find some other sample code on SO: https://stackoverflow.com/search?q=wix+managed+custom+action

How to Implement TFS InvokeProcess to run under other credentials

I'm using TFS (VS 2010) Build Definitions and XAMLs to build apps to different environments. Now, we need to push these builds to Production servers which require different credentials than what the Build Controller has.
I have been working on implementing the steps found at "Customize Team Build 2010 – Part 9: Impersonate activities (run under other credentials)" from http://www.ewaldhofman.nl/post/2010/05/28/Customize-Team-Build-2010-e28093-Part-9-Impersonate-activities-(run-under-other-credentials).aspx but I cannot figure out how to use the credentials within the XAML file.
So, I have implemented the provided solution, and have made build definitions require the credentials, but how do I implement the credentials code (which appears to be in C#) into the XAML (which is XML)?
Thanks,
Stephanie
I have solved my issue here. I wasn't aware that the activities were coded in C#, although organized through the XML.
You can use a TryCatch activity to wrap the impersonation object and dispose it in the Finally.
The XAML should look like:
<TryCatch>
<TryCatch.Variables>
<Variable x:TypeArguments="bl:Impersonation" Name="Impersonation" />
</TryCatch.Variables>
<TryCatch.Try>
<Sequence>
<mtbwa:WriteBuildMessage Message="Impersonating..." />
<ba:CreateImpersonationContext Credentials="[Credentials]" Result="[Impersonation]" />
<!-- Your activities go here -->
</Sequence>
</TryCatch.Try>
<TryCatch.Finally>
<Sequence>
<ba:DisposeImpersonationContext Impersonation="[Impersonation]" />
<mtbwa:WriteBuildMessage Message="Done with impersonation!" />
</Sequence>
</TryCatch.Finally>
</TryCatch>

WIX: persist session data between C# CustomActions and subsequently displayed WIX Dialog

I am new to WIX and have been tasked with creating an installer that does
the following:
*Deploys a build of our application without overwriting the App.Config file
for the application
*Loads the key/values in the App.Config file and prompts the user with the
"defaults" (existing values) and allows them to modify them before finishing
*SAVES the values the user provided (or defaults if the user made no
changes) back to the App.Config file for use with the application.
I've got the WIX dilalogs and custom actions laid out successfully where
after InstallFinalize, my "LoadDefaultOptions" CustomAction is executed,
which successfully takes the installation directory and the app config file
name, loads it in an XML reader, and parses the key/value pairs, setting
them into the session variable in this manner:
session[key.toUpper()] = value;
My custom action(s) are defined as:
<CustomAction Id="LoadDefaultOptions" Return="asyncWait" Execute="immediate" BinaryKey="aeserverDbDialogPackage.dll" DllEntry="LoadDefaultOptions"/>
<CustomAction Id="SetConfigOptions" Return="check" Execute="immediate" BinaryKey="aeserverDbDialogPackage.dll" DllEntry="SetConfigOptions"/>
The LoadDefaultOptions executes as such:
<Custom Action="LoadDefaultOptions" After="InstallFinalize" />
I have the custom dialog edit properties set like this:
<Control Id="CCPDbConnString" Type="Edit" X="20" Y="62" Width="150" Height="18" Property="CCPCONNECTIONSTRING" Indirect="no" />
There's a matching Property tag earlier in the WXS file like this:
<Property Id="CCPCONNECTIONSTRING" Secure="yes" ></Property>
...And the LoadDefaultOptions customAction overwrites the session var like
this:
session["CCPCONNECTIONSTRING"] = <value parsed from file>;
According to session logs, this works as expected, the xml parse works, and
the session vars are set.
My problem is when my custom dialog comes around to prompt the user with
those stored defaults AFTER the LoadDefaultOptions CustomAction has run.
The ORIGINAL property values of the session variables seem to have "stuck"
instead of being overwritten by the custom action that loaded the defaults
via the xml file and stored them in the session. (they are blank as their
original properties are defined, or in the case I define them otherwise,
they show those values instead of the session written values)
How do you get Dialogs to "read" overridden session variables by
CustomActions?
Ultimately I want to load those values from the app config, prompt them back
to the user in an optional dialog prompt off the exit screen (which works so
far, aside from not getting updated session vars), and then on command from
that prompt dialog, run another custom action to re-write the App.Config
file with the settings provided from the custom dialog...
I just can't get the session vars to PERSIST!!!
Any ideas? am I completely off base attempting to use the session in this manner? how else could I parse the app.config file, and allow an installation user to change app settings if not by session?
Apparently, part of what I'm trying to do is more or less impossible... You cannot modify the session vars in the InstallExecuteSequence for use in dialogs... this can only be done in the InstallUISequence...
Therefore, I cannot READ AND PROMPT USERS FROM my App.Config on first installs as the file will never have been deployed during the period of time that it would be possible to do.... Seems the only time this would work is during an UPGRADE where the App.Config file exists from a prior install in the same location from which the original install occurred.
I'm going to go at it from this point of view, with NO (or hard-coded) default settings during a fresh installation, with an attempt to parse and use as defaults EXISTING app.config settings during upgrade installations... That should take care of my requirements!
If you schedule your custom action after InstallFinalize it won't run elevated during a managed installation / UAC type story. I also have a question, have you considered moving this configuration data to the application where it's easier to manage it as a first-run pattern?

Resources