J'ai essayé de suivre le modèle suggéré OP pour copier les ACL et les attributs d'un fichier et j'ai trouvé quelques problèmes dans notre application. Espérons que cette information aide les autres.
Selon MSDN, l'utilisation de la méthode File.SetAccessControl()
comme indiqué ci-dessus ne fonctionnera pas.
La méthode SetAccessControl persiste uniquement les objets FileSecurity qui ont été modifiés après la création de l'objet. Si un objet FileSecurity n'a pas été modifié, il ne sera pas conservé dans un fichier. Par conséquent, il n'est pas possible de récupérer un objet FileSecurity à partir d'un fichier et réappliquer le même objet à un autre fichier.
Il est nécessaire de faire un nouvel objet FileSecurity
pour le fichier de destination et attribuer à cette une copie de la source objet FileSecurity
.
Voici un exemple d'un modèle qui fonctionne à partir de notre application. Après avoir corrigé le premier problème, nous avons constaté que l'attribut propriétaire n'était pas copié. Au lieu de cela, le fichier de destination appartenait à l'administrateur dans notre cas. Pour contourner ce problème, le processus doit activer le privilège SE_RESTORE_NAME. Découvrez AdjustTokenPrivileges
sur pinvoke.net pour une classe Privileges complète qui facilite les privilèges de configuration.
La dernière chose que nous avons dû faire était UAC. Nous devions redémarrer notre application avec des droits d'administration si l'utilisateur s'exécutait sous UAC. Voici un autre exemple de notre application qui traite de relancer l'application avec des privilèges élevés.
private static void RelaunchWithAdministratorRights(string[] args)
{
// Launch as administrator
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.UseShellExecute = true;
processStartInfo.WorkingDirectory = Environment.CurrentDirectory;
string executablePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
processStartInfo.FileName = executablePath;
processStartInfo.Verb = "runas";
if (args != null && args.Count() > 0)
{
string arguments = args[0];
for (int i = 1; i < args.Count(); i++)
arguments += " " + args[i];
processStartInfo.Arguments = arguments;
}
try
{
using (Process exeProcess = Process.Start(processStartInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// The user refused to allow privileges elevation. Do nothing and return directly ...
}
Environment.Exit(0);
}
nôtre était une application console donc nous avons besoin de passer le paramètre args
de la méthode Main
au RelaunchWithAdministratorRights(args)
. Les applications non-console peuvent passer null à la place. Nous lançons un appel RelaunchWithAdministratorRights
à l'intérieur catch
blocs comme dans:
try
{
...
}
catch (SecurityException)
{
RelaunchWithAdministratorRights(args);
return;
}
Dans notre application nous revenons juste après l'appel à RelaunchWithAdministratorRights
pour quitter l'instance de l'application qui ne disposaient pas de privilèges. En fonction de votre application, vous préférerez peut-être throw
votre sortie.Quoi qu'il en soit, après le retour de RelaunchWithAdministratorRights
vous ne voulez pas que cette instance continue le traitement.
Profitez-en!
Les autorisations de copie des attributs _and_ étaient exactement le comportement que je voulais atteindre. - désolé je ne vous l'ai pas dit avant; ...-) Et oui, l'application s'assure que le compte administrateur est utilisé. – dhh