campo-sirio/setup/Setup.cpp

1290 lines
47 KiB
C++
Raw Normal View History

//Il sorgente va scritto in notazione ungherese.
//Le variabili seguono la seguente regola: 'acronimo tipo'+'nome variabile cammellata'
//Es. wxArrayString 'as' + 'AcceptRefuse' -> asAcceptRefuse
#include "wxinc.h"
#ifdef WIN32
#include <shlobj.h>
#endif
#include <wx/protocol/http.h>
#include <wx/snglinst.h>
#include "key.h"
#include "wizard.h"
#include "utils.h"
///////////////////////////////////////////////////////////
// CampoFrame
///////////////////////////////////////////////////////////
class CampoFrame : public wxFrame
{
protected:
DECLARE_EVENT_TABLE();
virtual void OnErase(wxEraseEvent& e);
public:
CampoFrame();
};
BEGIN_EVENT_TABLE(CampoFrame, wxFrame)
EVT_ERASE_BACKGROUND(CampoFrame::OnErase)
END_EVENT_TABLE()
void CampoFrame::OnErase(wxEraseEvent& e)
{
//preparazione background
wxDC& dc = *e.GetDC();
const wxRect rect = GetClientSize();
wxColour c0 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT);
wxColour c1 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
wxColour c2 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW);
wxRect rect1 = rect; rect1.SetBottom(rect.GetBottom() / 2);
dc.GradientFillLinear(rect1, c0, c1, wxSOUTH);
wxRect rect2 = rect; rect2.SetTop(rect.GetBottom() / 2);
dc.GradientFillLinear(rect2, c1, c2, wxDOWN);
const int nHeight = rect.GetHeight()/10;
wxFont* pFont = wxTheFontList->FindOrCreateFont(nHeight, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC,
wxFONTWEIGHT_BOLD);
dc.SetFont(*pFont);
dc.SetBackgroundMode(wxTRANSPARENT);
const int k = nHeight / 16 + 1;
dc.SetTextForeground(c2);
dc.DrawText(APPNAME, k, k);
dc.SetTextForeground(c1);
dc.DrawText(APPNAME, k/2, k/2);
int w, h;
const wxString strSetup = wxT("Setup");
dc.GetTextExtent(strSetup, &w, &h);
dc.SetTextForeground(c2);
dc.DrawText(strSetup, rect.GetRight()-w-k/2, rect.GetHeight()-h-k/2);
dc.SetTextForeground(c1);
dc.DrawText(strSetup, rect.GetRight()-w-k, rect.GetHeight()-h-k);
}
CampoFrame::CampoFrame()
: wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0)
{
ShowFullScreen(true);
}
///////////////////////////////////////////////////////////
// CampoSetup
///////////////////////////////////////////////////////////
//classe principale, ovvero applicazione
class CampoSetup : public wxApp
{
CampoFrame* m_pMainFrame;
wxLocale m_locale;
wxString m_strSetupPath;
CampoWizard* m_pWizard;
private:
bool WriteRegistryKey(HKEY hBaseKey, const wxString strKey, const wxString& strValue) const;
wxString ReadRegistryKey(HKEY hBaseKey, const wxString strKey) const;
wxString GetFolderPath(unsigned int uPathID) const;
protected:
DECLARE_EVENT_TABLE()
//metodi principali dell'applicazione
void OnTimer(wxTimerEvent& e);
void DiskUpdate();
void InternetUpdate();
void ClientUpdate();
void NormalSetup();
bool CampoRunning(const wxString& strAppName, const wxString& strMsg) const;
bool LurchRunning() const;
//metodi di interfaccia con Windows
bool CreateIcon(unsigned int csidl, const wxFileName& strExeFile, const wxString& strLinkName) const;
void AssociateExtension(const wxFileName& strExeFile, const wxString strExt);
//...per i servers
bool CreateAutostartMode(const LurchMode iSrvAutostartMode, const wxString& strPath);
bool StopLurch() const;
bool StartLurch(const wxString& strPrgLocPath) const;
//metodi di interfaccia con il registry di Windows
wxString ReadRootRegistryKey(const wxString strKey) const;
wxString ReadLocalMachineRegistryKey(const wxString strKey) const;
bool WriteRootRegistryKey(const wxString strKey, const wxString& strValue) const;
bool WriteLocalMachineRegistryKey(const wxString strKey, const wxString& strValue) const;
//metodi di utility per i vari modi di aggiornamento
const wxString GetSourceDir(const wxString strDirName) const;
void EmptyOutDir(const wxString& strDir) const;
bool UnzipModule(const wxString& strPrgLocPath, const wxString& strSrc, const wxString& strModule) const;
void CopyDir(const wxString& strSourceDir, const wxString& strDestDir) const;
bool CopyFilesAndDirs(const wxString& FilesListI, wxString strFileCurr, const bool bIni) const;
void UpdateInstallIni(const wxString strSourcePath, const wxString strDestPath, const wxString& strModule) const;
bool HTTPGet(const wxString& strLocalPath, const wxString& strWebPath) const;
//metodi di aggiornamento non standard (client, da disco e via web con installazione moduli)
int ClientUpdateModule(const wxString& strLocalPath, const wxString& strRemotePath, const wxString strModule) const;
bool DiskUpdateModule(const wxString& strLocalPath, const wxString& strWebPath, const wxString strModule) const;
bool InternetUpdateModule(const wxString& strLocalPath, const wxString& strWebPath, const wxString strModule) const;
public:
virtual bool OnInit();
};
IMPLEMENT_APP(CampoSetup)
BEGIN_EVENT_TABLE(CampoSetup, wxApp)
EVT_TIMER(883, OnTimer)
END_EVENT_TABLE()
//----------------------------------------------------------------
// Metodi di lettura/scrittura registry di Windows (fantastici!)
//----------------------------------------------------------------
wxString CampoSetup::ReadRegistryKey(HKEY hBaseKey, const wxString strKey) const
{
wxString strValue;
HKEY hKey = NULL;
wxString strPath, strName;
wxFileName::SplitPath(strKey, &strPath, &strName, NULL);
bool ok = ::RegOpenKeyEx(hBaseKey, strPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS;
if (ok)
{
BYTE buff[512];
DWORD type = REG_SZ;
DWORD dw = sizeof(buff);
ok = ::RegQueryValueEx(hKey, strName, NULL, &type, buff, &dw) == ERROR_SUCCESS;
if (ok)
strValue = buff;
::RegCloseKey(hKey);
}
return strValue;
}
wxString CampoSetup::ReadRootRegistryKey(const wxString strKey) const
{
return ReadRegistryKey(HKEY_CLASSES_ROOT, strKey);
}
wxString CampoSetup::ReadLocalMachineRegistryKey(const wxString strKey) const
{
return ReadRegistryKey(HKEY_LOCAL_MACHINE, strKey);
}
bool CampoSetup::WriteRegistryKey(HKEY hBaseKey, const wxString strKey, const wxString& strValue) const
{
HKEY hKey = NULL;
DWORD dw = 0;
//splitta la stringa in path e valore
wxString strPath, strName;
wxFileName::SplitPath(strKey, &strPath, &strName, NULL);
bool ok = ::RegCreateKeyEx(hBaseKey, strPath, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hKey, &dw) == ERROR_SUCCESS;
if (ok)
{
ok = ::RegSetValueEx(hKey, strName, 0, REG_SZ,
(BYTE*)(const wxChar*)strValue, DWORD(2*strValue.Len()+2)) == ERROR_SUCCESS;
::RegCloseKey(hKey);
}
return ok;
}
bool CampoSetup::WriteRootRegistryKey(const wxString strKey, const wxString& strValue) const
{
return WriteRegistryKey(HKEY_CLASSES_ROOT, strKey, strValue);
}
bool CampoSetup::WriteLocalMachineRegistryKey(const wxString strKey, const wxString& strValue) const
{
return WriteRegistryKey(HKEY_LOCAL_MACHINE, strKey, strValue);
}
//----------------------------------
// Metodi di interfaccia con Windows
//----------------------------------
wxString CampoSetup::GetFolderPath(unsigned int uPathID) const
{
TCHAR szPath[MAX_PATH] = wxT("");
HRESULT hres = ::SHGetFolderPath(NULL, uPathID, NULL, SHGFP_TYPE_CURRENT, szPath);
return szPath;
}
void CampoSetup::AssociateExtension(const wxFileName& strExeFile, const wxString strExt)
{
// Register icon and application
WriteRootRegistryKey(strExt, APPNAME);
wxString str = strExeFile.GetFullPath(); str += wxT(",0");
WriteRootRegistryKey(wxT("Campo\\DefaultIcon"), str);
str = strExeFile.GetFullPath(); str += wxT(" \"%1\"");
WriteRootRegistryKey(wxT("Campo\\shell\\open\\command"), str);
}
bool CampoSetup::CreateIcon(unsigned int csidl, const wxFileName& strExeFile, const wxString& strLinkName) const
{
//csidl = CSIDL_COMMON_DESKTOPDIRECTORY = desktop
//csidl = CSIDL_COMMON_STARTUP = all users esecuzione automatica
wxString strDesktopPath = GetFolderPath(csidl);
if (!strDesktopPath.IsEmpty())
{
CoInitialize(NULL);
// Get a pointer to the IShellLink interface.
IShellLink* psl;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
if (SUCCEEDED(hres))
{
// Set the path to the shortcut target and add the description.
psl->SetPath(strExeFile.GetFullPath());
psl->SetWorkingDirectory(strExeFile.GetPath());
psl->SetDescription(APPNAME);
//sceglie l'icona da quelle possibili legate al .exe in base al tipo di installazione
const InstallationType uInstallationType = m_pWizard->GetInstallationType();
if (uInstallationType == it_server || uInstallationType == it_client)
{
wxString strPath = m_pWizard->GetPrgLocPath();
strPath += "/res/";
switch (uInstallationType)
{
case it_server: strPath += "CampoSrv.ico"; break;
case it_client: strPath += "CampoCln.ico"; break;
default: strPath += "Campo.ico"; break;
}
psl->SetIconLocation(strPath, 0);
}
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (SUCCEEDED(hres))
{
wxFileName fnLnk;
wxString strName = strLinkName + ".lnk";
fnLnk.Assign(strDesktopPath, strName);
// Save the link by calling IPersistFile::Save.
wxString strPath = fnLnk.GetFullPath();
wchar_t buff[_MAX_PATH];
memset(buff, 0, sizeof(buff));
wxConvLocal.MB2WC(buff, strPath, strPath.Len());
hres = ppf->Save(buff, true);
ppf->Release();
}
psl->Release();
}
CoUninitialize();
}
return true;
}
//-------------------------------------------
// ..per i servers di Campo
//-------------------------------------------
bool CampoSetup::StopLurch() const
{
bool ok = false;
//cerca e ferma authoriz e lurch come processi
for (int i = 0; i < 2; i++)
{
wxHTTP scServer;
if (scServer.Connect("127.0.0.1", i == 0 ? 10000 : 1883))
{
//if (scServer.BuildRequest("/stop.cgi", 0))
wxInputStream* isIs = scServer.GetInputStream("/stop.cgi");
if (isIs)
{
delete isIs;
wxSleep(3);
ok = true;
break;
}
}
}
//se lurch e' un servizio lo stoppa
const wxString strValue = ReadLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application");
if (!strValue.IsEmpty())
{
wxString strExecService = GetFolderPath(CSIDL_SYSTEM);
strExecService += "\\NET STOP Lurch";
wxExecute(strExecService, wxEXEC_SYNC);
}
return ok;
}
bool CampoSetup::StartLurch(const wxString& strPrgLocPath) const
{
const wxString strValue = ReadLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application");
if (!strValue.IsEmpty())
{
wxString strExecService = GetFolderPath(CSIDL_SYSTEM);
strExecService += "\\NET START Lurch";
wxExecute(strExecService, wxEXEC_SYNC);
}
else
{
wxString strPath = strPrgLocPath;
strPath += "/servers/lurch.exe";
wxExecute(strPath, wxEXEC_ASYNC);
}
return true;
}
bool CampoSetup::CreateAutostartMode(const LurchMode iSrvAutostartMode, const wxString& strPath)
{
//creazione dei filenames e dei path necessari in giro per la funzione
//filename (con path quindi) di Lurch.exe
wxFileName strExe(strPath, wxT("lurch.exe"));
strExe.AppendDir("servers");
//stringa path della cartella Servers in base alle scelte dell'utente
const wxString strSrvPath = strExe.GetPath();
//1) Cerca di eliminare Lurch se presente come servizio
const wxString strValue = ReadLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application");
if (!strValue.IsEmpty())
{
//elimina un eventuale servizio precedente (senno' col cavolo che lo riesce a modificare!)
//utilizza il programma instsrv.exe dentro la cartella servers installata
wxString strRemove = strSrvPath + "\\instsrv Lurch REMOVE";
const long lRemove = wxExecute(strRemove, wxEXEC_SYNC);
}
//2) Cerca di fermare Lurch se presente come programma in esecuzione automatica
else
{
if (LurchRunning())
StopLurch();
}
switch (iSrvAutostartMode)
{
//esecuzione server come servizi (magia!)
case lm_service:
{
//aggiunge la voce ai servizi di windows (dentro strumenti di amministrazione)
//utilizza i programmi instrv.exe e srvany.exe dentro la cartella servers installata
wxString strCreateService = strSrvPath + "\\instsrv Lurch ";
strCreateService += strSrvPath;
strCreateService += "\\srvany.exe";
//esegue il programma di installazione servizi di Windows creando la voce
const long lExec = wxExecute(strCreateService, wxEXEC_SYNC);
if (lExec >= 0)
{
//crea le voci nel registry di windows
WriteLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application", strExe.GetFullPath());
wxString strExecService = GetFolderPath(CSIDL_SYSTEM);
strExecService += "\\NET START Lurch";
//avvia il servizio
const long lExecLurch = wxExecute(strExecService, wxEXEC_SYNC);
if (lExecLurch < 0)
WarningBox("Impossibile eseguire il servizio del gestore applicazioni.\nLanciarlo manualmente dagli strumenti di amministrazione nel pannello di controllo!");
}
else
WarningBox("Impossibile registrare il servizio per l'esecuzione automatica del gestore applicazioni.\nSelezionare una diversa modalita' di esecuzione!");
}
break;
//link nella cartella esecuzione automatica
case lm_autostart:
{
CreateIcon(CSIDL_COMMON_STARTUP, strExe, "lurch");
}
break;
default:
break;
}
return true;
}
//----------------------------------------------------------------
// Metodi di utility per i vari tipi di aggiornamento
//----------------------------------------------------------------
static int PatchCompare(const wxString& first, const wxString& second)
{
const wxFileName fn1(first);
const wxFileName fn2(second);
const wxString strName1 = fn1.GetName().Lower();
const wxString strName2 = fn2.GetName().Lower();
if (strName1 == "syinst1")
return -1;
if (strName2 == "syinst1")
return 1;
return strName1.CompareTo(strName2);
}
const wxString CampoSetup::GetSourceDir(const wxString strDirName) const
{
wxFileName strSourcePath(m_strSetupPath, "pippo.txt");
strSourcePath.AppendDir("..");
strSourcePath.AppendDir("..");
strSourcePath.AppendDir(strDirName);
strSourcePath.MakeAbsolute();
const wxString strSrc = strSourcePath.GetPath();
return strSrc;
}
//metodo per aggiornare il modulo SY in install.ini
void CampoSetup::UpdateInstallIni(const wxString strSourcePath, const wxString strDestPath, const wxString& strModule) const
{
for (int j = 0; j < 2; j++)
{
wxString strParagraph = strModule;
if (j > 0)
strParagraph << j;
CampoIniFile InstallIniSource(strSourcePath, strParagraph);
CampoIniFile InstallIniDest(strDestPath, strParagraph);
wxString strWrk;
long nIndex;
for (bool ok = InstallIniSource.GetFirstEntry(strWrk, nIndex); ok; ok = InstallIniSource.GetNextEntry(strWrk, nIndex))
{
InstallIniDest.Set(strWrk, InstallIniSource.Get(strWrk));
}
}
}
bool CampoSetup::UnzipModule(const wxString& strPrgLocPath, const wxString& strSrc, const wxString& strModule) const
{
//Attenzione! Se c'e' il server di chiavi in funzione va fermato prima di procedere!!!!
const bool bLurch = strModule == "sr" && LurchRunning();
if (bLurch)
StopLurch();
bool ok = false;
wxArrayString asFilesList;
//..contando anche quanti sono e memorizzandoli in un array asFileList
const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asFilesList, strModule+"*.zip");
if (uFilesToCopy > 0)
{
//ordina le patch per numero crescente ma mette davanti a tutte il pacco (sysinst1)
asFilesList.Sort(PatchCompare);
for (size_t i = 0; i < uFilesToCopy; i++)
{
UnzipFile(asFilesList[i] , strPrgLocPath);
}
//aggiorna l'install.ini in base al numero di patch e versione dell'ultimo file zip di sistema
//ci vuole un giro allucinogeno per trasformare il .zip in .ini e togliere quel cazzo di 1 in fondo
wxFileName strLastFile(asFilesList[uFilesToCopy - 1]); //zip con path completo
wxString strWrk = strLastFile.GetName();
strWrk.Truncate(strWrk.Len() - 1);
strLastFile.SetName(strWrk);
strLastFile.SetExt("ini");
strWrk = strLastFile.GetFullPath();
//adesso che ha trovato quello sporco ultimo .ini prende versione e patch e le copia nell'install.ini..
//..nella dir dei programmi; lo fa paragrafo x paragrafo ([sy],[sy1]..)
//potrebbe sembrare assurdo un for, ma e' per futuri sottomoduli con numero > 1
UpdateInstallIni(strWrk, strPrgLocPath + "/install.ini", strModule);
}
//Adesso puo' far ripartire il server di chiavi
if (bLurch)
StartLurch(strPrgLocPath);
return uFilesToCopy > 0;
}
bool CampoSetup::CopyFilesAndDirs(const wxString& FilesListI, wxString strFileCurr, const bool bIni) const
{
bool ok = true;
strFileCurr.MakeLower(); //minuscolizzazione di sicurezza
const wxFileName strFileName(strFileCurr);
//i files .ini vanno trattati con i guanti (se esistono gia' non vanno copiati!!!)
//parte da eseguire solo in caso sia indicata la trattazione degli ini (bIni true)
if (bIni)
{
if (strFileName.GetExt() == "ini")
{
const wxString strName = strFileName.GetName();
//campo.ini e install.ini vanno lasciati stare se esistono (aggiornamento)!!!
if ((strName == "campo" || strName == "install") && strFileName.FileExists())
ok = false;
}
}
if (ok)
{
//eventuali sottodirectory le crea (solo se hanno un nome)
const wxString strDir = strFileName.GetPath();
if (!strDir.IsEmpty() && !wxDirExists(strDir))
wxMkdir(strDir);
ok = CopiaFile(FilesListI, strFileCurr);
}
return ok;
}
//metodo per copiare una directory e tutti i files che contiene
void CampoSetup::CopyDir(const wxString& strSourceDir, const wxString& strDestDir) const
{
if (!wxDir::Exists(strDestDir))
wxMkdir(strDestDir);
wxArrayString asFilesList;
const size_t uFilesToCopy = wxDir::GetAllFiles(strSourceDir, &asFilesList, "*.*", wxDIR_FILES);
const size_t uFrom = strSourceDir.Len();
for (size_t i = 0; i < uFilesToCopy; i++)
{
wxString strFileDest = strDestDir + asFilesList[i].Mid(uFrom);
CopiaFile(asFilesList[i], strFileDest);
}
}
//metodo per accoppare tutti i files di una directory
void CampoSetup::EmptyOutDir(const wxString& strDir) const
{
wxArrayString asFilesList;
const size_t uFilesToKill = wxDir::GetAllFiles(strDir, &asFilesList, "*.*");
for (size_t i = 0; i < uFilesToKill; i++)
::wxRemoveFile(asFilesList[i]);
}
//-----------------------------------------------------
// METODI BASSO LIVELLO PER AGGIORNAMENTI NON STANDARD
//-----------------------------------------------------
//----------------------------
// 1) AGGIORNAMENTO CLIENT
//----------------------------
//Aggiornatore client. Copia i files del programma da una directory remota su un server campo nella directory...
//...locale di campo
int CampoSetup::ClientUpdateModule(const wxString& strLocalPath, const wxString& strRemotePath, const wxString strModule) const
{
int nLocVer, nLocPatch, nRemVer, nRemPatch;
{
CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strModule);
nLocVer = iniLocalInstall.GetInt("Versione");
nLocPatch = iniLocalInstall.GetInt("Patch");
CampoIniFile iniRemoteInstall(strRemotePath + "/install.ini", strModule);
nRemVer = iniRemoteInstall.GetInt("Versione");
nRemPatch = iniRemoteInstall.GetInt("Patch");
}
int cmp = nLocVer - nRemVer;
if (cmp == 0)
cmp = nLocPatch - nRemPatch;
//il client e' piu' indietro e quindi va aggiornato!
if (cmp < 0)
{
bool bOk = true;
CampoProgressDialog pi("Aggiornamento elenco files dal server...", 100, m_pWizard);
wxArrayString asGroups;
{
wxString strGroup;
long nIndex;
CampoIniFile iniRemoteInstall(strRemotePath + "/install.ini", "");
for (bool ok = iniRemoteInstall.GetFirstGroup(strGroup, nIndex); ok; ok = iniRemoteInstall.GetNextGroup(strGroup, nIndex))
{
if(strGroup.Len() > 2 && strGroup.StartsWith(strModule))
asGroups.Add(strGroup);
}
}
//controlla tutti i sottomoduli del modulo [sy1],[sy2]...
for (size_t i = 0; i < asGroups.GetCount() && bOk; i++)
{
const wxString& strParagraph = asGroups[i];
CampoIniFile iniRemoteInstallModule(strRemotePath + "/install.ini", strParagraph);
//install.ini locale che deve essere aggiornato durante la copia dei files!
CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strParagraph);
//ogni file dell'elenco del sottomodulo corrente va copiato
for (int j = 0;; j++)
{
pi.Pulse(); //magica barra modello supercar!
const wxString strVarName = wxString::Format("File(%d)", j);
wxString strCurrFile = iniRemoteInstallModule.Get(strVarName);
if (strCurrFile.IsEmpty())
break;
strCurrFile = strCurrFile.BeforeFirst('|');
const wxString strSrcPath = strRemotePath + "/" + strCurrFile;
const wxString strDstPath = strLocalPath + "/" + strCurrFile;
//copia il file remoto di origine sul file locale di destinazione (overwrite=true di default)
if (!CopiaFile(strSrcPath, strDstPath))
{
wxString strError;
strError += "\nAssicurarsi che il client locale di ";
strError += APPNAME;
strError += " non sia in funzione.\n";
strError += "Assicurarsi che il server di ";
strError += APPNAME;
strError += " sia in funzione e raggiungibile in rete.\n";
strError += "Aggiornamento interrotto!";
ErrorBox(strError);
bOk = false;
break;
}
//se ci sono zip deve scompattarli (per ora esiste solo res.zip)
if (strCurrFile.EndsWith("res.zip"))
{
UnzipFile(strDstPath, strLocalPath + "/res");
}
//se riesce la copia del file aggiorna l'install.ini sul file (se non lo facesse non comparirebbero...
//...eventuali nuovi files
iniLocalInstall.Set(strVarName, strCurrFile);
} //for(int j...
//una volta termiata la copia dei files del sottmodulo[i] scatta l'aggiornamento dell'install.ini locale...
//...al livello versione/patch appena copiate sempre del sottomodulo[i]
iniLocalInstall.Set("Versione", nRemVer);
iniLocalInstall.Set("Patch", nRemPatch);
} //for(int i...
//una volta termiata la copia dei files dell'intero modulo scatta l'aggiornamento dell'install.ini locale al..
//..livello versione/patch appena copiate
CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strModule);
iniLocalInstall.Set("Versione", nRemVer);
iniLocalInstall.Set("Patch", nRemPatch);
} //if(cmp<0...
return cmp;
}
//----------------------------
// 2) AGGIORNAMENTO DA DISCO
//----------------------------
//Aggiornatore da disco. Copia i files delle patch da una directory su disco in una directory di appoggio...
//...temporanea dove esegue lo scompattamento con destinazione la directory locale
bool CampoSetup::DiskUpdateModule(const wxString& strLocalPath, const wxString& strDiskPath, const wxString strModule) const
{
//puo' chiamare direttamente il metodo che scompatta tutte le patch del modulo a partire dal pacco iniziale...
//...fino all'ultima;il metodo le ordina gia' in modo crescente di numero d'ordine
return UnzipModule(strLocalPath, strDiskPath, strModule);
}
//-------------------------------
// 3) AGGIORNAMENTO DA INTERNET
//-------------------------------
bool CampoSetup::HTTPGet(const wxString& strLocalPath, const wxString& strWebPath) const
{
wxString strServer, strPath;
int nSlash = strWebPath.First('/');
strServer = strWebPath.Left(nSlash);
strPath = strWebPath.Mid(nSlash);
wxHTTP http;
//connessione al server web con le patch
if (http.Connect(strServer))
{
wxInputStream* pStream = http.GetInputStream(strPath);
if (pStream != NULL)
{
//compila un file di testo temporaneo con l'elenco dei files che trova sul server
wxFileOutputStream fos(strLocalPath);
fos.Write(*pStream);
delete pStream;
return true;
}
}
return false;
}
//Aggiornatore via web. Copia i files delle patch da una directory web remota in una directory di appoggio...
//...temporanea dove esegue lo scompattamento con destinazione la directory locale
bool CampoSetup::InternetUpdateModule(const wxString& strLocalPath, const wxString& strWebPath, const wxString strModule) const
{
bool ok = false;
int nLocVer, nLocPatch;
{
CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strModule);
nLocVer = iniLocalInstall.GetInt("Versione");
nLocPatch = iniLocalInstall.GetInt("Patch");
}
//Svuota,elimina e ricrea una directory temporanea di appoggio ove mettere i files delle patch da scompattare
//E' necessaria questa operazione per non trovarsi ancora files di vecchie patch parcheggiati nella dir!
const wxString strTempDir = wxFileName::GetTempDir() + "/setup/";
EmptyOutDir(strTempDir); //deve svuotare la directory dai files per poterla eliminare!!!
if (::wxRmdir(strTempDir)) //elimina la dir adesso vuota
::wxMkDir(strTempDir); //la ricrea
const wxString strTempFile = strTempDir + "httpdir.txt";
if (HTTPGet(strTempFile, strWebPath))
{
//partendo dal file temporaneo ne compila un secondo con i soli nomi dei file validi da scaricare
//i criteri di selezione sono il nome del modulo ed il livello patch
wxTextFile tfFilesList;
if (tfFilesList.Open((strTempFile)))
{
CampoProgressDialog pi("Aggiornamento elenco files dal server...", (int)tfFilesList.GetLineCount(), m_pWizard);
for (wxString strWrk = tfFilesList.GetFirstLine(); !tfFilesList.Eof(); strWrk = tfFilesList.GetNextLine())
{
int nPos = strWrk.Find("href");
if (nPos > 0)
{
wxString strHref = strWrk.Mid(nPos + 5, 16);
strHref = strHref.AfterFirst('"');
strHref = strHref.BeforeLast('"');
if ( strHref.StartsWith(strModule) && ((atoi(strHref.Mid(2)) > nLocPatch) || (nLocPatch == 0)))
{
if (!pi.Update((int)tfFilesList.GetCurrentLine(), strHref))
break;
HTTPGet(strTempDir+strHref, strWebPath+strHref);
}
}
}
//chiude il file temporaneo
tfFilesList.Close();
} //if(tfFilesList...
//scompatta le patch di sistema e aggiorna l'install.ini locale
ok = UnzipModule(strLocalPath, strTempDir, strModule);
} //if(HTTPGet(...
return ok;
}
//-----------------------------------------------------
// METODI ALTO LIVELLO PER AGGIORNAMENTI NON STANDARD
//-----------------------------------------------------
//---------------------------------------------------------------
// 1) metodo per l'aggiornamento dei client di rete in automatico
//---------------------------------------------------------------
void CampoSetup::ClientUpdate()
{
wxFileName fn(m_strSetupPath, "install.ini");
fn.AppendDir("..");
fn.MakeAbsolute();
const wxString strLocalPath = fn.GetPath();
wxString strRemotePath;
{
CampoIniFile iniLocalInstall(fn.GetFullPath(), "Main");
strRemotePath = iniLocalInstall.Get("DiskPath");
}
ClientUpdateModule(strLocalPath, strRemotePath, "sy");
wxSetWorkingDirectory(strLocalPath);
wxExecute("ba1 -6 /uADMIN");
}
//-----------------------------------------------------------------------------------------------
// 2) metodo per l'aggiornamento da disco attraverso il menu di Manutenzione/Installazione moduli
//-----------------------------------------------------------------------------------------------
void CampoSetup::DiskUpdate()
{
wxFileName fn(m_strSetupPath, "install.ini");
fn.AppendDir("..");
fn.MakeAbsolute();
const wxString strLocalPath = fn.GetPath();
wxString strRemotePath;
{
CampoIniFile iniLocalInstall(fn.GetFullPath(), "Main");
strRemotePath = iniLocalInstall.Get("DiskPath");
}
DiskUpdateModule(strLocalPath, strRemotePath, "sy");
DiskUpdateModule(strLocalPath, strRemotePath, "sr");
wxSetWorkingDirectory(strLocalPath);
wxExecute("ba1 -6 /uADMIN");
}
//----------------------------------------------------------------------------------------
// 3) metodo per l'aggiornamento via internet attraverso Manutenzione/Installazione moduli
//----------------------------------------------------------------------------------------
void CampoSetup::InternetUpdate()
{
//install.ini locale dove setup.exe e' in esecuzione
wxFileName fn(m_strSetupPath, "install.ini");
fn.AppendDir("..");
fn.MakeAbsolute();
const wxString strLocalPath = fn.GetPath();
//quale e' il path web da cui aggiornarmi?
wxString strRemotePath;
{
//Install.ini locale da cui leggere il path di dove sta il mio server web
CampoIniFile iniLocalInstall(fn.GetFullPath(), "Main");
strRemotePath = iniLocalInstall.Get("WebPath");
}
//aggiornamento dei moduli SY e SR via web
InternetUpdateModule(strLocalPath, strRemotePath, "sy");
InternetUpdateModule(strLocalPath, strRemotePath, "sr");
//lanciare ba1.exe -6 in uscita
wxSetWorkingDirectory(strLocalPath);
wxExecute("ba1 -6 /uADMIN");
}
//--------------------------------------------------------------------------
//metodo per tutte le installazioni e gli aggiornamenti automatici in locale
//--------------------------------------------------------------------------
void CampoSetup::NormalSetup()
{
//creazione del CampoWizard, ovvero dell'insieme di finestre per gestire installazione/aggiornamento
m_pWizard = new CampoWizard(m_pMainFrame);
if (m_pWizard->Run())
{
//e' una DEMO o una versione normale?
const bool bInstallDemoVersion = m_pWizard->GetInstDemoVersion();
// 0) INSTALLAZIONE VERSIONE DEMO (SIETE PAZZI?)
//----------------------------------------------
if (bInstallDemoVersion)
{
const wxString& strPrgLocPath = "c:/campodemo";
const wxString& strDataPath = strPrgLocPath + "/dati";
const wxString& strHelpPath = strPrgLocPath + "/htmlhelp";
//creazione delle directories necessarie alla installazione DEMO
CheckAndMakeDir(strPrgLocPath, "programmi");
CheckAndMakeDir(strDataPath, "dati");
CheckAndMakeDir(strHelpPath, "help");
//copia della campodemo sull'hard disk in c:\campodemo
wxArrayString asDemoList;
const wxString strSrc = GetSourceDir("campodemo");
const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asDemoList);
wxString strFileCurr;
const size_t nPathLenght = strSrc.Len();
CampoProgressDialog pi("Installazione Versione Demo...", (int)uFilesToCopy, m_pWizard);
for (size_t i = 0; i < uFilesToCopy; i++)
{
if (!pi.Update((int)i, asDemoList[i]))
break;
asDemoList[i].Lower();
strFileCurr = strPrgLocPath;
strFileCurr += asDemoList[i].Mid(nPathLenght);
if (!strFileCurr.IsEmpty())
{
if (!CopyFilesAndDirs(asDemoList[i], strFileCurr, false))
break;
}
}
//icona sul desktop
const bool bDesktopShortcut = m_pWizard->GetDesktopShortcut();
if (bDesktopShortcut)
{
const wxFileName strExe("c:/campodemo", wxT("ba0.exe"));
CreateIcon(CSIDL_COMMON_DESKTOPDIRECTORY, strExe, "CampoDEMO");
}
//lanciare ba0.exe in uscita
wxSetWorkingDirectory(strPrgLocPath);
wxExecute("ba0");
}
else //tutti i casi normali (std,server,client,aggiornamento)
{
// 1) RACCOLTA PARAMETRI GENERALI INSTALLAZIONE (tipo,path,cartelle,servers,...)
//------------------------------------------------------------------------------
//tipo di installazione/aggiornamento
const InstallationType uInstallationType = m_pWizard->GetInstallationType();
const bool bNewInstallation = uInstallationType != it_upgrade;
//installazione servers? solo per server di campo
const bool bInstallLurch = uInstallationType == it_server && (m_pWizard->GetInstUseAuth() || m_pWizard->GetInstUseDict());
//uso servers? sarebbe solo per i client ma lo teniamo buono per tutti
const bool bUseLurch = uInstallationType != it_server && (!m_pWizard->GetSrvAuth().IsEmpty() || !m_pWizard->GetSrvDict().IsEmpty());
//installazione datidemo? (oddio speriamo di no!; comunque vale solo per installazione standard)
const bool bInstallDemoData = uInstallationType == it_standalone && m_pWizard->GetInstDemoData();
//cartelle selezionate dall'utente
const wxString& strPrgLocPath = m_pWizard->GetPrgLocPath();
const wxString& strDataPath = m_pWizard->GetDataPath();
//se nuova installazione deve anche creare la directory di destinazione
if (bNewInstallation)
{
//creazione della directory dei programmi (compreso l'intero albero directory)
CheckAndMakeDir(strPrgLocPath, "programmi");
//creazione della directory dei dati (compreso l'intero albero directory)
//un client NON installa i dati!! (senno' e' una installazione locale semplice)
if (uInstallationType != it_client)
CheckAndMakeDir(strDataPath, "dati");
}
// 2) COPIA DEI FILES DI INSTALLAZIONE DALLA CARTELLA CAMPO (E SUBDIRS) (SU CD) ALLA CARTELLA DESTINAZIONE
//--------------------------------------------------------------------------------------------------------
//copia del contenuto della cartella campo nella cartella di destinazione (installaz/aggiornam)
//per prima cosa cerca la cartella dei files sorgente...
wxArrayString asFilesList;
wxFileName strSourcePath(m_strSetupPath, "*.*");
strSourcePath.AppendDir("..");
strSourcePath.AppendDir("..");
strSourcePath.AppendDir("campo");
strSourcePath.MakeAbsolute();
//stringa inutile al programma ma decisiva per il programmatore
const wxString strSrc = strSourcePath.GetPath();
//..contando anche quanti sono e memorizzandoli in un array asFileList
const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asFilesList);
const size_t nPathLenght = strSrc.Len();
//progress bar
CampoProgressDialog pi("Installazione Dati e Programmi di base...", (int)uFilesToCopy, m_pWizard);
for (size_t i = 0; i < uFilesToCopy; i++)
{
//per ogni file da copiare controlla i path sorgente e destinazione(problema con sottodirectory tipo..
//..dati); strFileCurr va lasciato qui perche' DEVE ESSERE AZZERATO ad ogni cambio file!!!!!!
wxString strFileCurr;
//controlla se il file corrente e' dentro una sottodirectory (tipo dati,servers,setup...) oppure e' al..
//..primo livello (quindi e' un file di programma)
wxString strSourceFile = asFilesList[i].Lower();
strSourceFile.Replace("\\", "/");
//e' in una subdir se la lunghezza del suo path prima dell'ultimo '/' e' > della lunghezza del path di root
const bool bIsSubDir = strSourceFile.Find('/', true) > (int)nPathLenght;
//2A) files con subdirectory
if (bIsSubDir)
{
//files dei dati standard! solo in caso di nuova installazione!!
if (strSourceFile.Find("/dati/") > 0)
{
//i DATI NON VANNO MAI installati in caso di aggiornamento!!!
//i DATI NON VANNO MAI installati in caso di installazione client!!!
//e nemmeno in caso si scelga di installare i dati demo (senno' sporca la dir dati e i datidemo non si installano)
//Ricordare che c'e' gia' stato il controllo nella Forward della pagina di selezione, quindi la cartella..
//..di destinazione e' comunque vuota
if (bNewInstallation && uInstallationType != it_client && !bInstallDemoData)
{
strFileCurr = strDataPath;
strFileCurr += asFilesList[i].Mid(nPathLenght + 5);
//Ulteriore controllo di sicurezza: se trova il file di destinazione gia' presente..
//..NON lo sovrascrive (lo mette vuoto cosi' non lo copia)
if (wxFileName::FileExists(strFileCurr))
strFileCurr = "";
}
} else
if (strSourceFile.Find("/servers/") > 0) //che fare con i servers? copiare la directory...
{
if (bInstallLurch) //..ma solo se devi installare i servers
{
strFileCurr = strPrgLocPath;
strFileCurr += "/servers";
strFileCurr += asFilesList[i].Mid(nPathLenght + 8);
}
}
else //files vari di altre subdirectory che si installano sempre (es. setup)
{
strFileCurr = strPrgLocPath;
strFileCurr += asFilesList[i].Mid(nPathLenght);
}
}
//2B) files senza subdirectory (programmi!)
else
{
strFileCurr = strPrgLocPath;
strFileCurr += asFilesList[i].Mid(nPathLenght);
}
//copia i files nella cartella di destinazione (programmi,dati,cazzi e mazzi);se il nome del file..
//..di destinazione e' vuoto significa che non lo deve copiare!! (es. dati in aggiornamento)
if (!strFileCurr.IsEmpty())
{
//aggiorna la progind
if (!pi.Update((int)i, asFilesList[i]))
break;
//eventuali sottodirectory le crea (solo se hanno un nome) e poi copia fisicamente i files
//se un file non si copia interrompe l'installazione con un ErrorBox
if (!CopyFilesAndDirs(asFilesList[i], strFileCurr, true))
break;
} //if (!strFileCurr.IsEmpty()..
} //for(size_t...
UpdateInstallIni(strSrc + "/install.ini", strPrgLocPath + "/install.ini", "sy");
// 3) INSTALLAZIONE DATI DEMO
//---------------------------
//installazione dei dati dimostrativi (che schifo!).Non si puo' fare in aggiornamento!
/* if (bInstallDemoData && uInstallationType < 3)
{
//trova la cartella datidemo da copiare
wxArrayString asDataList;
const wxString strSrc = GetSourceDir("datidemo");
//conta i files da copiare e si lancia nell'operazione di copiatura...
//Vale quanto detto per l'installazione dell'area dati
const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asDataList);
wxString strFileCurr;
const size_t nPathLenght = strSrc.Len();
CampoProgressDialog pi("Installazione Dati Demo...", (int)uFilesToCopy, m_pWizard);
for (size_t i = 0; i < uFilesToCopy; i++)
{
if (!pi.Update((int)i, asDataList[i]))
break;
asDataList[i].Lower();
strFileCurr = strDataPath;
strFileCurr += asDataList[i].Mid(nPathLenght);
if (!strFileCurr.IsEmpty())
{
//eventuali sottodirectory le crea (solo se hanno un nome) e poi copia fisicamente i files
//se un file non si copia interrompe l'installazione con un ErrorBox
if (!CopyFilesAndDirs(asDataList[i], strFileCurr, false))
break;
} //if (!strFileCurr.IsEmpty()..
} //for (size_t i = 0...
} //if(bInstallDemoData... */
// 4) COMPILAZIONE CAMPO.INI CON CONFIGURAZIONE NUOVA INSTALLAZIONE
//-----------------------------------------------------------------
//adesso deve compilare il campo.ini se nuova installazione..
if (bNewInstallation)
{
{ //parentesi necessaria per la scrittura immediata (non cancellare! serve per debug)
//paragrafo [Main]
CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main");
const unsigned int uDongleType = m_pWizard->GetDongleType();
CampoIniMain.Set("Donglehw", uDongleType);
CampoIniMain.Set("Study", strDataPath);
CampoIniMain.Set("Firm", "com");
//server,client o standalone?
CampoIniMain.Set("Type", uInstallationType);
}
//paragrafo [Server]
if (bInstallLurch || bUseLurch)
{
CampoIniFile CampoIniSrv(strPrgLocPath + "/campo.ini", "Server");
CampoIniSrv.Set("Dongle", m_pWizard->GetSrvAuth());
CampoIniSrv.Set("Dictionary", m_pWizard->GetSrvDict());
}
} //if(bNewInstallation...
else //e' un aggiornamento! scrive il type
{
CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main");
//SOLO se sta aggiornando una versione antecedente alla 10.0 scrive la variabile Type nel campo.ini..
//..ovvero deve testare se Type = 0
if (CampoIniMain.GetInt("Type") == 0)
CampoIniMain.Set("Type", CampoIniMain.GetInstallationType());
}
// 5) COMPILAZIONE\AGGIORNAMENTO INSTALL.INI CON DISKPATH
//-------------------------------------------------------
//..e modificare comunque l'install.ini aggiornando eventualmente l'origine dei programmi
//parentesi necessaria per la scrittura immediata (non cancellare! serve per debug)
{
CampoIniFile CampoInstall(strPrgLocPath + "/install.ini", "Main");
if (uInstallationType == it_client) //client: directory origine sul server
CampoInstall.Set("DiskPath", m_pWizard->GetPrgNetPath());
else //e' il path assoluto dell'install.ini che sta in 'program' (es. D:\program)
{
const wxString strSrc = GetSourceDir("program");
CampoInstall.Set("DiskPath", strSrc);
}
}
// 6) AGGIORNAMENTO DEL MODULO SY CON EVENTUALI PATCH PRESENTI IN PROGRAM DEL CD E AGGIORNAMENTO INSTALL.INI
//----------------------------------------------------------------------------------------------------------
//procede poi al caricamento delle patch eventuali di sistema all'interno della dir 'program' e al..
//..conseguente riaggiornamento del livello versione/patch di SY ed SR in install.ini
const wxString strPrgCDPath = GetSourceDir("program");
if (wxFileName::DirExists(strPrgCDPath))
{
const wxString strSetupCDPath = strPrgCDPath + "/setup";
const wxString strSetupLocPath = strPrgLocPath + "/setup";
CopyDir(strSetupCDPath, strSetupLocPath);
UnzipModule(strPrgLocPath, strPrgCDPath, "sy");
UnzipModule(strPrgLocPath, strPrgCDPath, "sr");
}
// 7) CREAZIONE AUTOSTART DEI SERVERS (SE CI SONO)
//------------------------------------------------
//solo se sta installando campo in postazione server e deve installare un gestore di servizi..
//..avvia la procedura della creazione dell'autostart(un casino). Questa procedura non puo'..
//..valere per l'aggiornamento, che agisce in modo diverso
if (bNewInstallation)
{
const LurchMode iSrvAutostartMode = m_pWizard->GetSrvAutostartMode();
if (iSrvAutostartMode != lm_none)
{
CreateAutostartMode(iSrvAutostartMode, strPrgLocPath);
}
}
// 8) CREAZIONE DELL'ICONA SUL DESKTOP
//------------------------------------
const bool bDesktopShortcut = m_pWizard->GetDesktopShortcut();
if (bDesktopShortcut)
{
const wxFileName strExe(strPrgLocPath, wxT("ba0.exe"));
wxString strLnk;
CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main");
InstallationType nInstType = CampoIniMain.GetInstallationType();
switch (nInstType)
{
case it_server:
strLnk = "Campo (Server)";
break;
case it_client:
strLnk = "Campo (Client)";
break;
default:
strLnk = "Campo";
break;
}
//crea comunque l'icona
CreateIcon(CSIDL_COMMON_DESKTOPDIRECTORY, strExe, strLnk);
}
// 9) AGGIORNAMENTO CAMPO.STP
//---------------------------
if (bNewInstallation)
{
//deve aggiungere la nuova installazione al campo.stp
for (int i = 1;; i++)
{
wxString strGroup;
strGroup << i;
CampoIniFile CampoStp("C:\\campo.stp", strGroup);
wxString strPath = CampoStp.Get("Program");
if (strPath.IsEmpty())
{
CampoStp.Set("Program", strPrgLocPath);
break;
}
}
}
// 10) CHIUDE IL SETUP LANCIANDO BA1 -6 PER INSTALLAZIONE MODULI
//-------------------------------------------------------------
//lanciare ba1.exe -6 in uscita
if (wxSetWorkingDirectory(strPrgLocPath))
wxExecute("ba1 -6 /uADMIN");
else
ErrorBox("Impossibile installare i moduli. Cartella di destinazione irraggiungibile!");
}
} //if (m_pWizard->Run())...
m_pWizard->Destroy();
}
bool CampoSetup::CampoRunning(const wxString& strAppName, const wxString& strMsg) const
{
wxSingleInstanceChecker sicProgram(strAppName);
int i;
for (i = 10; i > 0 && sicProgram.IsAnotherRunning(); i--)
wxSleep(1);
if (i <= 0 && !strMsg.IsEmpty())
ErrorBox(strMsg);
return i <= 0;
}
bool CampoSetup::LurchRunning() const
{
//cerca Lurch che funziona come programma (esecuzione in modalita' avvio automatico)...
bool ok = CampoRunning("Lurch", wxEmptyString);
if (!ok)
{
//...se non lo trova cerca il solo Authoriz sempre come programma...
ok = CampoRunning("Authorization", wxEmptyString);
//se non trova nulla cerca Lurch come servizio...
if (!ok)
{
int year = 0;
wxString strSrv = "127.0.0.1";
ok = ServerLogin(year, strSrv) != 0xFFFF;
}
}
return ok;
}
//metodo principale che sceglie la modalita' di lancio del programma
void CampoSetup::OnTimer(wxTimerEvent& WXUNUSED(e))
{
//controllo di eventuali Campo o servers attivi e conseguente interruzione dell'installazione
if (LurchRunning())
{
WarningBox("Per poter aggiornare/installare il programma CAMPO verra' temporaneamente disattivato il gestore delle licenze!\nPrima di proseguire accertarsi che tutti gli utenti spengano il programma CAMPO!!");
const long lStop = StopLurch();
}
if (CampoRunning("ba0", "Uscire dal programma CAMPO prima di procedere con l'aggiornamento/installazione!") ||
CampoRunning("ba1", "Uscire dal programma di manutenzione di CAMPO\n prima di procedere con l'aggiornamento/installazione!"))
{
m_pMainFrame->Destroy();
return;
}
wxFileName strPath(argv[0]);
strPath.MakeAbsolute();
strPath.SetCwd();
//path del programma setup.exe in esecuzione; serve in seguito in quanto alcuni metodi (tipo la GetAllFiles)..
//..fanno perdere questo path
m_strSetupPath = strPath.GetPath();
wxString strCommand = argv[1];
if (strCommand.IsEmpty())
NormalSetup();
else
{
if (strCommand == "-ud")
DiskUpdate();
if (strCommand == "-uc")
ClientUpdate();
if (strCommand == "-uw")
InternetUpdate();
}
//finestrina x chiudere a mano il programma (sconsigliata causa lancio ba1.exe)
// ::wxMessageBox(wxT("Installazione terminata"), APPNAME, wxOK | wxICON_INFORMATION);
m_pMainFrame->Destroy();
}
bool CampoSetup::OnInit()
{
wxInitAllImageHandlers();
m_locale.Init();
m_pMainFrame = new CampoFrame;
SetTopWindow(m_pMainFrame);
wxTimerEvent e(883);
AddPendingEvent(e);
return true;
}