Click here to Skip to main content
11,493,171 members (63,735 online)
Click here to Skip to main content
Add your own
alternative version

dotNetInstaller - Setup Bootstrapper for .NET Application

, 4 Jan 2004 MIT 595.3K 1.8K 309
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.
dotnetinstaller_source.zip
dotNetInstaller_source
dotNetInstaller
dotNetInstaller.vcproj.vspscc
dotNetInstaller.vssscc
mssccprj.scc
res
banner.bmp
dotNetInstaller.ico
dotNetInstaller.manifest
Thumbs.db
vssver.scc
Tools
vssver.scc
vssver.scc
InstallerEditor
App.ico
banner.bmp
bin
Release
InstallerEditor.exe
SourceLibrary.dll
vssver.scc
InstallerEditor.csproj.user
InstallerEditor.csproj.vspscc
InstallerEditor.suo
InstallerEditor.vssscc
mssccprj.scc
References
SourceLibrary.dll
vssver.scc
Thumbs.db
vssver.scc
Sample
banner.bmp
dotNetInstaller.exe
SupportFiles
DataAccess
Jet
Jet40Sp7
Win2000_English
Win2000_Italiano
Win9x_NT
WinME
WinXp_English
WinXp_Italiano
MDAC2.7Sp1Refresh
Win_98_ME_NT_2000
dotNet
v1.1
English
Italiano
InternetExplorer
IE60SP1_English
IE60SP1_Italiano
ServicePack
2000_SP4_English
2000_SP4_Italiano
NT4_SP6a_English
NT4_SP6a_Italiano
Win98_Y2k_Update_English
Win98_Y2k_Update_Italiano
#pragma once

#include <vector>
#include "ExecCmd.h"
#include "VersionCompare.h"
#include "Path.h"
#include "File.h"
#include "DownloadDialogSupport.h"
#include "DownloadDialog.h"

//in tutti i percorsi viene sostituito #APPPATH con il percorso dell'applicazione corrente, #SYSTEMPATH con la directory System del computer e #WINDOWSPATH con la directory di installazione di Windows, #TEMPPATH con la directory temporanea
//in all the paths we replace the string constant #APPPATH with the current path of the application and #SYSTEMPATH with the system directory of the computer, #TEMPPATH with the temp directory

#define c_APPPATH "#APPPATH"
#define c_SYSTEMPATH "#SYSTEMPATH"
#define c_WINDOWSPATH "#WINDOWSPATH"
#define c_TEMPPATH "#TEMPPATH"

enum component_type
{
	cmd, //shell command
	msi, //windows installer setup
	openfile //ShellExecute call to open a file
};

struct installedcheck
{
	virtual bool IsInstalled() = 0;
};

struct installedcheck_check_registry_value : public installedcheck
{
	CString path; //percorso del registry
	CString fieldname; //nome del campo del registry
	CString fieldvalue; //valore del registry bisogna convertirlo in base al tipo
	CString fieldtype; //tipo del campo nel registry : REG_DWORD (long) o REG_SZ  (string)
	CString comparison; //tipo di comparazione : match (verifica se le due stringhe sono uguali) version (che tratta le due stringhe come versioni e quindi se quella richiesta � minore bisogna installare altrimenti no)

	virtual bool IsInstalled()
	{
		try
		{
			HKEY l_HKey;
			LONG l_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
						path,
						0,
						KEY_READ,
						&l_HKey);

			if (l_result != ERROR_SUCCESS)
				return false;

			if (fieldtype == "REG_DWORD")
			{
				DWORD l_value;
				DWORD l_dwordLen = sizeof(DWORD);
				DWORD l_type = REG_DWORD;
				l_result = RegQueryValueEx(l_HKey,fieldname, NULL, &l_type, (LPBYTE)&l_value, &l_dwordLen);
				if (l_result != ERROR_SUCCESS)
				{
					RegCloseKey(l_HKey);
					return false;
				}

				RegCloseKey(l_HKey);

				DWORD l_checkValue;
				if (sscanf(fieldvalue, "%d", &l_checkValue) != 1)
				{
					AfxMessageBox("Invalid registry value to check expected DWORD.", MB_OK|MB_ICONSTOP);
					return false;
				}

				if (comparison == "match")
				{
					if (l_checkValue == l_value)
						return true;
					else
						return false;
				}
				else if (comparison == "version")
				{
					if (l_checkValue <= l_value)
						return true;
					else
						return false;
				}
				else
				{
					AfxMessageBox("Invalid comparison type, expected match or version.", MB_OK|MB_ICONSTOP);
					return false;
				}
			}
			else if (fieldtype == "REG_SZ")
			{
				DWORD l_dwordLen = 0;
				DWORD l_type = REG_SZ;
				l_result = RegQueryValueEx(l_HKey,fieldname, NULL, &l_type, NULL, &l_dwordLen);
				if (l_result != ERROR_SUCCESS)
				{
					RegCloseKey(l_HKey);
					return false;
				}

				TCHAR * l_value = new TCHAR[l_dwordLen+1];
				ZeroMemory(l_value,l_dwordLen+1);

				l_result = RegQueryValueEx(l_HKey,fieldname, NULL, &l_type, (LPBYTE)l_value, &l_dwordLen);
				if (l_result != ERROR_SUCCESS)
				{
					RegCloseKey(l_HKey);
					return false;
				}

				RegCloseKey(l_HKey);

				if (comparison == "match")
				{
					if (fieldvalue == l_value)
						return true;
					else
						return false;
				}
				else if (comparison == "version")
				{
					if ( DVLib::stringVersionCompare(fieldvalue, l_value) <= 0 )
						return true;
					else
						return false;
				}
				else
				{
					AfxMessageBox("Invalid comparison type, expected match or version.", MB_OK|MB_ICONSTOP);
					return false;
				}
			}
			else
			{
				RegCloseKey(l_HKey);

				AfxMessageBox("Invalid registry type", MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		catch(...)
		{
			return false;
		}
	}
};

struct installedcheck_check_file : public installedcheck
{
	CString filename; //percorso del file da cercare
	CString fileversion; //versione del file (se "" non viene verificata la versione ma solo la presenza del file)
	CString comparison; //tipo di comparazione : match (verifica se le due stringhe sono uguali) version (che tratta le due stringhe come versioni e quindi se quella richiesta � minore bisogna installare altrimenti no)

	virtual bool IsInstalled()
	{
		try
		{
			if (DVLib::FileExists(filename))
			{
				if (fileversion.GetLength()>0)
				{
					CString l_FileVersion = DVLib::GetFileVersionString(filename);

					if (comparison == "match")
					{
						if (l_FileVersion == fileversion)
							return true;
						else
							return false;
					}
					else if (comparison == "version")
					{
						//se la versione � uguale o maggiore
						if (DVLib::stringVersionCompare(l_FileVersion, fileversion) >= 0)
							return true;
						else
							return false;
					}
					else
					{
						AfxMessageBox("Invalid comparison type, expected match or version.", MB_OK|MB_ICONSTOP);
						return false;
					}
				}
				else
					return true;
			}
			else
				return false;
		}
		catch(...)
		{
			return false;
		}
	}
};

struct component
{
	//tipo di componente: cmd, msi, openfile
	component_type type;
	//descrizione
	CString description;
	//filtro che indica il minimo sistema operativo in cui lanciare il componente (estremo escluso)
	CString os_filter_greater;
	//filtro che indica il massimo sistema operativo in cui lanciare il componente (estremo escluso)
	CString os_filter_smaller;
	//filtro che indica il filtro per lingua del sistema operativo (es. Italy = 1040, English - United Kingdom = 2057, English - United States = 1033)
	CString os_filter_lcid;
	//Testo visualizzato quando si installa il componente
	CString installmessage;
	//testo da visualizzare a fine installazione (se vuoto non visualizza niente)
	CString installcompletemessage;
	//true per forzare il reboot al termine dell'installazione altrimenti false
	bool mustreboot;

	//classi per gestire la verifica se il componente � installato o no
	std::vector<installedcheck*> installedchecks;

	//Informazioni sull'eventuale download dei componenti (fa riferimento al nodo downloaddialog all'interno di component, se non � presente non viene scaricato nessun componente)
	DVLib::DownloadGroupConfiguration DownloadDialogConfiguration;
	//indica se il componente contiene o meno dei componenti da scaricare (in pratica dice se il nodo downloaddialog � presente o no)
	bool ContainsDownloadComponent;

	//scarica gli eventuali componenti necesari e restituisce true se il download ha avuto successo
	bool DownloadComponents()
	{
		try
		{
			if (ContainsDownloadComponent)
				return RunDownloadDialog(DownloadDialogConfiguration);
			else
				return true;
		}
		catch(...)
		{
			return false;
		}
	}

	//virtual bool ExecWait(DWORD * pExitCodes) = 0;

	//funzione virtuale specifica per il tipo di componente
	virtual bool Exec() = 0;

	virtual DWORD GetExitCode() = 0;
	virtual bool IsExecuting() = 0;

	bool IsInstalled()
	{
		if (installedchecks.size() == 0)
			return false;

		bool l_installed = true;
		for (size_t j = 0; j < installedchecks.size(); j++)
		{
			l_installed = l_installed && installedchecks[j]->IsInstalled();
		}
		return l_installed;
	}

};

struct process_component : public component
{
	//Informazioni sul processo in eseguzione
	PROCESS_INFORMATION m_process_info;

	virtual DWORD GetExitCode()
	{
		DWORD l_ExitCode;
		if (GetExitCodeProcess(m_process_info.hProcess, &l_ExitCode))
		{
			return l_ExitCode;
		}
		else
		{
			_ASSERT(false);
			throw -1;
		}
	}
	virtual bool IsExecuting()
	{
		DWORD l_ExitCode;
		if (GetExitCodeProcess(m_process_info.hProcess, &l_ExitCode))
		{
			if (l_ExitCode == STILL_ACTIVE)
				return true;
			else
				return false;
		}
		else
			return false;
	}
};

struct cmd_component : public process_component
{
	CString command;

/*	virtual bool ExecWait(DWORD * pExitCodes)
	{
		return DVLib::ExecCmdAndWait(command, pExitCodes);
	};*/

	virtual bool Exec()
	{
		return DVLib::ExecCmd(command, &m_process_info);
	};
};

struct msi_component : public process_component
{
	CString package;
	CString cmdparameters; // es. "/qn REBOOT=ReallySuppress"

	// msi install cmd-line
	//const TCHAR g_tszMsiCmdLine[] = _T("Msiexec /I %s REBOOT=ReallySuppress");

	/*virtual bool ExecWait(DWORD * pExitCodes)
	{
		CString l_command = "msiexec /I ";
		l_command += "\"";
		l_command += package;
		l_command += "\"";
		l_command += " ";
		l_command += cmdparameters;
		//if (silent)
		//	l_command += " /qn";
		//if (suppressreboot)
		//	l_command += " REBOOT=ReallySuppress";

		return DVLib::ExecCmdAndWait(l_command, pExitCodes);
	};*/

	virtual bool Exec()
	{
		CString l_command = "msiexec /I ";
		l_command += "\"";
		l_command += package;
		l_command += "\"";
		l_command += " ";
		l_command += cmdparameters;
		//if (silent)
		//	l_command += " /qn";
		//if (suppressreboot)
		//	l_command += " REBOOT=ReallySuppress";

		return DVLib::ExecCmd(l_command, &m_process_info);
	};
};

//open a file with a shellexecute call
struct openfile_component : public component
{
	CString file; //file to open. Can be a web link or a standard file

	virtual bool Exec()
	{
		HINSTANCE l_hInstance = ShellExecute(NULL,NULL,file,NULL,NULL,SW_SHOWNORMAL);
		if ( l_hInstance <= (HINSTANCE)32 )
			return false;
		else
			return true;
	}
	virtual DWORD GetExitCode()
	{
		return ERROR_SUCCESS;
	}
	virtual bool IsExecuting()
	{
		return false;
	}
};


struct installerSetting
{
	CString dialog_caption;
	CString dialog_message;
	CString dialog_bitmap;
	CString install_caption;
	CString cancel_caption;
	CString reinstallflag_caption;
	CString status_installed;
	CString status_notinstalled;
	CString failed_exec_command_continue;
	CString installation_completed;
	CString reboot_required;
	CString dialog_install_next;
	CString dialog_install_skip;
	CString installing_component_wait;

	std::vector<component*> components;
};

// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
#define c_dotNetInstaller "dotNetInstallerBoot"
//#define c_RunOnce "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"
#define c_Reg_Run "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"

inline void InsertRegistryRun()
{
	try
	{
		HKEY l_HKey;
		LONG l_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
					c_Reg_Run,
					0,
					KEY_WRITE,
					&l_HKey);
		if (l_result != ERROR_SUCCESS)
			return;

		CString l_ExeName = DVLib::GetAppFullName();
		RegSetValueEx(l_HKey, c_dotNetInstaller,0,REG_SZ,(LPBYTE)(LPCTSTR)l_ExeName, (DWORD)(l_ExeName.GetLength()+1) );

		RegCloseKey(l_HKey);
	}
	catch(...)
	{
		_ASSERT(false);
	}
};

inline void RemoveRegistryRun()
{
	try
	{
		HKEY l_HKey;
		LONG l_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
					c_Reg_Run,
					0,
					KEY_WRITE,
					&l_HKey);
		if (l_result != ERROR_SUCCESS)
			return;

		RegDeleteValue(l_HKey, c_dotNetInstaller);

		RegCloseKey(l_HKey);
	}
	catch(...)
	{
		_ASSERT(false);
	}
};

// ==========================================================================
// InitiateReboot()
//
// Purpose: initiates a system reboot
//
// ==========================================================================
inline BOOL InitiateReboot()
{
    HANDLE hToken;              // handle to process token 
    TOKEN_PRIVILEGES tkp;       // pointer to token structure     
     
    try 
    {
        // Get the current process token handle so we can get shutdown 
        // privilege. 
         
        if (!OpenProcessToken(GetCurrentProcess(), 
                TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        {
           // return FALSE;
        }
         
        // Get the LUID for shutdown privilege. 
         
        LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 
                &tkp.Privileges[0].Luid); 
         
        tkp.PrivilegeCount = 1;  // one privilege to set    
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
         
        // Get shutdown privilege for this process. 
         
        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 
            (PTOKEN_PRIVILEGES) NULL, 0); 
         
        // Cannot test the return value of AdjustTokenPrivileges. 
         
        if (GetLastError() != ERROR_SUCCESS) 
        {
           // return FALSE;
        }
    }

    catch (...)
    {
    }
    return ExitWindowsEx( EWX_REBOOT, 0);
}

inline CString ValidatePath(LPCTSTR p_Path)
{
	//ApplicationPath
	CString l_CurrentPath = DVLib::GetAppPath();

	//SystemPath
	TCHAR l_bufferSystem[MAX_PATH+1];
	ZeroMemory(l_bufferSystem,MAX_PATH+1);
	GetSystemDirectory(l_bufferSystem, MAX_PATH+1);

	//WindowsPath
	TCHAR l_bufferWindows[MAX_PATH+1];
	ZeroMemory(l_bufferWindows,MAX_PATH+1);
	GetWindowsDirectory(l_bufferWindows, MAX_PATH+1);

	//TempPath
	TCHAR l_bufferTempPath[MAX_PATH+1];
	ZeroMemory(l_bufferTempPath,MAX_PATH+1);
	GetTempPath(MAX_PATH+1, l_bufferTempPath);

	CString tmp = p_Path;
	tmp.Replace(c_APPPATH, l_CurrentPath);
	tmp.Replace(c_SYSTEMPATH, l_bufferSystem);
	tmp.Replace(c_WINDOWSPATH, l_bufferWindows);
	tmp.Replace(c_TEMPPATH, l_bufferTempPath);

	return tmp;
}

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

Share

About the Author

Davide Icardi
Software Developer
Italy Italy
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150520.1 | Last Updated 5 Jan 2004
Article Copyright 2003 by Davide Icardi
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid