Sto girovagando da un bel po' attorno al problema di gestire l'elevazione dei previlegi con Windows. Il pattern della situazione è alquanto tipico e che capita a tanti sviluppatori, ossia lanciare un eseguibile esterno con diritti di amministratore, semplicemente perché l'eseguibile esterno deve intraprendere operazioni di manutenzione sulle installazione, come ad esempio un software di aggiornamento.
Anzitutto è necessario prevedere che l'eseguibile sia contrassegnato in modo tale che esso pretenda diritti di amministrazione prima di partire. Per fare questo basta scrivere qualcosina del manifest file esterno o iniettarlo nel manifest interno come risorsa:
<?xml version="1.0" encoding="UTF-8"
standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="2.3.0.0"
processorArchitecture="X86" name="YourUpdater.exe"
type="win32"/>
<description>Update Tool</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
</assembly>
Come potete vedere, i previlegi pretendono di essere amministratore, requireAdministrator, poi sarà carico del sistema operativo tramite UAC (User Access Control) o tramite PCA (Program Compatibility Assistant) a gestire o meno la richiesta all'utente tramite opportuno dialogo con cui intraprendere l'elevazione.
Purtroppo Microsoft continua a rimettere in discussione le politiche di gestione ed ogni qualche mese, il comportamento cambia a seguito di nuove invenzioni di Redmond. Anche alcuni stessi sviluppatori all'interno di Microsoft hanno manifestato tutto il loro disappunto per continuare a cambiare la carte in tavola, cosa su cui gli sviluppatori impazziscono e gli utenti finali ancor di più.
Sostanzialmente se all'interno dell'eseguibile è presente un manifest che dice cosa fare, il problema non si pone, o meglio, non dovrebbe porsi. Esso dice cosa deve fare il sistema, senza che si inventi nulla in particolare. In realtà, già a partire da Windows Vista, il sistema provava per conto suo a tentare l'elevazione semplicemente perché il nome ed il codice binario conteneva qualche occorrenza delle parole "setup", "installer" e "update". Tutto questo però portava al succedere sia dei "false positive" che dei "false negative", con gravi incazzature degli sviluppatori.
Per rendervi conto dell'evoluzione dei fatti, vi lascio a questi articoli:
Ora vi introduco al codice nel mio processo che gira in modalità standard:
Try
updProcess = New Process()
With updProcess.StartInfo
.UseShellExecute = False
.FileName = updPath
.WorkingDirectory = CurDir()
.Arguments = arguments
End With
updProcess.Start()
fileExistsAndLaunched = True
Catch ex As Exception
MsgBox(ex.ToString)
End Try
In realtà ho scoperto una cosa molto più semplice e cioè che Process.Start, se impostato con StartInfo.UseShellExecute a falso, non è in grado di far scattare tutto questo sistema di elevazione dei previlegi, ma esso si ferma a sollevare un'eccezione che recita più o meno così:
ex {Name = "Win32Exception" FullName = "System.ComponentModel.Win32Exception"} System.Type
"Per eseguire l'operazione richiesta è necessaria l'esecuzione con privilegi elevati"
La soluzione è semplice: ricordarsi di farlo con UseShellExecute impostato a vero, anche se all'atto dell'istanziazione di oggetto di classe System.Diagnostics.Process, tale proprietà è già impostata a true, quindi il problema non si pone, a meno che non abbiate tra le mani, come è capitato a me, il caso in cui UseShellExecute era stato forzato a falso...