Oplà!
codice:
//Header di Windows
#include <windows.h>
//Shell lightweight API (per manipolare i path)
#include <shlwapi.h>
//Funzioni stringa standard C
#include <cstring>
//Funzioni ora standard C
#include <ctime>
//Funzioni IO standard C
#include <cstdio>
//Importo il namespace std, in cui si trovano le funzioni standard visto che le ho incluse con gli header C++ e non C
using namespace std;
//Macro per ottenere il numero di elementi di un array allocato sullo stack
#define ARRSIZE(arr) ((size_t)(sizeof(arr)/sizeof(*arr)))
//Prototipi
//Mostra l'help screen
void HelpScreen(HWND Parent);
//Mostra un messaggio di errore
void ErrorMessage(LPWSTR Message);
//Disabilita un warning che in questo punto dà solo fastidio
#pragma warning(push)
#pragma warning(disable:4100)
//Entrypoint
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
//Valore restituito dal programma e numero di argomenti
int ret=ERROR_SUCCESS, argc=0;
//Ottiene la linea di comando e ne effettua il parsing
LPWSTR * argv=CommandLineToArgvW(GetCommandLineW(),&argc);
//Se c'è stato qualche problema con il parsing della linea di comando (non dovrebbe mai accadere, ma non si sa mai)...
if(argv==NULL)
{
//... notifica l'errore
ErrorMessage(L"Errore imprevisto durante il parsing della linea di comando.");
//ed esce con un errore generico.
return ERROR_INTERNAL_ERROR;
}
//Se c'è almeno un argomento ed è /?...
if(argc>=2 && wcscmp(argv[1],L"/?")==0)
{
//...mostra l'help screen
HelpScreen(NULL);
//ed esce con successo
return ERROR_SUCCESS;
}
//Se non ci sono sufficienti argomenti...
if(argc<4)
{
//... notifica l'errore,
ErrorMessage(L"Non ci sono abbastanza parametri.");
//mostra l'help screen
HelpScreen(NULL);
//ed esce usando un codice d'uscita significativo.
return ERROR_INVALID_PARAMETER;
}
//File da aprire, programma con cui aprirlo, percorso di backup, estensione del file
LPWSTR sourceFile, program, backupPath, extension;
//Percorso completo del file di backup
WCHAR targetFile[MAX_PATH];
//Dà agli argomenti degli "alias" più sensati
sourceFile=argv[1];
program=argv[2];
backupPath=argv[3];
//Trova il carattere dove comincia l'estensione del file
extension=PathFindExtension(sourceFile);
//Costruzione del percorso del file di backup
//Combina il nome del file con il percorso di backup
if(PathCombine(targetFile,backupPath,PathFindFileName(sourceFile))==NULL)
{
//In caso di errore, notifica ed esce
ErrorMessage(L"PathCombine ha restituito NULL.");
return ERROR_INTERNAL_ERROR;
}
//Rimuove l'estensione
PathRemoveExtension(targetFile);
//Aggiunge il timestamp e l'estensione
_snwprintf(targetFile+wcslen(targetFile),ARRSIZE(targetFile)-wcslen(targetFile)-1,L"_%x%s",time(NULL),extension);
//Piccolo trucco per evitare problemi con la _snwprintf
targetFile[ARRSIZE(targetFile)-1]=0;
//Resetta il valore dell'ultimo errore
SetLastError(0);
//Copia il file
if(!CopyFile(sourceFile,targetFile,FALSE))
{
//In caso di errore notifica...
ErrorMessage(L"Impossibile copiare il file nella cartella di backup.");
//... e si mette da parte il codice di errore per restituirlo alla fine.
ret=GetLastError();
//Nota che anche se non riesce a copiare prova comunque ad avviare il programma.
}
//Disabilita un warning che in questo punto dà solo fastidio
#pragma warning(push)
#pragma warning(disable:4311)
//Avvia il programma
if((int)ShellExecuteW(NULL,L"open",program,sourceFile,NULL,nCmdShow)<=32)
#pragma warning(pop)
{
//In caso di errore notifica ed esce
ErrorMessage(L"ShellExecute è fallita.");
return ERROR_INTERNAL_ERROR;
}
//Restituisce ERROR_SUCCESS o l'errore per cui la copia è fallita.
return ret;
}
#pragma warning(pop)
//Mostra l'help screen
void HelpScreen(HWND Parent)
{
//Mostra l'help screen
MessageBoxW(Parent,
L"BackupAndStart by Matteo Italia\n"
L"\n"
L"Utilizzo:\n\n"
L"BackupAndStart nomefile programma cartellabackup\n\n"
L"nomefile\t\tNome del file da lanciare e salvare.\n"
L"programma\tNome del programma con cui aprire il file; viene avviato tramite ShellExecute.\n"
L"cartellabacup\tCartella in cui effettuare il backup.",
L"BackupAndStart",
MB_ICONINFORMATION);
}
//Mostra un messaggio di errore
void ErrorMessage(LPWSTR Message)
{
//Buffer per il messaggio
WCHAR message[8192];
//Costruisce il messaggio sulla base dell'argomento passato e dell'ultimo errore avvenuto
_snwprintf(message,ARRSIZE(message),L"%s\nGetLastError: 0x%08x",Message,GetLastError());
//Solito trucco
message[ARRSIZE(message)-1]=0;
//Mostra il messaggio
MessageBoxW(NULL,message,L"Errore",MB_ICONERROR);
}
Download eseguibile.
Download progetto completo.
Di fatto l'intero oggetto è quasi esclusivamente C anche se il file è .cpp (l'ho usato solo per i commenti single-line e per gli header C++-style); è una mezza porcheria, come si può vedere (tutti quegli smanettamenti sulle stringhe non sono mai troppo belli), ma dovrebbe funzionare.
Come riga di comando per l'associazione dei file .ppt metti:
codice:
c:\percorso\BackupAndStart.exe "%1" powerpnt "c:\cartellabackup"
.
Originariamente inviato da skypatrik
Comunque, MItaly non so proprio come ringraziarti per l'impegno. Ti inviterei volentieri a bere qualcosa ma proprio ora mi si è rotta la macchina del teletrasporto

. Magari se passi da queste parti me lo fai sapere.
Quando a Roma avrò bisogno di birra saprò a chi chiedere...