How to detect unattended installation (msiexec /quit or /qn) in you’re Custom Action with C#

Set UILevel property in CustomActionData, enter: /UILevel="[UILevel]"


A msi package can be started with different user interface types. For instance, a *.msi package started with msiexec /quit /i Example.msi, will have an UILevel = 2, but the same *.msi package started with msiexec /i Example.msi will have an UILevel = 5, see

User interface level Value Description
msiUILevelNoChange 0 Does not change UI level.
msiUILevelDefault 1 Uses default UI level.
msiUILevelNone 2 Silent installation.
msiUILevelBasic 3 Simple progress and error handling.
msiUILevelReduced 4 Authored UI and wizard dialog boxes suppressed.
msiUILevelFull 5 Authored UI with wizards, progress, and errors.
msiUILevelHideCancel 32 If combined with the msiUILevelBasic value, the installer shows progress dialog boxes but does not display a Cancel button on the dialog box to prevent users from canceling the installation.
msiUILevelProgressOnly 64 If combined with the msiUILevelBasic value, the installer displays progress dialog boxes but does not display any modal dialog boxes or error dialog boxes.
msiUILevelEndDialog 128 If combined with any above value, the installer displays a modal dialog box at the end of a successful installation or if there has been an error. No dialog box is displayed if the user cancels.

If you want to detect de UILevel of you’re executed msi package, during the execution of the msi package in a custom action follow the steps:

  • At a System.Configuration.Install.Installer to you’re project
  • image
  • Make sure the System.Configuration.Install.Installer has the attribute [RunInstaller(true)] set
  • Make sure the System.Configuration.Install.Installer has event handling wired up for the events you whish to handle (in this case I want to run code “AfterInstall” and “BeforeUninstall”
  • image
  • At a setup project to you’re solution
  • At the output and content files of you’re project to the setup project
  • image
  • Add custom actions (so the System.Configuration.Install.Installer events are fired)
  • image
  • image
  • Click on the custom actions and set the UILevel to /UILevel="[UILevel]" in the CustomActionData on the property page
  • image
  • In you’re “AfterInstall” event handler you can know access user interface type of the executed msi package, via this.Context.Parameters[“UILevel”]
  • Msi parameters are case sensitive so use “UILevel”
  • private void AfterInstallation(object sender, InstallEventArgs e)
    #if DEBUG
                // Break when in debug modus
                string uiLevel = this.Context.Parameters["UILevel"];

Change Telerik RadGrid CommandItemTemplate controls on page load with a recursive FindControl function

If you want to change the controls in the CommandItemTemplate of a Telerik RadGrid, you will have to use a recursive FindControl function, because ASP .NET 2.0 does not ship with a FindControl function that can search for controls in child controls.

     public static class ControlFinder
        /// <summary>
        /// Recursively finds a control in the controls collection.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static Control FindControlRecursive(Control control, string id)
            // Return null if parameter control is null
            if (control == null) return null;

            // Try to find the control at the current level
            Control ctrl = control.FindControl(id);
            if (ctrl == null)
                // Loop through child controls
                foreach (Control child in control.Controls)
                    // Try to find the control at the next level
                    ctrl = FindControlRecursive(child, id);

                    // Stop search when control is found
                    if (ctrl != null) break;
            return ctrl;        }

In the page load:

LinkButton showReports = ControlFinder.FindControlRecursive(this.RadGrid.MasterTableView, "showReports") as LinkButton;
showReports.Attributes["href"] = @"\MyShare";

How to use datediff with LLBLGen Pro

If you want to use datedif to filter on a date, you can use code like:

        public EntityCollection<Customers> GetCustomers(DateTime creationDate)
            EntityCollection<AfhaalopdrachtEntity> result = new EntityCollection<AfhaalopdrachtEntity>();

            // Filter
            IRelationPredicateBucket filter = new RelationPredicateBucket();

            IPredicate customerCreateDateFilter = new EntityField2("CreateCustomerDiff", new DbFunctionCall("DATEDIFF(day, {0}, {1})", new object[] { CustomerFields.CreationDate, creationDate})) == 0;
            filter.PredicateExpression.Add(customerCreateDateFilter );

            // Fetch (get the data)
            using (DataAccessAdapter da = ConnectionHelper.GetAdapter(Source.Pegaso, Global.Logger))
                da.FetchEntityCollection(result, filter);

           return result;