Click here to Skip to main content
15,895,746 members
Articles / Desktop Programming / MFC

dotNetInstaller - Setup Bootstrapper for .NET Application

Rate me:
Please Sign up or sign in to vote.
4.96/5 (87 votes)
4 Jan 2004MIT22 min read 1M   2.2K   310  
With this tool the developer can define the application prerequisites and install the correct version of these components in the correct order based on the user operating system type and language, allow the user to download these components from the web or install these components directly.
#pragma once

#include "XMLite.h"
#include "InstallerTypes.h"
#include "DownloadDialogSupport.h"
#include "DownloadDialog.h"
#include "OsIdentifier.h"
#include "Image.h"
//#include <atlimage.h>

void LoadConfigFile(CString p_FileName, installerSetting & p_Setting);

inline bool ConvBoolString(const CString & p_BoolString)
{
	CString l_tmp = p_BoolString;
	if (l_tmp.MakeLower() == "true")
		return true;
	else if (l_tmp.MakeLower() == "false")
		return false;
	else
	{
		_ASSERT(false); //non riconosciuto (default false)
		return false;
	}
}

inline void LoadDownloadConfiguration(XNode * p_Node_downloaddialog, DVLib::DownloadGroupConfiguration & p_Configuration)
{
	p_Configuration.Caption = p_Node_downloaddialog->GetAttrValue("dialog_caption");
	p_Configuration.HelpMessage = p_Node_downloaddialog->GetAttrValue("dialog_message");
	p_Configuration.HelpMessageDownloading = p_Node_downloaddialog->GetAttrValue("dialog_message_downloading");
	p_Configuration.ButtonStartCaption = p_Node_downloaddialog->GetAttrValue("buttonstart_caption");
	p_Configuration.ButtonCancelCaption = p_Node_downloaddialog->GetAttrValue("buttoncancel_caption");
	p_Configuration.AutoStartDownload = ConvBoolString(p_Node_downloaddialog->GetAttrValue("autostartdownload"));

	p_Configuration.Components.RemoveAll();

	LPXNode l_Node_downloads = p_Node_downloaddialog->GetChild("downloads");
	for (size_t i = 0; i < l_Node_downloads->GetChildCount(); i++)
	{
		LPXNode l_Node_download = l_Node_downloads->GetChild(i);
		if (l_Node_download->name == "download")
		{
			DVLib::DownloadComponentInfo l_DownloadComp;
			l_DownloadComp.ComponentName = l_Node_download->GetAttrValue("componentname");
			l_DownloadComp.SourceURL = ValidatePath(l_Node_download->GetAttrValue("sourceurl"));
			l_DownloadComp.DestinationPath = ValidatePath(l_Node_download->GetAttrValue("destinationpath"));
			l_DownloadComp.DestinationFileName = ValidatePath(l_Node_download->GetAttrValue("destinationfilename"));
			p_Configuration.Components.Add(l_DownloadComp);
		}
	}

	if (p_Configuration.Components.GetCount() <= 0)
	{
		AfxMessageBox("No download components found. downloads node is empty.", MB_OK|MB_ICONSTOP);
		throw -1;
	}
}

inline void LoadInstallConfigNode(XNode * p_Node, installerSetting & p_Setting)
{
	p_Setting.cancel_caption = p_Node->GetAttrValue("cancel_caption");
	p_Setting.dialog_bitmap = ValidatePath(p_Node->GetAttrValue("dialog_bitmap"));
	p_Setting.dialog_caption = p_Node->GetAttrValue("dialog_caption");
	p_Setting.dialog_message = p_Node->GetAttrValue("dialog_message");
	p_Setting.install_caption = p_Node->GetAttrValue("install_caption");
	p_Setting.reinstallflag_caption = p_Node->GetAttrValue("reinstallflag_caption");
	p_Setting.status_installed = p_Node->GetAttrValue("status_installed");
	p_Setting.status_notinstalled = p_Node->GetAttrValue("status_notinstalled");
	p_Setting.failed_exec_command_continue = p_Node->GetAttrValue("failed_exec_command_continue");
	p_Setting.installation_completed = p_Node->GetAttrValue("installation_completed");
	p_Setting.reboot_required = p_Node->GetAttrValue("reboot_required");
	p_Setting.dialog_install_next = p_Node->GetAttrValue("dialog_install_next");
	p_Setting.dialog_install_skip = p_Node->GetAttrValue("dialog_install_skip");
	p_Setting.installing_component_wait = p_Node->GetAttrValue("installing_component_wait");

	//caricamento componenti
	DVLib::OperatingSystem l_CurrentOs = DVLib::GetOsVersion();
	p_Setting.components.clear();
	LPXNode l_Node_components = p_Node->GetChild("components");
	for (size_t i = 0; i < l_Node_components->GetChildCount(); i++)
	{
		LPXNode l_Node_component = l_Node_components->GetChild(i);
		CString l_comp_type = l_Node_component->GetAttrValue("type");

		component * l_new_component;

		if (l_comp_type == "msi")
		{
			msi_component * l_msi_Comp = new msi_component(); //TODO must delete this memory
			l_msi_Comp->package = ValidatePath(l_Node_component->GetAttrValue("package"));
			l_msi_Comp->type = msi;
			l_msi_Comp->cmdparameters = ValidatePath(l_Node_component->GetAttrValue("cmdparameters"));

			l_new_component = l_msi_Comp;
		}
		else if (l_comp_type == "cmd")
		{
			cmd_component * l_cmd_Comp = new cmd_component(); //TODO must delete this memory
			l_cmd_Comp->command = ValidatePath(l_Node_component->GetAttrValue("command"));
			l_cmd_Comp->type = cmd;

			l_new_component = l_cmd_Comp;
		}
		else if (l_comp_type == "openfile")
		{
			openfile_component * l_openfile_Comp = new openfile_component(); //TODO must delete this memory
			l_openfile_Comp->file = ValidatePath(l_Node_component->GetAttrValue("file"));
			l_openfile_Comp->type = openfile;

			l_new_component = l_openfile_Comp;
		}
		else
		{
			throw "Invalid configuration file, component type not supported";
		}

		l_new_component->description = l_Node_component->GetAttrValue("description");
		l_new_component->os_filter_greater = l_Node_component->GetAttrValue("os_filter_greater");
		l_new_component->os_filter_smaller = l_Node_component->GetAttrValue("os_filter_smaller");
		l_new_component->os_filter_lcid = l_Node_component->GetAttrValue("os_filter_lcid");
		l_new_component->installmessage = l_Node_component->GetAttrValue("installmessage");
		l_new_component->installcompletemessage = l_Node_component->GetAttrValue("installcompletemessage");
		l_new_component->mustreboot = ConvBoolString(l_Node_component->GetAttrValue("mustreboot"));

		// installed checks
		for (size_t j = 0; j < l_Node_component->GetChildCount(); j++)
		{
			LPXNode l_Node_installedcheck = l_Node_component->GetChild(j);
			if (l_Node_installedcheck->name == "installedcheck")
			{
				CString l_installedcheck_type = l_Node_installedcheck->GetAttrValue("type");
				installedcheck * l_new_installedcheck;
				if(l_installedcheck_type=="check_registry_value")
				{
					installedcheck_check_registry_value * l_new_check_registry_value = new installedcheck_check_registry_value;  //TODO must delete this memory

					l_new_check_registry_value->fieldname = l_Node_installedcheck->GetAttrValue("fieldname");
					l_new_check_registry_value->fieldtype = l_Node_installedcheck->GetAttrValue("fieldtype");
					l_new_check_registry_value->fieldvalue = l_Node_installedcheck->GetAttrValue("fieldvalue");
					l_new_check_registry_value->path = l_Node_installedcheck->GetAttrValue("path");
					l_new_check_registry_value->comparison = l_Node_installedcheck->GetAttrValue("comparison");

					l_new_installedcheck = l_new_check_registry_value;
				}
				else if(l_installedcheck_type=="check_file")
				{
					installedcheck_check_file * l_new_check_file = new installedcheck_check_file;  //TODO must delete this memory

					l_new_check_file->filename = ValidatePath(l_Node_installedcheck->GetAttrValue("filename"));
					l_new_check_file->fileversion = l_Node_installedcheck->GetAttrValue("fileversion");
					l_new_check_file->comparison = l_Node_installedcheck->GetAttrValue("comparison");

					l_new_installedcheck = l_new_check_file;
				}
				else
				{
					throw "Invalid configuration file, installed check type not supported";
				}

				l_new_component->installedchecks.insert(l_new_component->installedchecks.end(), l_new_installedcheck);
			}
		}



		// download dialog
		l_new_component->ContainsDownloadComponent = false; //default viene messo a falso e poi guardo se � presente il nodo
		LPXNode l_Node_downloaddialog = l_Node_component->GetChild("downloaddialog");
		if (l_Node_downloaddialog!=NULL)
		{
			LoadDownloadConfiguration(l_Node_downloaddialog, l_new_component->DownloadDialogConfiguration);
			l_new_component->ContainsDownloadComponent = true;
		}

		if ( DVLib::IsInRangedOs(l_CurrentOs, l_new_component->os_filter_greater, l_new_component->os_filter_smaller) 
			&& DVLib::IsOperatingSystemLCID(l_new_component->os_filter_lcid) )
			p_Setting.components.insert(p_Setting.components.end(), l_new_component);
	}
}

inline void LoadReferenceConfigNode(XNode * p_Node, installerSetting & p_Setting)
{
	LPXNode l_NodeDownloadDialog = p_Node->GetChild("downloaddialog");

	DVLib::DownloadGroupConfiguration l_DownloadConfig;
	LoadDownloadConfiguration(l_NodeDownloadDialog, l_DownloadConfig);

	if (RunDownloadDialog(l_DownloadConfig))
	{
		LPXNode l_Node_configfile = p_Node->GetChild("configfile");

		CString l_configfile_filename = ValidatePath(l_Node_configfile->GetAttrValue("filename"));
		//CString l_configfile_banner = ValidatePath(l_Node_configfile->GetAttrValue("banner"));

		LoadConfigFile(l_configfile_filename, p_Setting);
	}
	else
	{
		throw -1;
	}
}

inline void LoadConfigNode(XNode * p_Node, installerSetting & p_Setting)
{
	bool l_bFound = false;
	if (p_Node->name != "configurations")
		throw "Invalid configuration file, node name not supported, expected 'configurations'.";

	for (size_t i = 0; i < p_Node->GetChildCount(); i++)
	{
		LPXNode l_Node_configuration = p_Node->GetChild(i);

		if (l_Node_configuration->name == "configuration")
		{
			CString l_Config_LCID = l_Node_configuration->GetAttrValue("lcid");
			if (DVLib::IsOperatingSystemLCID(l_Config_LCID))
			{
				CString l_type = l_Node_configuration->GetAttrValue("type");
				if (l_type =="reference")
					LoadReferenceConfigNode(l_Node_configuration, p_Setting);
				else if (l_type =="install")
					LoadInstallConfigNode(l_Node_configuration, p_Setting);
				else
					throw "Invalid configuration file, configuration type not supported.";

				l_bFound = true;
				break;
			}
		}
	}

	if (l_bFound== false)
		throw "System not supported or invalid configuration, no valid 'configuration' node found.";
}
inline void LoadConfigFile(CString p_FileName, installerSetting & p_Setting)
{
	PARSEINFO l_parseInfo;
	XNode l_Node;
	bool l_ret = l_Node.LoadFromFile(p_FileName);
	if (l_ret==false)
		throw "Invalid configuration file, failed to parse XML elements.";

	LoadConfigNode(&l_Node, p_Setting);
}


inline HBITMAP LoadBannerFromResource(HMODULE p_Module)
{
	try
	{
		//leggo la risorsa
		HRSRC l_res = FindResource(p_Module, "RES_BANNER", "CUSTOM");
		if (l_res == NULL)
			throw -1;
		HGLOBAL l_hRes = LoadResource(p_Module, l_res);
		if (l_hRes == NULL)
			throw -1;
		DWORD l_size = SizeofResource(p_Module, l_res);

		LPVOID l_buffer = LockResource(l_hRes);
		if (l_buffer == NULL)
			throw -1;

		return DVLib::LoadBitmapFromBuffer(l_buffer, l_size);
	/*	
		// n.B. Questo pezzo di codice usava GDI+ e quindi non andava bene su sistemi operativi precedenti a Win XP

		HGLOBAL l_hGlobal = GlobalAlloc(GMEM_MOVEABLE, l_size);
		if (l_hGlobal==NULL)
			throw -1;
		LPVOID l_gBuffer = GlobalLock(l_hGlobal);
		CopyMemory(l_gBuffer, l_buffer, l_size);
		GlobalUnlock(l_hGlobal);

		CComPtr<IStream> l_pStream;
		HRESULT l_hrRet = CreateStreamOnHGlobal(l_hGlobal, FALSE, &l_pStream);
		if (FAILED(l_hrRet))
			throw -1;

		CImage l_Image;
		l_hrRet = l_Image.Load(l_pStream);
		if (FAILED(l_hrRet))
			throw -1;

		l_pStream.Release();
		//TODO controllare se � possibile liberare anche HGLOBAL - GlobalFree(l_hGlobal)
		return l_Image.Detach();
		*/
	}
	catch(...)
	{
		return NULL;
	}
}

inline void LoadConfigFromResource(HMODULE p_Module, installerSetting & p_Setting)
{
	HRSRC l_res = FindResource(p_Module, "RES_CONFIGURATION", "CUSTOM");
	if (l_res == NULL)
		throw "Resource RES_CONFIGURATION not found.";
	HGLOBAL l_hRes = LoadResource(p_Module, l_res);
	if (l_hRes == NULL)
		throw "Failed to load resource RES_CONFIGURATION.";
	LPVOID l_buffer = LockResource(l_hRes);
	if (l_buffer == NULL)
		throw "Failed to lock resource RES_CONFIGURATION.";
	DWORD l_size = SizeofResource(p_Module, l_res);
	TCHAR * l_bufferXml = new TCHAR[l_size+1];
	memset(l_bufferXml,0,l_size+1);
	memcpy(l_bufferXml, l_buffer, l_size);
	
	XNode l_Node;
	LPTSTR l_retLoad = l_Node.Load(l_bufferXml);
	if (l_retLoad==NULL)
		throw "Resource RES_CONFIGURATION is not a valid xml.";

	LoadConfigNode(&l_Node, p_Setting);

	delete [] l_bufferXml;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions