Oppure

Loading
10/11/14 21:15
Visto che la mia richiesta precedente ha fruttato consigli che mi sono stati e mi sono preziosi, ci riprovo su un tema simile ma diverso: come posso ricavare il percorso completo del file eseguibile che contiene il programma in esecuzione?

Ho provato diverse soluzioni, ma nessuna risulta affidabile sempre. La mia intenzione sarebbe poter effettuare l'operazione nell'immediatezza del lancio del programma, in ambienti da Windows XP a Windows 8.

Prima soluzione: GetCurrentDirectory().
Inizialmente mi sembrava un'ottima soluzione, perché pareva fornire il percorso alla cartella che contiene il file eseguibile. Problema: se il programma viene lanciato con il drag and drop d'un file sull'icona del programma, restituisce il percorso del file trascinato, non del file del programma! Che seccatura!

Seconda soluzione: GetModuleFileName().
Anche questo sembrava non essere male, perché restituisce il percorso del file eseguibile, completato dal nome del file stesso. Apparentemente basterebbe rimuovere il nome del file eseguibile per avere il percorso della cartella che lo contiene (e non è difficile). Per qualche ragione, però, la funzione dà risultati differenti con diversi sistemi operativi (e non riesco a cogliere la logica che c'è sotto ai vari meccanismi).

Può essere che, nonostante i numerosi test, io continui a sbagliare qualcosa. Può anche essere che la strada da seguire non sia nessuna delle due che ho provato. Qualcuno vuole aiutarmi?
Ultima modifica effettuata da 11/11/14 0:16
10/11/14 21:27
nessuno
Ma con quale linguaggio?

Per qualche ragione, però, la funzione dà risultati differenti con diversi sistemi operativi


Con precisione cosa succede?
Ultima modifica effettuata da nessuno 10/11/14 21:36
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità;) chiamava il gioco del Lotto Tassa sulla stupidità.
11/11/14 0:42
Il linguaggio che uso è il C/C++, interagendo con le API di Win32.

Alla domanda "con precisione cosa succede" mi resta difficile dare una risposta chiara, perché ho fatto talmente tante di quelle prove da aver creato nella mia testa un'insalata di possibilità che mi confonde alla grande.

Diciamo che ho un programmino ormai in stato avanzato di sviluppo che nelle intenzioni dovrebbe creare una cartella di file "di supporto" nella stessa cartella ove si trova l'eseguibile. Nella cartella "di supporto" si trovano un file di impostazioni e una serie di file di immagine che dovrebbero essere precaricati al lancio del programma. Il file di impostazioni dovrebbe essere inoltre aggiornato alla chiusura del programma. Se il file delle impostazioni è inaccessibile, al lancio vengono usate le impostazioni predefinite, mentre in chiusura viene inviato all'utente un semplice messaggio di notifica che avverte che le preferenze non sono state memorizzate.

Le cose funzionano bene su Windows 7 e 8, mentre in XP la cartella dei file di impostazione non viene trovata. E' come se qualcosa impedisse al programma di ricavare il percorso d'accesso, oppure come se l'accesso non fosse possibile anche in presenza del percorso corretto.

Tra le ipotesi che mi son venute in mente c'è anche quella che il problema non dipenda dal mio programma ma dalle credenziali d'accesso al percorso "incriminato": potrebbe essere che il sistema impedisca di accedere a certe cartelle per questioni legate a qualche opzione di protezione? (uso spesso il programma su computer che non sono di mia proprietà "armati" di dosi industriali di antivirus e software di protezione di varia natura) E se così fosse, come mai solo con XP?

Ah, il problema pare essere più frequente quando pongo l'eseguibile nella cartella radice (root directory) di un disco, tanto che si tratti del disco di sistema, quanto di un altro disco interno o di un volume rimovibile. Il casino è che a volte ottengo comportamenti apparentemente contraddittori dai quali non riesco a trarre una regola generale. Ho realizzato anche una versione di prova del programma che visualizza sotto forma testuale i percorsi con semplici MessageBox() inserite in punti strategici, e tutto sembra incredibilmente a posto (eppure il problema continua a presentarsi). Sono, come minimo, MOLTO confuso.

Dato che il file eseguibile si chiama "St'abbort'.exe" e ipotizzando che sia collocato nella cartella radice del volume "C", il percorso del programma così come viene "letto" è "C:\" e quello della cartella di supporto "C:\St'abbort' - File di supporto". Posto che il programma si trovasse in una sottocartella "Software personali" in un volume "E", i percorsi finirebbero per essere rispettivamente "E:\Software personali" e "E:\Software personali\St'abbort' - File di supporto". Non riesco a trovare niente di strano in nessuno dei due casi...

In qualche modo il trattamento del file system è diverso in XP rispetto a 7 e 8?

Per ogni altro verso il mio programma funziona alla perfezione. Volendo fare il figo m'azzarderei a definirlo "un gioiellino" (secondo i miei standard da amatore).

EDIT: dimenticavo... per peggiorare la confusione, ho un computer con XP mio personale sul quale tutto funziona liscio come l'olio... è assurdo!
Ultima modifica effettuata da 11/11/14 0:48
11/11/14 0:55
Il copia-e-incolla del codice sorgente dal quale credo nasca il problema è questo:

////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='Il copia-e-incolla del codice sorgente dal quale credo nasca il problema è questo:


////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='{parsed_message}'; }

        if( l >= 0 ) {
            delete[] buff;
            buff = new char[l+1];
            l = GetModuleFileName( hndIstanza, buff, l+1 );
        }

        *pBuffer = buff;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: //
//     1. il percorso indicato da percBase                                    //
//     2. un carattere '\'                                                   //
//     3. il nome del file indicato da "nomeAgg"                              //
// Il parametro percBase DEVE riguardare una stringa C valida e non vuota.    //
// E' compito del chiamante deallocare la stringa restituita quando non piu'  //
// necessaria.                                                                //
////////////////////////////////////////////////////////////////////////////////

char *ComponiPercorso( const char *percBase, const char *nomeAgg ) {
    const char *sep[] = { "", "\" };

    try {
        int lPercBase = lstrlen( percBase );
        int lNomeAgg  = lstrlen( nomeAgg );
        int lSep      = lstrlen( sep[lPercBase>3] );
        int lPerc = lPercBase + lSep + lNomeAgg;
        char *perc = new char[lPerc+1];
        wsprintf( perc, "%s%s%s", percBase, sep[lPercBase>3], nomeAgg );
        return perc;
    } catch( ... ) {
        return NULL;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il  //
// percorso assume quindi l'aspetto C:\Cartella.                              //
// Il parametro "pc" sta per [p]ercorso [c]ompleto.                           //
// Il parametro "lp" sta per [l]unghezza [p]ercorso.                          //
// Restituisce la lunghezza del percorso risultante.                          //
////////////////////////////////////////////////////////////////////////////////

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
    return lstrlen( pc );
}
'; } if( l >= 0 ) { delete[] buff; buff = new char[l+1]; l = GetModuleFileName( hndIstanza, buff, l+1 ); } *pBuffer = buff; return TRUE; } catch( ... ) { return FALSE; } } //////////////////////////////////////////////////////////////////////////////// // Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: // // 1. il percorso indicato da percBase // // 2. un carattere '\' // // 3. il nome del file indicato da "nomeAgg" // // Il parametro percBase DEVE riguardare una stringa C valida e non vuota. // // E' compito del chiamante deallocare la stringa restituita quando non piu' // // necessaria. // //////////////////////////////////////////////////////////////////////////////// char *ComponiPercorso( const char *percBase, const char *nomeAgg ) { const char *sep[] = { "", "\" }; try { int lPercBase = lstrlen( percBase ); int lNomeAgg = lstrlen( nomeAgg ); int lSep = lstrlen( sep[lPercBase>3] ); int lPerc = lPercBase + lSep + lNomeAgg; char *perc = new char[lPerc+1]; wsprintf( perc, "%s%s%s", percBase, sep[lPercBase>3], nomeAgg ); return perc; } catch( ... ) { return NULL; } } //////////////////////////////////////////////////////////////////////////////// // Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il // // percorso assume quindi l'aspetto C:\Cartella. // // Il parametro "pc" sta per [p]ercorso [c]ompleto. // // Il parametro "lp" sta per [l]unghezza [p]ercorso. // // Restituisce la lunghezza del percorso risultante. // //////////////////////////////////////////////////////////////////////////////// DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) { for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp ) pc[lp] = 'Il copia-e-incolla del codice sorgente dal quale credo nasca il problema è questo:

////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='{parsed_message}'; }

        if( l >= 0 ) {
            delete[] buff;
            buff = new char[l+1];
            l = GetModuleFileName( hndIstanza, buff, l+1 );
        }

        *pBuffer = buff;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: //
//     1. il percorso indicato da percBase                                    //
//     2. un carattere '\'                                                   //
//     3. il nome del file indicato da "nomeAgg"                              //
// Il parametro percBase DEVE riguardare una stringa C valida e non vuota.    //
// E' compito del chiamante deallocare la stringa restituita quando non piu'  //
// necessaria.                                                                //
////////////////////////////////////////////////////////////////////////////////

char *ComponiPercorso( const char *percBase, const char *nomeAgg ) {
    const char *sep[] = { "", "\" };

    try {
        int lPercBase = lstrlen( percBase );
        int lNomeAgg  = lstrlen( nomeAgg );
        int lSep      = lstrlen( sep[lPercBase>3] );
        int lPerc = lPercBase + lSep + lNomeAgg;
        char *perc = new char[lPerc+1];
        wsprintf( perc, "%s%s%s", percBase, sep[lPercBase>3], nomeAgg );
        return perc;
    } catch( ... ) {
        return NULL;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il  //
// percorso assume quindi l'aspetto C:\Cartella.                              //
// Il parametro "pc" sta per [p]ercorso [c]ompleto.                           //
// Il parametro "lp" sta per [l]unghezza [p]ercorso.                          //
// Restituisce la lunghezza del percorso risultante.                          //
////////////////////////////////////////////////////////////////////////////////

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
    return lstrlen( pc );
}
'; return lstrlen( pc ); }
Ultima modifica effettuata da 11/11/14 0:56
11/11/14 9:11
Questa mattina mi son svegliato e, come per incanto, nella nebbia del dormiveglia ho avuto un' "illuminazione"! Non so spiegarmelo e so che ha dell'incredibile, però è così. Credo che aver riordinato le idee per spiegarle su questo forum sia stato fondamentale per "mettere in moto" i neuroni, per cui parte del merito è comunque vostro (ringrazio Nessuno per l'aiuto, anche se può sembrare che non ci sia stato nessun aiuto).

Comunque sia, alzatomi in fretta e furia, ho provato queste modifiche:

////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='Questa mattina mi son svegliato e, come per incanto, nella nebbia del dormiveglia ho avuto un' "illuminazione"! Non so spiegarmelo e so che ha dell'incredibile, però è così. Credo che aver riordinato le idee per spiegarle su questo forum sia stato fondamentale per "mettere in moto" i neuroni, per cui parte del merito è comunque vostro (ringrazio Nessuno per l'aiuto, anche se può sembrare che non ci sia stato nessun aiuto).


Comunque sia, alzatomi in fretta e furia, ho provato queste modifiche:

////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='{parsed_message}'; }

        if( l >= 0 ) {
            delete[] buff;
            buff = new char[l+1];
            l = GetModuleFileName( hndIstanza, buff, l+1 );
        }

        *pBuffer = buff;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: //
//     1. il percorso indicato da percBase                                    //
//     2. un carattere '\'                                                   //
//     3. il nome del file indicato da "nomeAgg"                              //
// Il parametro percBase DEVE riguardare una stringa C valida e non vuota.    //
// E' compito del chiamante deallocare la stringa restituita quando non piu'  //
// necessaria.                                                                //
////////////////////////////////////////////////////////////////////////////////

char *ComponiPercorso( const char *percBase, const char *nomeAgg ) {
    try {
        int lPercBase = lstrlen( percBase );
        int lNomeAgg = lstrlen( nomeAgg );

        // determina quale separatore usare
        const char *seps[] = { "", "\" };
        const char *sep = seps[lPercBase>3];
        int lSep = lstrlen( sep );

        // determina la lunghezza del percorso in uscita
        int lPerc = lPercBase + lSep + lNomeAgg;

        char *perc = new char[lPerc+1];

        wsprintf( perc, "%s%s%s", percBase, sep, nomeAgg );

        return perc;
    } catch( ... ) {
        return NULL;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il  //
// percorso assume quindi l'aspetto C:\Cartella.                              //
// Il parametro "pc" sta per [p]ercorso [c]ompleto.                           //
// Il parametro "lp" sta per [l]unghezza [p]ercorso.                          //
// Restituisce la lunghezza del percorso risultante.                          //
////////////////////////////////////////////////////////////////////////////////

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere
    // '\', elimina l'ultimo carattere del percorso
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else --lp;

    return lp;
}


Ora pare che tutto funzioni, ma non ho a disposizione i molti computer che uso al lavoro, per cui ora copio l'eseguibile sulla mia fedele USB-Stick e domani testo il programma nelle classi, con Windows XP e Windows 8 negli ambienti di rete maniacalmente protetti della scuola. Sono fiducioso!'; } if( l >= 0 ) { delete[] buff; buff = new char[l+1]; l = GetModuleFileName( hndIstanza, buff, l+1 ); } *pBuffer = buff; return TRUE; } catch( ... ) { return FALSE; } } //////////////////////////////////////////////////////////////////////////////// // Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: // // 1. il percorso indicato da percBase // // 2. un carattere '\' // // 3. il nome del file indicato da "nomeAgg" // // Il parametro percBase DEVE riguardare una stringa C valida e non vuota. // // E' compito del chiamante deallocare la stringa restituita quando non piu' // // necessaria. // //////////////////////////////////////////////////////////////////////////////// char *ComponiPercorso( const char *percBase, const char *nomeAgg ) { try { int lPercBase = lstrlen( percBase ); int lNomeAgg = lstrlen( nomeAgg ); // determina quale separatore usare const char *seps[] = { "", "\" }; const char *sep = seps[lPercBase>3]; int lSep = lstrlen( sep ); // determina la lunghezza del percorso in uscita int lPerc = lPercBase + lSep + lNomeAgg; char *perc = new char[lPerc+1]; wsprintf( perc, "%s%s%s", percBase, sep, nomeAgg ); return perc; } catch( ... ) { return NULL; } } //////////////////////////////////////////////////////////////////////////////// // Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il // // percorso assume quindi l'aspetto C:\Cartella. // // Il parametro "pc" sta per [p]ercorso [c]ompleto. // // Il parametro "lp" sta per [l]unghezza [p]ercorso. // // Restituisce la lunghezza del percorso risultante. // //////////////////////////////////////////////////////////////////////////////// DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) { for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp ) pc[lp] = 'Questa mattina mi son svegliato e, come per incanto, nella nebbia del dormiveglia ho avuto un' "illuminazione"! Non so spiegarmelo e so che ha dell'incredibile, però è così. Credo che aver riordinato le idee per spiegarle su questo forum sia stato fondamentale per "mettere in moto" i neuroni, per cui parte del merito è comunque vostro (ringrazio Nessuno per l'aiuto, anche se può sembrare che non ci sia stato nessun aiuto).

Comunque sia, alzatomi in fretta e furia, ho provato queste modifiche:

////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='{parsed_message}'; }

        if( l >= 0 ) {
            delete[] buff;
            buff = new char[l+1];
            l = GetModuleFileName( hndIstanza, buff, l+1 );
        }

        *pBuffer = buff;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: //
//     1. il percorso indicato da percBase                                    //
//     2. un carattere '\'                                                   //
//     3. il nome del file indicato da "nomeAgg"                              //
// Il parametro percBase DEVE riguardare una stringa C valida e non vuota.    //
// E' compito del chiamante deallocare la stringa restituita quando non piu'  //
// necessaria.                                                                //
////////////////////////////////////////////////////////////////////////////////

char *ComponiPercorso( const char *percBase, const char *nomeAgg ) {
    try {
        int lPercBase = lstrlen( percBase );
        int lNomeAgg = lstrlen( nomeAgg );

        // determina quale separatore usare
        const char *seps[] = { "", "\" };
        const char *sep = seps[lPercBase>3];
        int lSep = lstrlen( sep );

        // determina la lunghezza del percorso in uscita
        int lPerc = lPercBase + lSep + lNomeAgg;

        char *perc = new char[lPerc+1];

        wsprintf( perc, "%s%s%s", percBase, sep, nomeAgg );

        return perc;
    } catch( ... ) {
        return NULL;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il  //
// percorso assume quindi l'aspetto C:\Cartella.                              //
// Il parametro "pc" sta per [p]ercorso [c]ompleto.                           //
// Il parametro "lp" sta per [l]unghezza [p]ercorso.                          //
// Restituisce la lunghezza del percorso risultante.                          //
////////////////////////////////////////////////////////////////////////////////

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere
    // '\', elimina l'ultimo carattere del percorso
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else --lp;

    return lp;
}


Ora pare che tutto funzioni, ma non ho a disposizione i molti computer che uso al lavoro, per cui ora copio l'eseguibile sulla mia fedele USB-Stick e domani testo il programma nelle classi, con Windows XP e Windows 8 negli ambienti di rete maniacalmente protetti della scuola. Sono fiducioso!'; // se il percorso "tagliato" termina con un carattere // '\', elimina l'ultimo carattere del percorso if( pc[lp] == '\' || pc[lp] == '/' ) pc[lp] = 'Questa mattina mi son svegliato e, come per incanto, nella nebbia del dormiveglia ho avuto un' "illuminazione"! Non so spiegarmelo e so che ha dell'incredibile, però è così. Credo che aver riordinato le idee per spiegarle su questo forum sia stato fondamentale per "mettere in moto" i neuroni, per cui parte del merito è comunque vostro (ringrazio Nessuno per l'aiuto, anche se può sembrare che non ci sia stato nessun aiuto).

Comunque sia, alzatomi in fretta e furia, ho provato queste modifiche:

////////////////////////////////////////////////////////////////////////////////
// Restituisce in pBuffer il puntatore ad uno spazio di memoria allocato      //
// dinamicamente che contiene il percorso completo della cartella nella quale //
// si trova il file eseguibile del programma abbinato ad hndIstanza.          //
// La memoria dinamica puntata da pBuffer DEVE essere liberata per mezzo di   //
// delete[].                                                                  //
////////////////////////////////////////////////////////////////////////////////

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        char *buff = new char[8*MAX_PATH];
        DWORD l = GetModuleFileName( hndIstanza, buff, 8*MAX_PATH );

        l = EliminaUltimaPartePercorso( buff, l );
        if( l>1 && buff[l-1]==':' ) { buff[l]='\'; buff[++l]='{parsed_message}'; }

        if( l >= 0 ) {
            delete[] buff;
            buff = new char[l+1];
            l = GetModuleFileName( hndIstanza, buff, l+1 );
        }

        *pBuffer = buff;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Alloca dinamicamente una stringa nella quale vengono inseriti nell'ordine: //
//     1. il percorso indicato da percBase                                    //
//     2. un carattere '\'                                                   //
//     3. il nome del file indicato da "nomeAgg"                              //
// Il parametro percBase DEVE riguardare una stringa C valida e non vuota.    //
// E' compito del chiamante deallocare la stringa restituita quando non piu'  //
// necessaria.                                                                //
////////////////////////////////////////////////////////////////////////////////

char *ComponiPercorso( const char *percBase, const char *nomeAgg ) {
    try {
        int lPercBase = lstrlen( percBase );
        int lNomeAgg = lstrlen( nomeAgg );

        // determina quale separatore usare
        const char *seps[] = { "", "\" };
        const char *sep = seps[lPercBase>3];
        int lSep = lstrlen( sep );

        // determina la lunghezza del percorso in uscita
        int lPerc = lPercBase + lSep + lNomeAgg;

        char *perc = new char[lPerc+1];

        wsprintf( perc, "%s%s%s", percBase, sep, nomeAgg );

        return perc;
    } catch( ... ) {
        return NULL;
    }
}


////////////////////////////////////////////////////////////////////////////////
// Dato un percorso (es. C:\Cartella\file.txt) ne elimina l'ultima parte. Il  //
// percorso assume quindi l'aspetto C:\Cartella.                              //
// Il parametro "pc" sta per [p]ercorso [c]ompleto.                           //
// Il parametro "lp" sta per [l]unghezza [p]ercorso.                          //
// Restituisce la lunghezza del percorso risultante.                          //
////////////////////////////////////////////////////////////////////////////////

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere
    // '\', elimina l'ultimo carattere del percorso
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else --lp;

    return lp;
}


Ora pare che tutto funzioni, ma non ho a disposizione i molti computer che uso al lavoro, per cui ora copio l'eseguibile sulla mia fedele USB-Stick e domani testo il programma nelle classi, con Windows XP e Windows 8 negli ambienti di rete maniacalmente protetti della scuola. Sono fiducioso!'; else --lp; return lp; }


Ora pare che tutto funzioni, ma non ho a disposizione i molti computer che uso al lavoro, per cui ora copio l'eseguibile sulla mia fedele USB-Stick e domani testo il programma nelle classi, con Windows XP e Windows 8 negli ambienti di rete maniacalmente protetti della scuola. Sono fiducioso!
Ultima modifica effettuata da 11/11/14 9:25
11/11/14 9:30
nessuno
Scusa ma non ho avuto modo di controllare le differenze ... cosa hai fatto per correggere?
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità;) chiamava il gioco del Lotto Tassa sulla stupidità.
11/11/14 10:10
A parte alcune inezie formali, per un errore cretino in EliminaUltimaPartePercorso() in certe situazioni veniva lasciato un carattere '\' di troppo in fondo al percorso. In conseguenza, quando si costruivano i percorsi alla cartella e ai file di supporto risultava un carattere '\' "erratico" che a volte mandava tutto a rotoli.

La versione "fallata":

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = 'A parte alcune inezie formali, per un errore cretino in EliminaUltimaPartePercorso() in certe situazioni veniva lasciato un carattere '\' di troppo in fondo al percorso. In conseguenza, quando si costruivano i percorsi alla cartella e ai file di supporto risultava un carattere '\' "erratico" che a volte mandava tutto a rotoli.


La versione "fallata":

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
    return lstrlen( pc );
}


La versione revisionata:

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
 
    // se il percorso "tagliato" termina con un carattere
    // '\', elimina l'ultimo carattere del percorso
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else --lp;
 
    return lp;
}


Tutto sperando che in fase di testing non vengano fuori altri problemi...'; return lstrlen( pc ); }


La versione revisionata:

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = 'A parte alcune inezie formali, per un errore cretino in EliminaUltimaPartePercorso() in certe situazioni veniva lasciato un carattere '\' di troppo in fondo al percorso. In conseguenza, quando si costruivano i percorsi alla cartella e ai file di supporto risultava un carattere '\' "erratico" che a volte mandava tutto a rotoli.


La versione "fallata":

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
    return lstrlen( pc );
}


La versione revisionata:

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
 
    // se il percorso "tagliato" termina con un carattere
    // '\', elimina l'ultimo carattere del percorso
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else --lp;
 
    return lp;
}


Tutto sperando che in fase di testing non vengano fuori altri problemi...'; // se il percorso "tagliato" termina con un carattere // '\', elimina l'ultimo carattere del percorso if( pc[lp] == '\' || pc[lp] == '/' ) pc[lp] = 'A parte alcune inezie formali, per un errore cretino in EliminaUltimaPartePercorso() in certe situazioni veniva lasciato un carattere '\' di troppo in fondo al percorso. In conseguenza, quando si costruivano i percorsi alla cartella e ai file di supporto risultava un carattere '\' "erratico" che a volte mandava tutto a rotoli.

La versione "fallata":

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
    return lstrlen( pc );
}


La versione revisionata:

DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';
 
    // se il percorso "tagliato" termina con un carattere
    // '\', elimina l'ultimo carattere del percorso
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else --lp;
 
    return lp;
}


Tutto sperando che in fase di testing non vengano fuori altri problemi...'; else --lp; return lp; }


Tutto sperando che in fase di testing non vengano fuori altri problemi...
11/11/14 19:06
Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.

Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = 'Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.


Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!

        dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc );
        if( dimPerc>1 && buffer[dimPerc-1]==':' )
            { buffer[dimPerc]='\'; buffer[++dimPerc]='{parsed_message}'; }

        if( dimPerc >= 0 ) {
            delete[] buffer;
            buffer = new char[dimPerc+1];
            GetModuleFileName( hndIstanza, buffer, dimPerc+1 );
            buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!
        }

        *pBuffer = buffer;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere '\', elimina
    // l'ultimo carattere del percorso; per evitare problemi dovuti ai
    // "capricci" di Microsoft, termina la stringa
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else pc[--lp] = '{parsed_message}';

    return lp;
}
'; // XP non termina la stringa, Windows 7 sì!!! dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc ); if( dimPerc>1 && buffer[dimPerc-1]==':' ) { buffer[dimPerc]='\'; buffer[++dimPerc]='Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.

Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!

        dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc );
        if( dimPerc>1 && buffer[dimPerc-1]==':' )
            { buffer[dimPerc]='\'; buffer[++dimPerc]='{parsed_message}'; }

        if( dimPerc >= 0 ) {
            delete[] buffer;
            buffer = new char[dimPerc+1];
            GetModuleFileName( hndIstanza, buffer, dimPerc+1 );
            buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!
        }

        *pBuffer = buffer;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere '\', elimina
    // l'ultimo carattere del percorso; per evitare problemi dovuti ai
    // "capricci" di Microsoft, termina la stringa
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else pc[--lp] = '{parsed_message}';

    return lp;
}
'; } if( dimPerc >= 0 ) { delete[] buffer; buffer = new char[dimPerc+1]; GetModuleFileName( hndIstanza, buffer, dimPerc+1 ); buffer[dimPerc] = 'Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.

Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!

        dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc );
        if( dimPerc>1 && buffer[dimPerc-1]==':' )
            { buffer[dimPerc]='\'; buffer[++dimPerc]='{parsed_message}'; }

        if( dimPerc >= 0 ) {
            delete[] buffer;
            buffer = new char[dimPerc+1];
            GetModuleFileName( hndIstanza, buffer, dimPerc+1 );
            buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!
        }

        *pBuffer = buffer;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere '\', elimina
    // l'ultimo carattere del percorso; per evitare problemi dovuti ai
    // "capricci" di Microsoft, termina la stringa
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else pc[--lp] = '{parsed_message}';

    return lp;
}
'; // XP non termina la stringa, Windows 7 sì!!! } *pBuffer = buffer; return TRUE; } catch( ... ) { return FALSE; } } DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) { for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp ) pc[lp] = 'Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.

Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!

        dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc );
        if( dimPerc>1 && buffer[dimPerc-1]==':' )
            { buffer[dimPerc]='\'; buffer[++dimPerc]='{parsed_message}'; }

        if( dimPerc >= 0 ) {
            delete[] buffer;
            buffer = new char[dimPerc+1];
            GetModuleFileName( hndIstanza, buffer, dimPerc+1 );
            buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!
        }

        *pBuffer = buffer;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere '\', elimina
    // l'ultimo carattere del percorso; per evitare problemi dovuti ai
    // "capricci" di Microsoft, termina la stringa
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else pc[--lp] = '{parsed_message}';

    return lp;
}
'; // se il percorso "tagliato" termina con un carattere '\', elimina // l'ultimo carattere del percorso; per evitare problemi dovuti ai // "capricci" di Microsoft, termina la stringa if( pc[lp] == '\' || pc[lp] == '/' ) pc[lp] = 'Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.

Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!

        dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc );
        if( dimPerc>1 && buffer[dimPerc-1]==':' )
            { buffer[dimPerc]='\'; buffer[++dimPerc]='{parsed_message}'; }

        if( dimPerc >= 0 ) {
            delete[] buffer;
            buffer = new char[dimPerc+1];
            GetModuleFileName( hndIstanza, buffer, dimPerc+1 );
            buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!
        }

        *pBuffer = buffer;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere '\', elimina
    // l'ultimo carattere del percorso; per evitare problemi dovuti ai
    // "capricci" di Microsoft, termina la stringa
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else pc[--lp] = '{parsed_message}';

    return lp;
}
'; else pc[--lp] = 'Questa sera, dopo il lavoro, ho provato qualche ulteriore test ed ho scoperto una cosa che, se vera, ha dell'incredibile: pare che XP dia come esito di GetModuleFileName() una stringa non zero-terminata, mentre Windows 7 pare dare come esito una stringa zero-terminata. Se venisse confermata questa situazione, direi che Microsoft ha fatto una figura barbina: cambiare una funzione senza cambiarne il nome o i parametri (in modo da rendere impossibile ogni forma di confusione) è uno sgambetto che non ci si aspetterebbe da una ditta seria.

Ora RicavaPercorsoProgramma() funziona sul mio XP come sul mio Windows 7 di casa. Domani vedrò come si comporta sui computer "blindati" della scuola, con un mix di XP, 7 e 8.

BOOL RicavaPercorsoProgramma( HINSTANCE hndIstanza, LPSTR *pBuffer ) {
    try {
        int dimPerc = 0; // dimensioni del percorso
        int dimBuff = 0; // dimensioni del buffer
        char *buffer = NULL;

        do {
            delete[] buffer;
            dimBuff += MAX_PATH;
            buffer = new char[dimBuff];
            dimPerc = GetModuleFileName( hndIstanza, buffer, dimBuff );
            if( dimPerc == 0 ) { delete[] buffer; return FALSE; }
        } while( dimPerc >= dimBuff );

        buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!

        dimPerc = EliminaUltimaPartePercorso( buffer, dimPerc );
        if( dimPerc>1 && buffer[dimPerc-1]==':' )
            { buffer[dimPerc]='\'; buffer[++dimPerc]='{parsed_message}'; }

        if( dimPerc >= 0 ) {
            delete[] buffer;
            buffer = new char[dimPerc+1];
            GetModuleFileName( hndIstanza, buffer, dimPerc+1 );
            buffer[dimPerc] = '{parsed_message}'; // XP non termina la stringa, Windows 7 sì!!!
        }

        *pBuffer = buffer;

        return TRUE;
    } catch( ... ) {
        return FALSE;
    }
}


DWORD EliminaUltimaPartePercorso( char *pc, DWORD lp ) {
    for( --lp; pc[lp]!='\' && pc[lp]!='/' && lp>=0; --lp )
        pc[lp] = '{parsed_message}';

    // se il percorso "tagliato" termina con un carattere '\', elimina
    // l'ultimo carattere del percorso; per evitare problemi dovuti ai
    // "capricci" di Microsoft, termina la stringa
    if( pc[lp] == '\' || pc[lp] == '/' )
        pc[lp] = '{parsed_message}';
    else pc[--lp] = '{parsed_message}';

    return lp;
}
'; return lp; }