Win32 : Utilisation des fichiers INF et des Setup API


Création du programme InstallFromInf qui exploite un fichier INF pour copier, effacer, renommer des fichiers, ajouter ou supprimer des éléments dans la registry, mettre à jour des fichiers INI à partir des Setup API. La copie des fichiers fait apparaitre la boite de copie que l'on retrouve dans les programmes de setup standard.


De plus, lorsqu'un fichier est manquant, on retrouve la boite présente dans les applications du type service pack.



Le fichier INF possède une structure semblable à un fichier INI:
[Version]
Signature="$Windows 95$"
Provider=%Company%

[DestinationDirs]
MyDeleteFiles=65600
MyCopyFiles=65600
MyRenameFiles=65600

[Install]
DelReg=DelRegistry
AddReg=AddRegistry
CopyFiles=MyCopyFiles
UpdateInis=MajIni
 
[UnInstall]
DelReg=DelRegistry
DelFiles=MyDeleteFiles

[AddRegistry]
HKLM,"Software\%Company%\Data Access"
HKLM,"Software\%Company%\Data Access\SQL Server"
HKLM,"Software\%Company%\Data Access\SQL Server","Database",FLG_ADDREG_TYPE_SZ ,"Default"

[DelRegistry]
HKLM,"Software\%Company%\Data Access\SQL Server\Database"
HKLM,"Software\%Company%\Data Access\SQL Server"
HKLM,"Software\%Company%\Data Access"
HKLM,"Software\%Company%"

[MyCopyFiles]
source.txt
dest.txt
new.txt

[MyDeleteFiles]
source.txt
dest.txt
new.txt

[MajIni]
%65600%\cpicorp.ini,CORPORATION,,NAME="%Company%"
%65600%\cpicorp.ini,CORPORATION,,REGISTERED="2000"

[Strings]
Company="CPI Corporation" 

Dans les sections [Install] et [UnInstall], on renseigne les sections standards vers des sections dans le fichier courant.
Dans la section [DestinationDirs], on affecte les noms de section courant avec une variable qui représente le répertoire d'installation. Le nom de cette variable est fixé dans le code.
Pour les autres valeurs du fichier INF, des variables peuvent utilisées si elles sont définies dans la section [Strings].
Les sections [AddRegistry] et [Delregistry] manipulent la base de registres.
La section [MajIni] manipule les fichiers INI.
La section [MyCopyFiles] contient la liste des fichiers à copier et [MyDeleteFiles] la liste des fichiers à supprimer.

Le programme InstallFromInf est une application console:

// InstallFromInf.cpp : Defines the entry point for the console application.
//

//dans stdafx.h
//#include 
//#include "setupapi.h"
//#pragma comment(lib, "setupapi.lib")
//#include 
#include "stdafx.h"

void Usage()
{
	printf("Usage:\n");
	printf("InstallFromInf options\n");
	printf("-i : Install\n");
	printf("-u : UnInstall\n");
}

int main(int argc, char* argv[])
{
	#define CPI_INF "D:\\dev\\cpi\\Tools\\InstallFromInf\\Release\\cpi.inf"
	#define DESTINATION_PATH "d:\\dev\\cpi\\tools\\install"
	#define SOURCE_PATH "d:\\dev\\cpi\\tools\\installfrominf\\release"

	BOOL bInstall = FALSE;
	if( argc == 2 )
	{
		if( !strcmp(argv[1], "-i") )
			bInstall = TRUE;
		else if( !strcmp(argv[1], "-u") )
			bInstall = FALSE;
		else
		{
			Usage();
			return 1;
		}
	}
	else
	{
		Usage();
		return 1;
	}

	HINF hInfFile;
	UINT iError;
	hInfFile = SetupOpenInfFile(CPI_INF, NULL, INF_STYLE_WIN4, &iError);
	if( hInfFile == INVALID_HANDLE_VALUE )
	{
		printf("SetupOpenInfFile failed\n");
		return 1;
	}

	BOOL bResult = FALSE;

	bResult = SetupSetDirectoryId(hInfFile,(DWORD) 65600, DESTINATION_PATH);
	if( bResult == FALSE )
	{
		printf("SetupSetDirectoryId failed\n");
		return 1;
	}

	HSPFILEQ FileQueue;
	FileQueue = SetupOpenFileQueue();
	if(!FileQueue || (FileQueue == INVALID_HANDLE_VALUE)) 
	{
		printf("SetupOpenFileQueue failed\n");
		return 1;
	}

	PVOID pData;
	pData = SetupInitDefaultQueueCallbackEx(NULL, NULL, 0, 0, NULL);
	if(!(pData)) 
	{
		printf("SetupInitDefaultQueueCallbackEx failed\n");
		SetupCloseFileQueue(FileQueue);
		SetupCloseInfFile(hInfFile);
		return 1;
	}

	if( bInstall )
		bResult = SetupInstallFilesFromInfSection(hInfFile, NULL, FileQueue, "Install", SOURCE_PATH, SP_COPY_NEWER);
	else
		bResult = SetupInstallFilesFromInfSection(hInfFile, NULL, FileQueue, "UnInstall", SOURCE_PATH, SP_COPY_NEWER);
	if( bResult == FALSE )
	{
		printf("SetupInstallFilesFromInfSection failed\n");
		return 1;
	}

	bResult = SetupCommitFileQueue(NULL, FileQueue, (PSP_FILE_CALLBACK) SetupDefaultQueueCallback , pData);
	if( bResult == FALSE )
	{
		printf("SetupCommitFileQueue failed\n");
		return 1;
	}

	int iFlags = SPINST_REGISTRY | SPINST_INIFILES;
	if( bInstall )
		bResult = SetupInstallFromInfSection(NULL, hInfFile, "Install", iFlags, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	else
		bResult = SetupInstallFromInfSection(NULL, hInfFile, "UnInstall", iFlags, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	if( bResult == FALSE )
	{
		printf("SetupInstallFromInfSection failed\n");
		return 1;
	}

	SetupTermDefaultQueueCallback(pData);
	SetupCloseFileQueue(FileQueue);
	SetupCloseInfFile(hInfFile);
	return 0;
}


'InstallFromInf -i' permet de traiter la section INSTALL su fichier INF.
'InstallFromInf -u' permet de traiter la section UNINSTALL su fichier INF.

 

© 2001 Christophe Pichaud. All rights reserved.