2010-02-10 8 views
4

Je dois créer un répertoire à l'intérieur de COMMONAPPDATA (s'il n'existe pas) avec tous les droits de tous les utilisateurs de cet ordinateur (tout le monde pourra lire ou écrire dans ce répertoire). Je suis à la recherche de code natif simple pour faire cela en Delphi, sans utiliser de bibliothèques ou composants tiers.Comment créer un répertoire en cours d'exécution avec tous les droits sur tous les utilisateurs, en utilisant Delphi?

+3

Donc, si je prends le code JCL, copier et le coller dans une autre unité, et l'appeler DefinitelyNotAJclUnit.pas, ce que ce sera mieux? –

+1

Peut-être que vous pouvez utiliser le programme d'installation à la place pour créer le répertoire et définir les autorisations correctes? Inno Setup a par exemple le paramètre 'Permissions' pour les répertoires, voir http://www.jrsoftware.org/isfaq.php#perms. – mghie

+0

Les unités Jedi ont tellement de dépendances que j'aimerais les éviter. Le programme d'installation n'est pas une option car l'application est déjà installée sur plusieurs clients/machines. – WarmBooter

Répondre

3

Je voudrais pouvoir commenter et demander "pourquoi?".

L'exécutable devrait être exécuté en mode administrateur (si la plupart de vos utilisateurs verraient invite d'élévation)

Pourquoi ne pas utiliser les dossiers APPDATA ou localappdata, ou la part du public?

est ici un lien à une question similaire: Delphi 2009 classes/components to read/write file permissions

+0

Exactement. Votre application devrait être exécutée avec tous les droits, et les droits élevés sur Win7 ne sont généralement pas accordés même aux administrateurs, sauf après avoir approuvé une installation. Ainsi, je pense que vous allez devoir faire un "outil" spécial avec ce code, que l'utilisateur doit exécuter en hauteur. –

+0

+1. Maintenant vous pouvez. :) Mais je pense que c'est la bonne réponse, de toute façon ... –

+2

Quelle est la bonne réponse? Cela n'essaie même pas de répondre à la question. Il y a des raisons de vouloir un tel répertoire. 'APPDATA' et' LOCALAPPDATA' ne conviennent pas pour les données d'application partagées entre les utilisateurs (comme les fichiers de base de données). Comme c'est la part du public, c'est pour d'autres choses. – mghie

9

@WarmBooter, vous pouvez utiliser la fonction CreateDirectory pour accomplir cette tâche.

voir cet exemple:

program Project645; 

{$APPTYPE CONSOLE} 

uses 
    AccCtrl, 
    AclApi, 
    Windows, 
    SysUtils; 


type 

    PTrusteeW = ^TTrusteeW; 
    TTrusteeW = record 
    pMultipleTrustee: PTrusteeW; 
    MultipleTrusteeOperation: DWORD; { MULTIPLE_TRUSTEE_OPERATION } 
    TrusteeForm: DWORD; { TRUSTEE_FORM } 
    TrusteeType: DWORD; { TRUSTEE_TYPE } 
    ptstrName: PWideChar; 
    end; 
    TExplicitAccessW = record 
    grfAccessPermissions: DWORD; 
    grfAccessMode: DWORD; { ACCESS_MODE } 
    grfInheritance: DWORD; 
    Trustee: TTrusteeW; 
    end; 



Function CreateDirectoryFullAccess(NewDirectory:String) :Boolean; 
var 
    SecurityAttributes : TSecurityAttributes; 
    SecurityDescriptor : PSecurityDescriptor; 
    ExplicitAccess  : array[0..0] of TExplicitAccessW; 
    easize    : integer; 
    pACL    : Windows.PACL; 
begin 
    ExplicitAccess[0].grfAccessPermissions:= STANDARD_RIGHTS_ALL or SPECIFIC_RIGHTS_ALL; 
    ExplicitAccess[0].grfAccessMode:=Ord(SET_ACCESS); 
    ExplicitAccess[0].grfInheritance:=SUB_CONTAINERS_AND_OBJECTS_INHERIT; 
    ExplicitAccess[0].Trustee.TrusteeForm:=Ord(TRUSTEE_IS_NAME); 
    ExplicitAccess[0].Trustee.TrusteeType:=Ord(TRUSTEE_IS_USER); 
    ExplicitAccess[0].Trustee.ptstrName:='Everyone';//Access for all users 
    SetEntriesinAclW(1,@ExplicitAccess,nil,pACL);//creates a new access control list 

    //SecurityDescriptor:= AllocMem(Sizeof(SECURITY_DESCRIPTOR_MIN_LENGTH)); 
    SecurityDescriptor:= AllocMem(SECURITY_DESCRIPTOR_MIN_LENGTH); 
    InitializeSecurityDescriptor(SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION); 
    SetSecurityDescriptorDacl(SecurityDescriptor,true,pacl,false);//sets information in a discretionary access control list (DACL). 

    FillChar(SecurityAttributes,sizeof(SECURITY_ATTRIBUTES),#0); 
    SecurityAttributes.nLength:=sizeof(SECURITY_ATTRIBUTES); 
    SecurityAttributes.lpSecurityDescriptor:=SecurityDescriptor; 
    SecurityAttributes.bInheritHandle:=false; 
    CreateDirectory(PChar(NewDirectory),@SecurityAttributes); 
    Result:=GetLastError=0;// if all ok, GetLastError = 0 
end; 

begin 
    if CreateDirectoryFullAccess('C:\MyNewDir') then 
    Writeln('Ok') 
    else 
    Writeln('Failed'); 

    Readln; 
end. 
+0

Pour définir les autorisations sur un répertoire existant, utilisez la fonction 'SetNamedSecurityInfo()' (http://msdn.microsoft.com/en-us/library/aa379579%28VS.85%29.aspx) - Google doit afficher un exemple code. – mghie

+0

@RRUZ, votre code a l'air simple et facile! Je vais l'essayer. Merci! – WarmBooter

Questions connexes