protected override void OnLoad(EventArgs e)
        {
            string applianceIDString = Request.QueryString.Get("ApplianceID");
            if (applianceIDString == null)
            {
                throw new Exception("ApplianceID not supplied");
            }
            long applianceID;
            if (!long.TryParse(applianceIDString, out applianceID))
            {
                throw new Exception("ApplianceID " + applianceIDString + " not a number");
            }
            string keyString = Request.QueryString.Get("Key");
            if (keyString == null)
            {
                throw new Exception("Key not supplied");
            }
            String serverKey = HttpServerUtility.UrlTokenEncode(ServerCryptoManager.Instance.PublicKey);
            if (!serverKey.Substring(0, 10).Equals(keyString))
            {
                throw new Exception("Key parameter must be the first 10 characters of the ScreenConnect server key");
            }

            NCentralMachineFacade nmf = new NCentralMachineFacade(getParameter("NCentralServerAddress"),
                                                    getParameter("NCentralAPIUsername"),
                                                    getParameter("NCentralAPIPassword"));
            //
            // Get the list of Service Organizations
            //
            Customer[] ServiceOrgs = nmf.getCustomerList(true);

            List<CustomerInfo> SOInfoList = new List<CustomerInfo>();
            foreach (Customer SO in ServiceOrgs)
            {
                CustomerInfo CustInfo = new CustomerInfo();
                foreach (T_KeyPair i in SO.Info)
                {
                    switch (i.Key)
                    {
                        case "customer.customername":
                            CustInfo.CustomerName = i.Value;
                            break;
                        case "customer.customerid":
                            CustInfo.CustomerID = Convert.ToInt32(i.Value);
                            break;
                        case "customer.parentid":
                            CustInfo.ParentID = Convert.ToInt32(i.Value);
                            break;
                    }
                }
                SOInfoList.Add(CustInfo);
            }

            //
            // Get the list of customers, and their parent IDs.  In N-Central 10.1, sites are implemented
            // as customers whose parent ID is the actual customer.  Top-level customers' parent ID is the
            // Service Organization to which they belong.
            //
            Customer[] Customers = nmf.getCustomerList(false);

            List<CustomerInfo> CustomerInfoList = new List<CustomerInfo>();
            foreach (Customer Cust in Customers)
            {
                CustomerInfo CustInfo = new CustomerInfo();
                foreach (T_KeyPair i in Cust.Info)
                {
                    switch (i.Key)
                    {
                        case "customer.customername":
                            CustInfo.CustomerName = i.Value;
                            break;
                        case "customer.customerid":
                            CustInfo.CustomerID = Convert.ToInt32(i.Value);
                            break;
                        case "customer.parentid":
                            CustInfo.ParentID = Convert.ToInt32(i.Value);
                            break;
                    }
                }
                CustomerInfoList.Add(CustInfo);
            }

            //
            // Get the device's Customer and determine the parent id for it
            //
            DeviceInfo result = nmf.getDeviceInfo(applianceIDString);
            string customerName = null;
            foreach (T_KeyValue i in result.Info)
            {
                if (i.Key.Equals("device.customername"))
                {
                    customerName = i.Value[0];
                    break;
                }
            }

            if (customerName == null)
            {
                throw new Exception("N-Central API call to getDeviceInfo for applianceID "+applianceIDString+" did not return a value for device.customername");
            }

            int customerID = 0;
            int parentID = 0;
            foreach (CustomerInfo Cust in CustomerInfoList)
            {
                if (customerName.Equals(Cust.CustomerName))
                {
                    customerID = Cust.CustomerID;
                    parentID = Cust.ParentID;
                    break;
                }
            }

            //
            // Determine if this is a site or a top-level customer
            // If it's a site, we'll be setting two custom properties,
            // c=<CustomerName>&c=<SiteName>
            //
            bool TopLevelCust = false;
            int numProperties = 2;
            foreach (CustomerInfo SO in SOInfoList)
            {
                if (SO.CustomerID == parentID)
                {
                    TopLevelCust = true;
                    numProperties = 1;
                    break;
                }
            }

            var relayUri = ServerExtensions.GetRelayUri(ConfigurationManager.AppSettings, HttpContext.Current.Request.Url, true, true);

            //
            // Set the custom properties according to whether this is a top-level customer
            // or site
            //
            string[] propertyValues=new string[numProperties];
            if (TopLevelCust)
            {
                propertyValues[0] = customerName;
            }
            else
            {
                propertyValues[1] = customerName;
                foreach (CustomerInfo Cust in CustomerInfoList)
                {
                    if (Cust.CustomerID == parentID)
                    {
                        propertyValues[0] = Cust.CustomerName;
                        break;
                    }
                }
            }

            //
            // Set the MSI customization parameters
            //
            var clientLaunchParameters = new ClientLaunchParameters
            {
                SessionType = SessionType.Access,
                ProcessType = ProcessType.Guest,
                NameCallbackFormat = "",
                CustomPropertyValueCallbackFormats = propertyValues,
                Host = relayUri.Host,
                Port = relayUri.Port,
                EncryptionKey = ServerCryptoManager.Instance.PublicKey,
            };

            var wildcardedHandlerPath = WebConfigurationManager.GetHandlerPath(typeof(InstallerHandler)).ReplaceFirst("*", WebResources.GetString("FileDownload.BaseName"));
            var handlerPath = wildcardedHandlerPath.ReplaceFirst("*", "msi");
            handlerPath = "/" + handlerPath + ClientLaunchParameters.ToQueryString(clientLaunchParameters);

            //
            // Redirect to the on-the-fly built custom MSI
            //
            Response.Redirect(getParameter("WebServerAddressableUri") + handlerPath);
            Response.End();
        }
        protected override void OnLoad(EventArgs e)
        {
            string applianceIDString = Request.QueryString.Get("ApplianceID");
            if (applianceIDString == null)
            {
                throw new Exception("ApplianceID not supplied");
            }
            long applianceID;
            if (!long.TryParse(applianceIDString, out applianceID))
            {
                throw new Exception("ApplianceID " + applianceIDString + " not a number");
            }
            string keyString = Request.QueryString.Get("Key");
            if (keyString == null)
            {
                throw new Exception("Key not supplied");
            }
            String serverKey = HttpServerUtility.UrlTokenEncode(ServerCryptoManager.Instance.PublicKey);
            if (!serverKey.Substring(0, 10).Equals(keyString))
            {
                throw new Exception("Key parameter must be the first 10 characters of the ScreenConnect server key");
            }

            NCentralMachineFacade nmf = new NCentralMachineFacade();
            DeviceInfo result = nmf.getDeviceInfo(getParameter("NCentralServerAddress") + "/dms/services/ServerEI",
                                                    getParameter("NCentralAPIUsername"),
                                                    getParameter("NCentralAPIPassword"),
                                                    applianceIDString);
            string customerName = null;
            foreach (T_KeyValue i in result.Info)
            {
                if (i.Key.Equals("device.customername"))
                {
                    customerName = i.Value[0];
                    break;
                }
            }
            if (customerName == null)
            {
                throw new Exception("N-Central API call to getDeviceInfo for applianceID "+applianceIDString+" did not return a value for device.customername");
            }
            var relayUri = ServerExtensions.GetRelayUri(ConfigurationManager.AppSettings, HttpContext.Current.Request.Url, true, true);

            string[] propertyValues=new string[1];
            propertyValues[0] = customerName;
            var clientLaunchParameters = new ClientLaunchParameters
            {
                SessionType = SessionType.Access,
                ProcessType = ProcessType.Guest,
                NameCallbackFormat = "",
                CustomPropertyValueCallbackFormats = propertyValues,
                Host = relayUri.Host,
                Port = relayUri.Port,
                EncryptionKey = ServerCryptoManager.Instance.PublicKey,
            };

            var wildcardedHandlerPath = WebConfigurationManager.GetHandlerPath(typeof(InstallerHandler)).ReplaceFirst("*", WebResources.GetString("FileDownload.BaseName"));
            var handlerPath = wildcardedHandlerPath.ReplaceFirst("*", "msi");
            handlerPath = "/" + handlerPath + ClientLaunchParameters.ToQueryString(clientLaunchParameters);

            Response.Redirect(getParameter("WebServerAddressableUri") + handlerPath);
            Response.End();
        }