wixsharp icon indicating copy to clipboard operation
wixsharp copied to clipboard

How to assign Session variable values in the main()

Open MithileshL-26 opened this issue 9 months ago • 11 comments

What I want --> In the main function, a VirtualDir is declared. I want to set the regular time interval value in IIS in one of the application pools.

In my Wix# project, one of the dialogs takes hours and minutes as input in text boxes from a user. These hours and minutes are converted into minutes and stored in a session variable named RECYCLETIME.

namespace WixSharp_Setup1.Dialogs
{
    public partial class ServerConfigDlg : ManagedForm, IManagedDialog 
    {
        void next_Click(object sender, EventArgs e)
        {
            Runtime.Session["AppPoolLeft"] = txt_IISAppPoolLeft.Text;
            Runtime.Session["AppPoolRight"] = txt_IISAppPoolRight.Text;

            int hours = int.Parse(txt_IISAppPoolLeft.Text);
            int minutes = int.Parse(txt_IISAppPoolRight.Text);
            int totalMinutes = (hours * 60) + minutes;

            Runtime.Session["RECYCLETIME"] = totalMinutes.ToString();

            SaveTextData();
            Shell.GoNext();
        }
    }
}

The VirtualDir is declared in the main function:

I want to assign the value of RECYCLETIME to the RecycleMinutes in the iasVirtualDir.

namespace Project1
{
    public class Program
    {
        static void Main()
        {
            var serviceUser = new User
            {
                Id = "MyAppPoolUser",
                Name = "[USERNAME]",
            };

            var iasVirtualDir = new IISVirtualDir
            {
                Name = "[SERVICENAME]",
                AppName = "[SERVICENAME]",
                WebSite = new WebSite("[WEBSITENAME]", "*:[WEBPORT]") { InstallWebSite = true },
                WebAppPool = new WebAppPool("[SERVICENAME]",
                "[USERNAME]" == "" ? "Identity=localSystem; RecycleMinutes=__________; RecycleRequests=10000"
                                   : $"Identity=other; RecycleMinutes=_________; User={serviceUser.Id};")
            };


            var project = new ManagedProject("MyProduct",
                             new Dir(@"%ProgramFiles%\My Company\My Product",
                                 new File("Program.cs")));

            project.BuildMsi();
        }
    }
}

When RecycleMinutes is assigned an integer directly, the value is visible in the IIS application pool.

Is there any way to assign the value of RECYCLETIME, declared in one of the dialogs, to RecycleMinutes in the main function? RecycleMinutes only take int values.

MithileshL-26 avatar Mar 18 '25 10:03 MithileshL-26

Hiho, dont know if helps, but try to create your own public property with Upper letters and set from dialog.


session["MYTIMEVALUE"] = textbox1.Text;

in your project you can add msi properties in project

 project.Properties = new[]
 {
     new Property("MYTIMEVALUE", "default")
 };

now you can set and get it from session object in any time of installdialog. This approach i use always if i have to asssign value to custom property.

best regards, Torchok.

Torchok19081986 avatar Mar 18 '25 12:03 Torchok19081986

Hi @Torchok19081986,

Thanks for the comment. I tried using your solution, but it isn't working.

Do you have any other approaches or solutions that might work?

@oleg-shilo

MithileshL-26 avatar Mar 20 '25 07:03 MithileshL-26

morning. Now i confused. Why isnt working ? Any errors on install or it doesnt assign your value from dialog to sesssion ? I done it many times in this way. There is only in one way where i cant be working. If your value has to be set from CA. Here you have to use DeffaultDefferedProperties where your custom Property after ADDLOCAL in projectdecription should looks like following


project.DefaultDeferedPropeties =",MYTIMEVALUE"

now you can use it in CA. Very good example for IIS and Webserver in example from @oleg-shilo. Download latest Wix# latest Folder now navigate to Source\src\WixSharp.Samples\Wix# Samples\IIS.
Maybe this can give you some infos. You can also try to degug it in installdialog all values on install event. just show messagebox.show in installprogressdialog . Method has SetupEventArgs e und now you can see in messagebox.Show -> e.Session.ToString().

Torchok19081986 avatar Mar 20 '25 08:03 Torchok19081986

Previously, I used many session variables directly in the main() function that were declared in the dialogs shown below.

Image

When I try to assign ["RECYCLETIME"] to RecycleMinutes, it throws an error.

Image

Error Message - Image

When I tried to convert ["RECYCLETIME"] to an integer, either the value is blank, or it shows an error indicating it is not a valid integer.

MithileshL-26 avatar Mar 20 '25 10:03 MithileshL-26

ok, I know, that it has to be Attribute1=[ATTRIBUTEVALUE1] in this Format. Your definition looks ok. Is RECYLETIME in output wxs file exists and show just like error says on WebAppPool Group? Check this passage in wxs file. May wxs file was wrong generated. You can also try, what happens if you set , just for test, your RecyleTime with value.


int RECYCLETIME = 125;
Recycletime ={RECYCLETIME};

if it works, then wxs file generates wrong values.

i just found https://docs.firegiant.com/wix3/xsd/iis/recycletime/ for IIS Wix toolset Extension. According to this link, value has to be DateTime in normal format und Pattern say h:mm. Maybe this helps.

Torchok19081986 avatar Mar 20 '25 11:03 Torchok19081986

It works. The int variable value is reflected in the regular time interval value in IIS.

Image

Is there any way the Session["RECYCLETIME"] can be converted to an int and used in the main method?

MithileshL-26 avatar Mar 20 '25 14:03 MithileshL-26

ok, recyclevminuttes value is in minutes. If you use mangedUI setup, you can add custom dialog with content. just add newitem to your solutionproject and search for WixSharp Dialog. Add this Dialog in step on project.ManagedUI.Dialogs.add(WelcomeDialog).Add(Your dialog).

int recycleMinutes = int.Parse(Runtime.Session["RECYCLEMINUTES"].ToString());

Image

Add textbox control to this dialog. After Click next Button on welcomeDialog , now you should see your new Dialog. In this Dialog you can add to session

I dont think, you can do any values in main() , because this happens on msi site and msi want a runtime value, whenever you set value, hardcoded or on install runtime.

and code from above. I cant do anything more, sorry.

Torchok19081986 avatar Mar 20 '25 15:03 Torchok19081986

Okay, I will try to implement your suggestion. Thanks for your help.

MithileshL-26 avatar Mar 27 '25 11:03 MithileshL-26

Hello again @oleg-shilo , @Torchok19081986

I am able to update the Regular time interval (minutes) in IIS using a PowerShell script. But I need some help.

During the first-time installation of the .msi, when no application pool is present, the default value of 1740 is set for the Regular time interval of an application pool.

When the application pool is already present in IIS, the value is updated.

This happens because, during the first-time installation, the PowerShell script is executed before the application pool is created, so the default value is set. During subsequent installations, the script finds the existing pool and updates the value.

The application pool code is present in the main() function, and the script to change the Regular time interval is present in the Project_AfterInstall() function.

I have tried using the e.IsInstalled and e.Installing events to set the Regular time interval, but neither of them worked.

namespace Project1
{
    public class Program
    {
        static void Main()
        {
            var project = new ManagedProject("MyProduct",
                             new Dir(@"%ProgramFiles%\My Company\My Product",
                                 new File("Program.cs")));

            var serviceUser = new User
            {
                Id = "MyAppPoolUser",
                Name = "[USERNAME]",
                Password = "[PASSWORD]",
                PasswordNeverExpires = true,
                CreateUser = false
            };


            var iasVirtualDir = new IISVirtualDir
            {
                Name = "[ISSERVICENAME]",
                AppName = "[ISSERVICENAME]",
                WebSite = new WebSite("[WEBSITENAME]", "*:[WEBPORT]") { InstallWebSite = true },
                WebAppPool = new WebAppPool("[ISSERVICENAME]",
                "[USERNAME]" == "" ? "Identity=localSystem; RecycleRequests=10000"
                                   : $"Identity=other; User={serviceUser.Id};")
            };

            project.GUID = new Guid("5ddb2fe5-9cb6-418b-a538-360cd00b2af6");

            //custom set of standard UI dialogs
            project.ManagedUI = new ManagedUI();

            project.ManagedUI.InstallDialogs.Add<WelcomeDialog>()
                                            .Add<LicenceDialog>()
                                            .Add<SetupTypeDialog>()
                                            .Add<FeaturesDialog>()
                                            .Add<InstallDirDialog>()
                                            .Add<ProgressDialog>()
                                            .Add<ExitDialog>();

            project.ManagedUI.ModifyDialogs.Add<MaintenanceTypeDialog>()
                                           .Add<FeaturesDialog>()
                                           .Add<ProgressDialog>()
                                           .Add<ExitDialog>();

            //project.SourceBaseDir = "<input dir path>";
            //project.OutDir = "<output dir path>";

            project.AfterInstall += Project_AfterInstall;

            project.BuildMsi();
        }

        private static void Project_AfterInstall(SetupEventArgs e)
        {
            string test = e.Session.Property("RECYCLETIME");
            int recycleInterval = Convert.ToInt32(test);

            string appPoolName = e.Session.Property("IASSERVICENAME");
            
            // Powershell Script execution starts
        }
    }
}

Is there a solution to set the value after the application pool is created?

MithileshL-26 avatar Apr 18 '25 18:04 MithileshL-26

TL;DR version Either look for "how to set Regular time interval from MSI WiX" or simply wait in your PS Script until the app pool is created and then set the value.

Well designed solution If WiX does not have support for the value you are trying to change, then you need to do it viaa custom routine. And this is where it becomes difficult.

The problem you are facing is caused by your deployment design. You want to take certain actions when an external system gets in a certain state. This is not a task for MSI. MSI has no means for interacting with this system, so it cannot access its state.

This means that you need to start some routine at the end of the installation, and that routine needs to wait for the state change event before doing the final configuration.

That's why good deployment practices require developers to separate the installation (copy files to the appropriate locations) and configuration (integrate your application with the OS). Thus, a good design would look like this:

  1. Have your msi that deploys all files and creates the base configuration (e.g. install your WebSite)
  2. Run your application configuration utility from your Project_AfterInstall to finalise the WebSite configuration
    • wait until app pool is created
    • set Regulat Time Interval of the app pool

This way, you can even invoke your config utility even without restarting the MSI installation. IE iof the configuration has been altered and you need to reset it to the healthy state.

The configuration utility is just a concept. But its implementation can be as simple as your application executable run with a special command line switch (-config) and the handler of this switch, where you do all waiting and configuring the stuff without even resorting to PowerShell.

oleg-shilo avatar Apr 19 '25 03:04 oleg-shilo

Thanks. Will try out this solution and let you know.

MithileshL-26 avatar Apr 24 '25 08:04 MithileshL-26