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...