using System; using System.Collections; using System.Diagnostics; using System.Drawing; using System.IO; using System.IO.Compression; using System.Linq; using System.Security.AccessControl; using System.Security.Principal; using System.Windows.Forms; using System.Collections.Generic; using System.Management.Instrumentation; using System.Net; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using Microsoft.Web.Administration; using PdMagic.Windows; namespace cmIISConfig { public partial class MainForm : Form { private PdIISManager mIISManager; private CmConst mConst; private bool mUpdating = false; public MainForm() { InitializeComponent(); } private string DialogTitle => $"{mConst.ApplicationName} Install and Configuration Tool v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; private void Form1_Shown(object sender, EventArgs e) { mIISManager = new PdIISManager(); mConst = new CmConst(uxConfigureInstanceList.Text); // Populate controls from default CmConst properties uxInstallerFolder.Text = mConst.InstallersFolder; uxNewInstance.Text = mConst.DefaultInstanceName; RePopulateInstallers(uxInstallerFolder.Text); RePopulateInstanceList(uxUpgradeInstanceList.Items); if (uxUpgradeInstanceList.Items.Count > 0) { uxUpgradeInstanceList.SelectedIndex = 0; } RePopulateInstanceList(uxConfigureInstanceList.Items); if (uxConfigureInstanceList.Items.Count > 0) { uxConfigureInstanceList.SelectedIndex = 0; } UpdateControls(); } private void ReCreatecmConst(bool aReportChange) { if (uxConfigureInstanceList.Text != string.Empty) { if (aReportChange) { AppendToStatusLog( $"All variable names recalculated to reflect Instance={uxConfigureInstanceList.Text}"); } mConst = new CmConst(uxConfigureInstanceList.Text); uxUser.Text = mConst.InstanceUserName; uxUserGroup.Text = mConst.InstanceUserGroupName; uxPassword.Text = ""; } } private void RePopulateInstanceList(IList aList) { aList.Clear(); // list all CrashMagicOnline* folders - these are instances - The suffix is the instance name. // No suffix is the "[Default]" instance. var lFiles = Directory.GetDirectories($@"{mConst.WindowsProgramFiles}\{mConst.CompanyFolder}", $"{mConst.ApplicationFolderBaseName}*"); foreach (var lFile in lFiles) { var lFileName = Path.GetFileName(lFile); if (lFileName != null) { var lInstance = lFileName.Substring(mConst.ApplicationFolderBaseName.Length, lFileName.Length - mConst.ApplicationFolderBaseName.Length); if (mConst.InstanceExistsP(lInstance)) { aList.Add(lInstance == string.Empty ? mConst.DefaultInstanceName : lInstance); } } } } private void RePopulateInstallers(string aFolder) { uxInstallerList.Items.Clear(); List<String> lInstallers = Directory.EnumerateFiles(aFolder, "cmoInstall*.zip") .Select(Path.GetFileName) .ToList(); foreach (var lInstaller in lInstallers) { uxInstallerList.Items.Add(lInstaller); } if (uxInstallerList.Items.Count > 0) { uxInstallerList.SelectedIndex = 0; } } private void ShowMessageBox(string aMessage, Exception aException = null) { var lMessage = aException == null ? $"{aMessage}" : $"{aMessage}:\n{PdActiveDirectory.CleanedException(aException)}"; MessageBox.Show(lMessage, DialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Hand); } private void AppendToStatusLog(string aLine) { uxStatusLog.AppendText(aLine + System.Environment.NewLine); } private void AppendToStatusLog(List<string> aList) { foreach (string lLine in aList) { uxStatusLog.AppendText(lLine + System.Environment.NewLine); } } public void AppendToStatusLog(string text, Color color) { uxStatusLog.SelectionStart = uxStatusLog.TextLength; uxStatusLog.SelectionLength = 0; uxStatusLog.SelectionColor = color; uxStatusLog.AppendText(text); uxStatusLog.SelectionColor = uxStatusLog.ForeColor; } private void ShowException(string aLine, Exception aException) { AppendToStatusLog("Exception: " + aLine + System.Environment.NewLine, Color.Crimson); var lCurEx = aException; while (lCurEx != null) { AppendToStatusLog(lCurEx.Message, Color.Crimson); lCurEx = lCurEx.InnerException; } } private void UpdateControls() { if (mUpdating) { return; } try { mUpdating = true; Text = DialogTitle; try { int lIndex; // Remember prior selections string lWebSite = uxWebSite.Text; string lApplication = uxApplication.Text; uxWebSite.Items.Clear(); uxWebSite.Items.Add(""); uxApplication.Items.Clear(); uxApplicationPool.Items.Clear(); uxApplicationPool.Items.Add(""); try { uxWebSite.Items.AddRange(mIISManager.Sites.ToArray()); // Reset prior webSite selection lIndex = uxWebSite.FindStringExact(lWebSite); if (lIndex >= 0) { uxWebSite.SelectedIndex = lIndex; } } catch (Exception lException) { ShowException($"Add websites and set current ({lWebSite})", lException); } try { if (lWebSite != string.Empty) { uxApplication.Items.AddRange(mIISManager.Sites[lWebSite].Applications.ToArray()); lIndex = uxApplication.FindStringExact(lApplication); uxApplication.SelectedIndex = lIndex >= 0 ? lIndex : 0; } } catch (Exception lException) { ShowException($"Add applications and select current ({lApplication})", lException); } string lPool = ""; try { foreach (ApplicationPool lAp in mIISManager.ApplicationPools) { uxApplicationPool.Items.Add(lAp.Name); } var lSlashPos = uxApplication.Text.IndexOf("/"); if (lSlashPos >= 0) { var lApplicationPath = uxApplication.Text.Substring(lSlashPos); if (lWebSite != string.Empty) { lPool = mIISManager.Sites[lWebSite].Applications[lApplicationPath].ApplicationPoolName; if (lPool != string.Empty) { lIndex = uxApplicationPool.FindStringExact(lPool); if (lIndex >= 0) { uxApplicationPool.SelectedIndex = lIndex; } } } } } catch (Exception lException) { ShowException($"List application pools and set current ({lPool})", lException); } } finally { mUpdating = false; } } catch (Exception lUpdateControls) { ShowException("UpdateControls", lUpdateControls); } } private bool ReportMissingParameters() { bool lMissing = false; if ((uxUserGroup.Text.Trim() == string.Empty) | (uxUser.Text.Trim() == string.Empty) | (uxPassword.Text.Trim() == string.Empty)) { ShowMessageBox("Please enter a group, login and password before executing this operation"); lMissing = true; } return lMissing; } private void PrepareSiteAndApplication(string aSiteName, string aApplicationPath) { if (ReportMissingParameters()) return; var lStatus = new List<string>(); try { mIISManager.CreateISAPIHandler(aSiteName, aApplicationPath, aSiteName + "_Handler", mConst.IsapiFolder + $@"\{mConst.DllFileName}", lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("CreateISAPIHandler - Note: Editing this section of IIS configuration " + "requires that Windows feature 'ASP.NET 4.x' be installed.", lException); } try { lStatus.Clear(); mIISManager.VerifyDLLAllowed("Crash Magic", $@"{mConst.IsapiFolder}\{mConst.DllFileName}", $"{mConst.ApplicationName} {mConst.InstanceName}", lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("VerifyDLLAllowed", lException); } try { lStatus.Clear(); mIISManager.SetApplicationUser(aSiteName, aApplicationPath, uxUser.Text, uxPassword.Text,lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("SetApplicationUser", lException); } try { lStatus.Clear(); mIISManager.VerifyMimeTypes(aSiteName, aApplicationPath, mConst.MimeEntries, lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("Add Mime Types", lException); } try { lStatus.Clear(); mIISManager.VerifyDefaultDocument(aSiteName, aApplicationPath, $"{mConst.DllFileName}", lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("AddDefaultDocument", lException); } try { lStatus.Clear(); mIISManager.SetMaxAllowedContentLength(aSiteName, 524288000, lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("Set MaxAllowedContentLength", lException); } try { lStatus.Clear(); mIISManager.SetServerRuntimeValues(aSiteName, 2147483647, 4294967295, lStatus); AppendToStatusLog( lStatus); } catch (Exception lException) { ShowException("Set uploadReadAheadSize, maxRequestEntityAllowed", lException); } try { lStatus.Clear(); mIISManager.VerifyVirtualFolders(aSiteName, aApplicationPath, mConst.VirtualFolders, lStatus); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowException("VerifyVirtualDirectory", lException); } UpdateControls(); } private void uxAddNewSite_Click(object sender, EventArgs e) { try { var lNewSiteName = mConst.InstanceSiteName; if (PdInput.Show(this, "New site name", DialogTitle, ref lNewSiteName) != DialogResult.OK) return; var lStatus = new List<string>(); mIISManager.AddNewSite(lNewSiteName, mConst.IsapiFolder, lStatus); AppendToStatusLog( lStatus); UpdateControls(); uxWebSite.SelectedIndex = uxWebSite.FindStringExact(lNewSiteName); UpdateControls(); } catch (Exception lException) { ShowMessageBox("Failed to add new site", lException); } } private void uxCreateNewApp_Click(object sender, EventArgs e) { try { var lNewAppName = mConst.InstanceAppName; if (PdInput.Show(this, "New application name", DialogTitle, ref lNewAppName) != DialogResult.OK) return; var lStatus = new List<string>(); mIISManager.AddNewApplication(uxWebSite.Text, lNewAppName, mConst.IsapiFolder, lStatus); UpdateControls(); uxApplication.SelectedIndex = uxApplication.FindStringExact(uxWebSite.Text + lNewAppName); UpdateControls(); AppendToStatusLog(lStatus); } catch (Exception lException) { ShowMessageBox("Failed to add new application", lException); } } private void uxCreateNewAppPool_Click(object sender, EventArgs e) { if (ReportMissingParameters()) return; try { var lNewAppPoolName = mConst.InstanceAppPoolName; if (PdInput.Show(this, "New application pool name", DialogTitle, ref lNewAppPoolName) != DialogResult.OK) return; var lApplicationPath = uxApplication.Text.Substring(uxApplication.Text.IndexOf("/", StringComparison.Ordinal)); var lStatus = new List<string>(); mIISManager.AddNewApplicationPool(lNewAppPoolName, lStatus); AppendToStatusLog(lStatus); lStatus.Clear(); mIISManager.AttachSiteToApplicationPool(uxWebSite.Text, lApplicationPath, lNewAppPoolName, lStatus); AppendToStatusLog(lStatus); UpdateControls(); } catch (Exception lException) { ShowMessageBox("Failed to add and associate new application pool", lException); } } private void uxSetupPool_Click(object sender, EventArgs e) { try { var lStatus = new List<string>(); mIISManager.SetUpApplicationPool(uxApplicationPool.Text, uxUser.Text, uxPassword.Text, lStatus); AppendToStatusLog(lStatus); UpdateControls(); } catch (Exception lException) { ShowMessageBox("Failed to set up application pool", lException); } } private void uxCreateUserAndGroup_Click(object sender, EventArgs e) { if (ReportMissingParameters()) return; var lAd = new PdActiveDirectory(); try { AppendToStatusLog("CREATE USER AND GROUP"); var lUserGroup = uxUserGroup.Text; var lUser = uxUser.Text; lAd.CreateLocalUserGroup(lUserGroup, $"{mConst.ApplicationName} User Group"); AppendToStatusLog($"* Created user group ({lUserGroup})"); var lPassword = uxPassword.Text; lAd.CreateLocalUser(lUser, lPassword, $"{mConst.ApplicationName} User"); AppendToStatusLog($"* Created user ({lUser})"); lAd.AddUserToGroup(lUser, lUserGroup); AppendToStatusLog($"* Added user ({lUser}) to group ({lUserGroup})"); const string lIUSRS = "IIS_IUSRS"; if (lAd.GroupExists(lIUSRS)) { lAd.AddUserToGroup(lUser, lIUSRS); AppendToStatusLog($"* Added user ({lUser}) to group ({lIUSRS})"); } else { AppendToStatusLog($"* ({lIUSRS}) group not found. (Is IIS installed?)"); } if (lAd.GroupExists("DB2USERS")) { lAd.AddUserToGroup(lUser, "DB2USERS"); AppendToStatusLog("* Added user ({lUser}) to group DB2USERS"); } } catch (Exception lException) { ShowMessageBox("cmAddAccounts Failed", lException); } } private void StatusCallback(string aStatus) { uxStatus.Text = aStatus; uxStatus.Update(); } private void uxAssignFolderSecurity_Click(object sender, EventArgs e) { var lAd = new PdActiveDirectory(); var lOldCursor = Cursor.Current; Cursor.Current = Cursors.WaitCursor; try { try { var lUserGroup = uxUserGroup.Text; AppendToStatusLog("ASSIGN FOLDER SECURITY"); try { lAd.AddDirectorySecurity(mConst.PubFolder, lUserGroup, FileSystemRights.Modify | FileSystemRights.ListDirectory | FileSystemRights.Read | FileSystemRights.Write, AccessControlType.Allow, StatusCallback); AppendToStatusLog($"* Gave group {lUserGroup} modify/list/read/write permissions to {mConst.PubFolder}"); } catch (Exception ePubFolder) { ShowException( $"Failed to gave group {lUserGroup} modify/list/read/write permissions to {mConst.PubFolder}", ePubFolder); throw; } try { lAd.AddDirectorySecurity(mConst.IsapiFolder, lUserGroup, FileSystemRights.ListDirectory | FileSystemRights.ReadAndExecute, AccessControlType.Allow, StatusCallback); AppendToStatusLog($"* Gave group {lUserGroup} read .&. execute permissions to {mConst.IsapiFolder}"); } catch (Exception eIsapiFolder) { ShowException( $"Failed to gave group {lUserGroup} modify/list/read/write permissions to {mConst.IsapiFolder}", eIsapiFolder); throw; } } catch (Exception lException) { ShowMessageBox("cmAddAccounts Failed", lException); } } finally { Cursor.Current = lOldCursor; } } private void uxRefresh_Click(object sender, EventArgs e) { mIISManager.ReLoad(); UpdateControls(); } private void uxPrepareSiteAndApplication_Click(object sender, EventArgs e) { try { PrepareSiteAndApplication(uxWebSite.Text, uxApplication.Text.Substring(uxApplication.Text.IndexOf("/", StringComparison.Ordinal))); } catch (Exception lException) { var lCurEx = lException; while (lCurEx != null) { AppendToStatusLog(lCurEx.Message); lCurEx = lCurEx.InnerException; } } } private void uxWebSite_SelectedIndexChanged(object sender, EventArgs e) { UpdateControls(); } private void uxApplication_SelectedIndexChanged(object sender, EventArgs e) { UpdateControls(); } private void uxClear_Click(object sender, EventArgs e) { uxStatusLog.Clear(); } private void uxInstanceName_Leave(object sender, EventArgs e) { ReCreatecmConst(true); } private void uxInstanceName_TextChanged(object sender, EventArgs e) { ReCreatecmConst(true); } private bool RunningAsAdmin() { try { var lIdentity = WindowsIdentity.GetCurrent(); var lPrincipal = new WindowsPrincipal(lIdentity); return lPrincipal.IsInRole(WindowsBuiltInRole.Administrator); } catch { return false; } } private void uxInstanceName_DropDown(object sender, EventArgs e) { RePopulateInstanceList(uxConfigureInstanceList.Items); } private void uxInstallerFolder_Click(object sender, EventArgs e) { uxSelectInstallerFolder.RootFolder = Environment.SpecialFolder.CommonApplicationData; uxSelectInstallerFolder.SelectedPath = mConst.DefaultInstallersFolder; if (uxSelectInstallerFolder.ShowDialog() == DialogResult.OK) { mConst.InstallersFolder = uxSelectInstallerFolder.SelectedPath; uxInstallerFolder.Text = mConst.InstallersFolder; } } private void uxInstallerFolder_TextChanged(object sender, EventArgs e) { mConst.InstallersFolder = uxInstallerFolder.Text; RePopulateInstallers( mConst.InstallersFolder); if (uxInstallerList.Items.Count > 0) { uxInstallerList.SelectedIndex = 0; } } private void InstallUpgradeChanged(object sender, EventArgs e) { if (uxSelectNewInstance.Checked) { uxNewInstanceControls.Show(); uxNewInstanceNameControls.Show(); uxUpgradeInstanceNameControls.Hide(); } else { RePopulateInstanceList(uxUpgradeInstanceList.Items); if (uxUpgradeInstanceList.Items.Count > 0) { uxUpgradeInstanceList.SelectedIndex = 0; } uxNewInstanceControls.Hide(); uxNewInstanceNameControls.Hide(); uxUpgradeInstanceNameControls.Show(); } UpdateCopyFilesDescription(); } private void uxUseDefaultInstance_CheckedChanged(object sender, EventArgs e) { if (uxUseDefaultInstance.Checked) { uxNewInstance.Text = mConst.DefaultInstanceName; uxNewInstance.Visible = false; } else { uxNewInstance.Text = string.Empty; uxNewInstance.Visible = true; } UpdateCopyFilesDescription(); } private void uxNewInstance_TextChanged(object sender, EventArgs e) { if (mConst.InstanceExistsP(uxNewInstance.Text)) { uxNewInstance.BackColor = Color.LightPink; } else if (!mConst.ValidNewInstanceNameP(uxNewInstance.Text)) { uxNewInstance.BackColor = Color.LightPink; } else { uxNewInstance.BackColor = Color.LightGreen; } UpdateCopyFilesDescription(); } private void uxConfigureInstanceList_DropDownClosed(object sender, EventArgs e) { if (uxConfigureInstanceList.Text == string.Empty) { uxConfigureInstanceList.Text = mConst.DefaultInstanceName; } } private void UpdateCopyFilesDescription() { var lInstanceName = uxSelectNewInstance.Checked ? uxNewInstance.Text : uxUpgradeInstanceList.Text; var lNewVersion = ExtractZipVersion($@"{uxInstallerFolder.Text}\{uxInstallerList.Text}"); var lIsapiFileName = $@"{mConst.IsapiFolderP(lInstanceName)}\CrashMagicOnline_ISAPI.dll"; string lExistingVersion; if (File.Exists(lIsapiFileName)) { var lFileVersion = FileVersionInfo.GetVersionInfo(lIsapiFileName); lExistingVersion = lFileVersion.FileVersion; } else { lExistingVersion = "Existing program version not available"; } uxCopyFilesDescription.Text = uxSelectNewInstance.Checked ? $"Install new instance of Crash Magic (v{lNewVersion}) named '{mConst.FullInstanceNameP(lInstanceName)}'" : $"Upgrade existing (v{lExistingVersion}) instance of Crash Magic named '{mConst.FullInstanceNameP(lInstanceName)}' to v{lNewVersion}"; } private bool ValidControlValues() { string lInstanceName = uxSelectNewInstance.Checked ? uxNewInstance.Text : uxUpgradeInstanceList.Text; string lInstallerPackage = uxInstallerList.Text; if (lInstallerPackage == string.Empty) { MessageBox.Show("Please select an install package and try again.", "Crash Magic Online Installation", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } if (uxSelectNewInstance.Checked) { if (mConst.InstanceExistsP(lInstanceName)) { MessageBox.Show( "The specified instance already exists. Please select a different instance name or upgrade an existing one.", "Crash Magic Online Installation", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } else if (!mConst.ValidNewInstanceNameP(lInstanceName)) { MessageBox.Show("Instance names may only contain letters and numbers, no special characters.", "Crash Magic Online Installation", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } } else if (uxSelectUpgradeInstance.Checked) { if (uxUpgradeInstanceList.SelectedIndex < 0) { MessageBox.Show( "Please select an instance to upgrade, or choose to Install a New Crash Magic Instance.", "Crash Magic Online Installation", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } } if (uxSelectNewInstance.Checked) { if (MessageBox.Show($"Install {uxInstallerList.Text} as a new instanced called {lInstanceName}?", "Crash Magic Online Installation", MessageBoxButtons.YesNo) != DialogResult.Yes) { return false; } } else //(uxSelectUpgradeInstance.Checked) { if (MessageBox.Show($"Upgrade existing instance {lInstanceName} to {uxInstallerList.Text}?", "Crash Magic Online Installation", MessageBoxButtons.YesNo) != DialogResult.Yes) { return false; } } return true; } private string ExtractZipVersion(string aFileName) { var lVersion = "INSTALL PACKAGE VERSION NOT FOUND"; try { using (ZipArchive lArchive = ZipFile.OpenRead(aFileName)) { var lResult = from currEntry in lArchive.Entries where Path.GetDirectoryName(currEntry.FullName) == "ProgramData" where currEntry.Name == "cmVersionNumber.txt" select currEntry; foreach (ZipArchiveEntry lEntry in lResult) { var lFileName = Path.GetTempFileName(); lEntry.ExtractToFile(lFileName, true); lVersion = File.ReadAllText(lFileName); File.Delete(lFileName); } } } catch( Exception lExtract) { lVersion = "ERROR READING INSTALL PACKAGE: " + lExtract.Message; } return lVersion; } private void uxExtractFiles_Click(object sender, EventArgs e) { if (!ValidControlValues()) { return; } string lInstanceName = uxSelectNewInstance.Checked ? uxNewInstance.Text : uxUpgradeInstanceList.Text; lInstanceName = mConst.NameWithInstanceP("", lInstanceName ); string lInstallerPackage = uxInstallerList.Text; string lZipFileName = $@"{uxInstallerFolder.Text}\{uxInstallerList.Text}"; try { using (var lArchive = ZipFile.OpenRead(lZipFileName)) { uxProgress.Minimum = 0; uxProgress.Maximum = lArchive.Entries.Count; uxProgress.Step = 1; var lDestinationBasePath = string.Empty; foreach (var lEntry in lArchive.Entries) { uxProgress.PerformStep(); uxProgress.Text = lEntry.Name; var lCleanedFullName = lEntry.FullName.Replace("/", "\\"); if (lEntry.FullName.StartsWith("Common")) { lDestinationBasePath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)}\PdMagic\Common"; lCleanedFullName = lCleanedFullName.Substring("Common".Length + 1); } else if (lEntry.FullName.StartsWith("ProgramData")) { lDestinationBasePath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}\PdMagic\CrashMagicOnline{lInstanceName}"; lCleanedFullName = lCleanedFullName.Substring("ProgramData".Length + 1); } else if (lEntry.FullName.StartsWith("ProgramFiles")) { lDestinationBasePath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)}\PdMagic\CrashMagicOnline{lInstanceName}"; lCleanedFullName = lCleanedFullName.Substring("ProgramFiles".Length + 1); } else if (lEntry.FullName.StartsWith("System32")) { lDestinationBasePath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.SystemX86)}"; lCleanedFullName = lCleanedFullName.Substring("System32".Length + 1); } var lFullFileName = Path.Combine(lDestinationBasePath, lCleanedFullName); var lJustPath = Path.GetDirectoryName(lFullFileName); if ((lJustPath != null) .&. (lJustPath != string.Empty)) { Directory.CreateDirectory(lJustPath); } lEntry.ExtractToFile(lFullFileName, true); } } MessageBox.Show("File copy completed"); } catch (Exception eZip) { MessageBox.Show("File copy failed: " + eZip.Message); } uxProgress.Value = 0; } private void uxVersions_Click(object sender, EventArgs e) { var lVersionsDlg = new NewVersionDownloads(); lVersionsDlg.Initialize( mConst ); lVersionsDlg.ShowDialog(); RePopulateInstallers( mConst.InstallersFolder ); } private void uxInstallerList_SelectedValueChanged(object sender, EventArgs e) { UpdateCopyFilesDescription(); } private void uxUpgradeInstanceList_SelectedValueChanged(object sender, EventArgs e) { UpdateCopyFilesDescription(); } private void uxInstallerList_DropDown(object sender, EventArgs e) { RePopulateInstallers(mConst.InstallersFolder); } } }