A custom action that reads the file and stores a value in session obj. Is there a way to use it as a property while invoking othr custom action - wix

<CustomAction I'd=readValue binaryKey = custom.dll
DllEntryy = readfilevalue Execute= deferred Return =
check/>
// // In a .cs file code to read the file having method
// readfilevalue.
// I am setting
Customsession.writesessionvalue(key, value);
// In another .wxs file invoking executables
<Custom Action = someExe After= someOtherExe>
<!CDATA[ key < someValue]>
<Custom>
// Can I get the key value in this Custom tag? If no then
// how can I get the value please suggest.

No, there is very limited information flow between deferred actions (#Execute="deferred") and the shared Windows Installer session. That flow includes sending a few properties to the action (including CustomActionData), and receiving progress information and a success or failure from it, but will not carry arbitrary data like you describe.
Your options, as I see them:
Make the first custom action immediate so it can take part in the planning. This won't work if the action requires elevated privileges, or access to something put in place by another deferred action, but is otherwise the most "correct" way to do this. Note that if the data itself can be read by existing search patterns (like RegistrySearch), that's even better than an immediate custom action.
Merge the two actions, so there isn't any need for such a flow of information.
Use unsupported hacks, like sharing a file location outside of Windows Installer that both actions can access. Then you can send information through that. Note that cleanup of this can be hard to get correct, and that its unsupported nature may result in other problems in esoteric scenarios. (The link about obtaining context information alludes to why.)

Related

Can commands be intercepted based on their type?

In Axon, Command Interceptors seem to intercept any and every command. For permission checking, I need to base my decision on the type of command to see whether it is allowed in the current context.
#Override
public BiFunction<Integer, CommandMessage<?>, CommandMessage<?>> handle(List<? extends CommandMessage<?>> messages) {
return (index, command) -> {
// Check permissions
return command;
};
}
Usually I would prefer to register an interceptor per command type and handle the permission checks in dedicated objects. How would I do it with Axon? Will I need to have a load of instanceof if-statements in a single interceptor? Does anyone have a good example of permission checking with Axon?
At this point (Axon 4.0) the framework does not allow you the option to register DispatchInterceptors per command payload type directly. So what you're suggesting to do, the if-blocks/switch-statements, is the best thing you could do at this point.
Although I am not certain how fine grained your permission checks are, what you could do is have some form of permission annotation on the commands, with a specific value/enum you need to set on it. That way you do not have to tie in your payload type into the dispatcher directly, but could just check if the annotation exists and if so, check it's value for the kind of permission check which should be performed on it.
That would very likely result in a far smaller if-block/switch-statement than checking per payload type.

MSI MsiGetFeatureState returns INSTALLSTATE_BROKEN when called by a custom action as commit execution

One of my CA's tried to detect which feature was selected using MsiGetFeatureState and modify HKLM using its state, but it alayws returns INSTALLSTATE_BROKEN. I put this CA before "InstallFinalize".
So I wonder if this is expected and how I can do this. Thank you in advance.
Please see: Obtaining Context Information for Deferred Execution Custom Actions
A deferred cusom acton ( which commit is ) can't call MsiGetFeatureState. Only an immeadiate custom action can. If the information is needed in the deferred it must be marshaled using CustomActionData. For more information, read Installation Phases and In-Script Execution Options for Custom Actions in Windows Installer.
Also please realize that commit custom actions don't execute when rollback is disabled.
I'm not really sure what you mean by "modify HKLM using it's state" but in general you should use the registry table to declare registry updates. Don't reinevent the wheel as it's generally less robust.
You should avoid modify the features in the registry. i'm not sure if it's allowed to query feature states thru the api while installing the same product. you may get an old/wrong answer. but what you can do, is to set some property's and use them within the custom action. Take a look at the msdn "Conditional Statement Syntax". there are some symbols which allow you the query features-actions and feature-states (or components).

How to execute custom action present in MSI without invoking installation?

Given:
Wix 3.0 is used to create MSI.
The product consists of multiple feature.
Each feature has few sub features. It’s a standard MSI feature tree.
Each feature or sub feature depend on multiple external components.
E.g. .NET 4, ASP.NET etc
Custom action written in C# using Wix 3.0 SDK processes these
dependency and evaluates if components are present or not for a
given set of features.
At time of install if dependent component is missing for given
selection of features, installation fails.
To achieve:
Ability to execute prerequisite check, which is already done in MSI as custom action during installation, without installing MSI on a given machine.
Failed Attempts:
1)
Custom action have function signature like this
[CustomAction]
public static ActionResult ProcessFeaturePrerequisite(Session session);
In order to get session object I used following API present in Wix 3.0 SDK
Session session = Installer.OpenPackage("Pathto\\Product.msi", true); // true doesn’t install it. Also tried with false, but didn’t work.
When I invoke the above method with above session following things fail.
session.Features["SomeFeature"].CurrentState;
This throws exception.
System.ArgumentException was unhandled by user code
Message=Feature ID not registered. SomeFeature
Source=Microsoft.Deployment.WindowsInstaller
StackTrace:
at Microsoft.Deployment.WindowsInstaller.FeatureInfo.get_CurrentState()
Also below critical API which determines prerequisite status always returns false.
session.EvaluateCondition(prereq);
2)
I know a command line way to specify features to the above MSI and install it. It goes like this
msiexec /i "Product.msi" ADDLOCAL=ALL REMOVE="Foo,Bar "
I couldn’t find any API in SDK which allows me to pass additional params which returns session object without starting installation. My guess is passing such param will make session.Features more valid.
Questions:
So how do I achieve above goal?
Is there
any API in Wix SDK which allows me to call custom action without
invoking installation?
any way to invoke custom action from command line for a given MSI
without installing?
any way to make Wix to change MSI into accepting a command string
containing custom action name which only evaluates the action?
any better way to do the same?
I suppose you're trying to solve the problem with the wrong tool. As far as I understand, you would like to check the installation prerequisites from inside a certain tool, but not from the installation. As long as the functionality is implemented as a custom action in the MSI package, you'd like to utilize that functionality in order not to duplicate the code.
I would choose a different way in your situation:
Extract the functionality which actually checks for prerequisites into a separate assembly, e.g. checkprereq.dll
Refactor your custom action to reference checkprereq.dll. Note that you'll have to add checkprereq.dll to your Binary table as well as the customaction.dll. You should divide the responsibility here: the custom action part works with MSI stuff - in your case, it's defining which prerequisites to check based on the combination of features a user selected - and the functional part - the actual prerequisites verification, which is done by checkprereq.dll
Use checkprereq.dll separately when you need to check prerequisites not triggering the installation process
The attempts you've outlined here demonstrate an important false assumption: the session object at install time is the same as the installation object you get by just opening the MSI database for read only purpose. IT'S NOT TRUE! Actually, I doubt it makes any sense to reference the session object outside the installation transaction. As its name states, it is an installation session, that is, available in process - not a static thing.
The MSI package should be treated just as a database when it is just a file and not a running installation. Hence, only static information living in MSI package can be queried and used when you just open it for reading and not installing. I mean you can query the Feature table, for instance, but don't expect it to contain information which makes sense in installation time only, like whether a user chose a feature for installation or not.
Hope this makes sense and shows you the right direction.

DTF and MsiGetProperty

Related to: Accessing InstallShield "Support Files" from DTF (Managed Custom Action)
I need to read the property SUPPORTDIR. According to this forum (http://community.flexerasoftware.com/showthread.php?t=180742&page=3), I need to use MsiGetProperty.
How can I call MsiGetProperty from DTF?
DTF's Session class has the method:
public string this[string property] get: set:
This gets remoted over to the unmanaged C++ side where they invoke MsiGetProperty and MsiSetProperty. It's kind of like VBScript Session.Property("SUPPORTDIR") only simpler.
InstallShield should have scheduled a custom action called ISSetupFilesExtract. Log your install and see if it's executing and assigning the path to the property.
The only other gotcha I can think of is if you are doing a proper UAC story of non-elevating your UI but then elevating your Execute sequence, make sure that SUPPORTDIR is listed in the SecureCustomProperties property. Only "Secure" properties that get a value in the UI sequence are carried over to the execute sequence. "PUBLIC" properties will default back to whatever then were when the installer started executing.
I can tell you that I use SUPPORTDIR ( sometimes directly and sometimes via CustomActionData serialization) in my DTF custom actions and I have no problems with it.
To duplicate and extend the info from my comment to Accessing InstallShield "Support Files" from DTF (Managed Custom Action):
An object of Session class is passed to the custom action in DTF. Use session["SUPPORTDIR"] to access the property value (for immediate action). For deferred action, you'll have to pass it via CustomActionData. Also, for immediate CA, make sure you scheduled the action which reads SUPPORTDIR after CostFinalize - the point when all entries in Directory table become accessible as properties.

How can I get WiX to call a method in a .NET assembly as part of the installation process?

I'm migrating some existing products to use WiX 3.5 (I'm using the Votive VS integration). Some of the items I'm installing need to be registered with a third-party framework. The requirement is that I must call a Register() method in a third party .NET assembly to inform it of the presence of the items I'm installing. It expects a COM ProgID.
I can't figure out how to get WiX to do this. I thought about creating a binary Custom Action, but I can't find a way of passing a parameter (a string containing the ProgID) into that custom action. I don't want to hard-code it because I need this to be re-usable code. I can't see a way to do this declaratively because the Register() function is a 'black box'.
Man this is a steep learning curve. What's my best approach here?
Look at the Deployment Tools Foundation (DTF) for WIX. There is a DTF.chm file with the WIX installation with lots of information.
Assuming you installation process is something like
Setup installation, input parameters/ProgID, do validation, etc.
Begin actual installation of files
Call registration methods
You'll need two Custom actions (ignoring rollback and uninstallation)
SetupRegistration
DoRegistration
SetupRegistration should be an immediate custom action fired either from the UI or late in the setup phase. It grabs the ProgID and any other data needed, uses a CustomActionData object and assigns that to a property named "DoRegistration" (Important, the property name must be the same as the second custom action)
The DoRegistration is a deferred custom action and needs to be scheduled in the InstallExecuteSequence probably after InstallFiles, but that depends. It pulls the Session.CustomActionData property and gets the ProgID out, then calls whatever registration method you need.
Am using a sort of what you have described.
I use to call CustomAction(events) when required. Like on clicking button you can call a method which will do work for you.
Calling custom action like:
<Custom Action="ActionName" After="InstallFinalize">CONDITION = "1"</Custom>
Or calling custom action based on specific button click:
<CustomAction Id="TestConnection" BinaryKey="SetupCustomActions" DllEntry="TestConnection" Execute="immediate" Return="check" />