N
nico
Hello
I have write this program that retrieve all directory and subdirectory
recursively of a given directory given in parameter.
For each directory, the script find all user permission for the current
directory and add the username, permission and directory name into MySQL.
The code works fine, but too slow.
He need aproximate 1 hour to scan 200 directory.
How to optimize this code please ?
I know I can improve it but I code with C# just for some days.
1 * Time: 08:59
2 *
3 * To change this template use Tools | Options | Coding | Edit Standard
Headers.
4 */
5
6 using System;
7 using System.IO;
8 using System.Data;
9 using System.Data.SqlClient;
10 using System.Data.Common;
11 using System.Management;
12 using System.Collections;
13 using ByteFX;
14 using ByteFX.Data.MySqlClient;
15 using System.Diagnostics;
16 using System.ComponentModel;
17
18 namespace System.Management
19
20 {
21 class wmi_scan_dossier
22 {
23 private string _nom_pc;
24 private MySqlConnection _id_con_mysql;
25 private System.Management.ManagementScope _oMs;
26
27 private MySqlConnection id_con_mysql
28 {
29 get
30 {
31 return _id_con_mysql;
32 }
33 set
34 {
35 _id_con_mysql = value;
36 }
37 }
38
39 private System.Management.ManagementScope oMs
40 {
41 get
42 {
43 return _oMs;
44 }
45 set
46 {
47 oMs = value;
48 }
49 }
50
51 void connect_mysql()
52 {
53 string ConnectionString = ConnectionString = "Database=toto;Data
Source=localhost;User Id=root;Password=XXX";
54 MySqlConnection _id_con_mysql = new MySqlConnection(ConnectionString);
55 _id_con_mysql.Open();
56 this.id_con_mysql = _id_con_mysql;
57 }
58
59 void mysql_query(string sql)
60 {
61 //this.connect_mysql();
62 MySqlCommand query_ajoute_dossier = new MySqlCommand(sql,
this.id_con_mysql);
63 query_ajoute_dossier.ExecuteNonQuery();
64 }
65
66 void mysql_deconnect()
67 {
68 this.id_con_mysql.Close();
69 }
70
71 public string trouve_nom_pc()
72 {
73 ConnectionOptions oConn = new ConnectionOptions();
74 //oConn.Username = "stist"; // je specifie le login local (pas
obligatoire si le programme est executer sur la machine local
75 //oConn.Password = "stage2004"; // je specifie le mot de passe local (pas
obligatoire si le programme est executer sur la machine local
76
77 //System.Management.ManagementScope oMs = new
System.Management.ManagementScope("\\\\MachineX", oConn);
78 //System.Management.ManagementScope oMs = new
System.Management.ManagementScope("\\\\MachineX");
79
80 //j appel la liste des dossiers d un repertoire de base donnee
81 System.Management.ObjectQuery oQueryPc = new
System.Management.ObjectQuery("SELECT Name from Win32_ComputerSystem");
82
83 //j execute la requete
84 ManagementObjectSearcher oSearcherPc = new
ManagementObjectSearcher(this.connect_wmi(),oQueryPc);
85
86 //je recupere le nom de l ordinateur avec la methode Get
87 ManagementObjectCollection oReturnCollectionPc = oSearcherPc.Get();
88
89 foreach(ManagementObject oReturnPc in oReturnCollectionPc)
90 {
91 _nom_pc = oReturnPc["name"].ToString();
92 }
93 return _nom_pc;
94 }
95
96 public System.Management.ManagementScope connect_wmi()
97 {
98 // fonction retournant l identifiant de connexion a WMI
99 this._oMs = new System.Management.ManagementScope("\\\\MachineX");
100 return this.oMs;
101 }
102
103 public static void Main(string[] args)
104 {
105 string nom_rep_mysql, sql_ajoute_dossier, sql_ajoute_acces, sql_pc;
106
107 wmi_scan_dossier un_scan = new wmi_scan_dossier();
108
109 ArrayList verif_login = new ArrayList(); // je declare un liste de
tableau dynamique qui contiendra la liste des utilisateurs uniques ayant des
droits sur les répertoires traités pour éviter les doublons
110 bool etre_doublon = false;
111
112 //Connection credentials to the remote computer - not needed if the
logged in account has access
113 ConnectionOptions oConn = new ConnectionOptions();
114
115 //j appel la liste des dossiers d un repertoire de base donnee
116 System.Management.ObjectQuery oQueryPc = new
System.Management.ObjectQuery("SELECT Name from Win32_ComputerSystem");
117
118 //j execute la requete
119 ManagementObjectSearcher oSearcherPc = new
ManagementObjectSearcher(un_scan.connect_wmi(),oQueryPc);
120
121 //je recupere le nom de l ordinateur avec la methode Get
122 ManagementObjectCollection oReturnCollectionPc = oSearcherPc.Get();
123
124 int j = args.Length;
125
126 if(j == 0)
127 {
128 Console.WriteLine ("Saisissez un paramètre pour utiliser le logiciel");
129 Console.WriteLine ("Exemple de synthaxe : test_ok.exe \"c:\\Apache\"
\"C:\\Documents and Settings\"");
130 Console.WriteLine ("Cette appel aura pour effet de scanner l'ensemble
des sous dossiers des répertoires c:\\Apache ET C:\\Documents and
Settings");
131
132 }
133 else
134 {
135 Console.WriteLine ("Début du scan du dossier ... patience ");
136 for(int compteur = 0; compteur < j ; compteur ++)
137 {
138 string nom_dossier = args[compteur].ToString();
139 nom_dossier = nom_dossier.Replace ("\\","\\\\");
140 //j appel la liste des dossiers d un repertoire de base donné en
parametre
141 string wql_dossier = "Select Name from Win32_Directory WHERE Name LIKE
'" + nom_dossier + "%'";
142 System.Management.WqlObjectQuery oQuery = new
System.Management.WqlObjectQuery(wql_dossier);
143
144 //j execute la requete
145 ManagementObjectSearcher oSearcher = new
ManagementObjectSearcher(un_scan.connect_wmi(),oQuery);
146
147 oSearcher.Options.ReturnImmediately = true;
148 oSearcher.Options.Rewindable = false;
149 oSearcher.Options.DirectRead = true;
150
151 //je recupere le resultat avec la methode Get
152 ManagementObjectCollection oReturnCollection = oSearcher.Get();
153
154 un_scan.connect_mysql();
155
156 //loop through found drives and write out info
157 foreach( ManagementObject oReturn in oReturnCollection )
158 {
159 string nom_rep = oReturn["Name"].ToString();
160 string verif_nom_rep = nom_rep.Replace("'","\\'"); // je remplace le
caractere ' qui fait planter la requete WMI par \'
161
162 if (nom_rep == verif_nom_rep) // si les 2 variables sont identiques c
est que le nom du repertoire ne contient pas le caractere '
163 {
164 nom_rep_mysql = nom_rep.Replace("\\","\\\\");
165 sql_ajoute_dossier = "REPLACE INTO repertoire VALUES ('" + nom_rep_mysql
+ "')";
166 un_scan.mysql_query(sql_ajoute_dossier);
167
168 ManagementObject LogicalFileSecuritySetting = new ManagementObject( new
ManagementPath( "ROOT\\CIMV2:Win32_LogicalFileSecuritySetting.Path='" +
nom_rep + "'"));
169 ManagementBaseObject inParams = null;
170 bool EnablePrivileges =
LogicalFileSecuritySetting.Scope.Options.EnablePrivileges;
171 LogicalFileSecuritySetting.Scope.Options.EnablePrivileges = true;
172 ManagementBaseObject outParams =
LogicalFileSecuritySetting.InvokeMethod("GetSecurityDescriptor", inParams,
null);
173 ManagementBaseObject Descriptor =
((ManagementBaseObject)(outParams.Properties["Descriptor"].Value));
174 LogicalFileSecuritySetting.Scope.Options.EnablePrivileges =
EnablePrivileges;
175
176 ManagementBaseObject[] DACLObject = ( ( ManagementBaseObject[] )(
Descriptor.Properties["DACL"].Value ) );
177
178 System.Collections.Stack stk = new System.Collections.Stack();
179
180 for(int i = 0; i < DACLObject.Length; i++)
181 {
182 ManagementBaseObject ACE=DACLObject[ i ];
183
184 stk.Push( ACE );
185
186 // si cette acces n a pas encore ete verifiee, je lajoute dans le
fichier et da ns mon arrayList
187 sql_ajoute_acces = "REPLACE INTO acces VALUES ('" + (nom_rep_mysql + "',
'" + ( (ManagementBaseObject) DACLObject[
i ].Properties["Trustee"].Value).Properties["Name"].Value + "', '" +
DACLObject.Properties["AccessMask"].Value + "', '" +
un_scan.trouve_nom_pc() + "', CURRENT_TIMESTAMP())"); // j ecrit le nom du
repertoire courant, le login et l'AccessMask dans le fichier
188 un_scan.mysql_query(sql_ajoute_acces);
189
190 etre_doublon = false;
191
192 foreach (string login in verif_login)
193 {
194 if (login == (string)(un_scan.trouve_nom_pc() + "|" +
((ManagementBaseObject) DACLObject[
i ].Properties["Trustee"].Value).Properties["Name"].Value) + "|" +
un_scan.trouve_nom_pc())
195 {
196 etre_doublon = true;
197 }
198 }
199
200 verif_login.Add (un_scan.trouve_nom_pc() + "|" + ((ManagementBaseObject)
DACLObject[ i ].Properties["Trustee"].Value).Properties["Name"].Value);
201
202 if (!etre_doublon)
203 {
204 sql_pc = "REPLACE pc VALUES ('" + un_scan.trouve_nom_pc() + "', '" +
(( (ManagementBaseObject) DACLObject[
i ].Properties["Trustee"].Value).Properties["Name"].Value + "')"); // j
ajoute le nom de l utilisateur dans la table utilisateur
205 un_scan.mysql_query(sql_pc);
206 }
207 }
208 }
209 }
210 }
211 un_scan.mysql_deconnect();
212 Console.WriteLine ("Analyse des dossiers terminées");
213 }
214 }
215 }
216 }
I have write this program that retrieve all directory and subdirectory
recursively of a given directory given in parameter.
For each directory, the script find all user permission for the current
directory and add the username, permission and directory name into MySQL.
The code works fine, but too slow.
He need aproximate 1 hour to scan 200 directory.
How to optimize this code please ?
I know I can improve it but I code with C# just for some days.
1 * Time: 08:59
2 *
3 * To change this template use Tools | Options | Coding | Edit Standard
Headers.
4 */
5
6 using System;
7 using System.IO;
8 using System.Data;
9 using System.Data.SqlClient;
10 using System.Data.Common;
11 using System.Management;
12 using System.Collections;
13 using ByteFX;
14 using ByteFX.Data.MySqlClient;
15 using System.Diagnostics;
16 using System.ComponentModel;
17
18 namespace System.Management
19
20 {
21 class wmi_scan_dossier
22 {
23 private string _nom_pc;
24 private MySqlConnection _id_con_mysql;
25 private System.Management.ManagementScope _oMs;
26
27 private MySqlConnection id_con_mysql
28 {
29 get
30 {
31 return _id_con_mysql;
32 }
33 set
34 {
35 _id_con_mysql = value;
36 }
37 }
38
39 private System.Management.ManagementScope oMs
40 {
41 get
42 {
43 return _oMs;
44 }
45 set
46 {
47 oMs = value;
48 }
49 }
50
51 void connect_mysql()
52 {
53 string ConnectionString = ConnectionString = "Database=toto;Data
Source=localhost;User Id=root;Password=XXX";
54 MySqlConnection _id_con_mysql = new MySqlConnection(ConnectionString);
55 _id_con_mysql.Open();
56 this.id_con_mysql = _id_con_mysql;
57 }
58
59 void mysql_query(string sql)
60 {
61 //this.connect_mysql();
62 MySqlCommand query_ajoute_dossier = new MySqlCommand(sql,
this.id_con_mysql);
63 query_ajoute_dossier.ExecuteNonQuery();
64 }
65
66 void mysql_deconnect()
67 {
68 this.id_con_mysql.Close();
69 }
70
71 public string trouve_nom_pc()
72 {
73 ConnectionOptions oConn = new ConnectionOptions();
74 //oConn.Username = "stist"; // je specifie le login local (pas
obligatoire si le programme est executer sur la machine local
75 //oConn.Password = "stage2004"; // je specifie le mot de passe local (pas
obligatoire si le programme est executer sur la machine local
76
77 //System.Management.ManagementScope oMs = new
System.Management.ManagementScope("\\\\MachineX", oConn);
78 //System.Management.ManagementScope oMs = new
System.Management.ManagementScope("\\\\MachineX");
79
80 //j appel la liste des dossiers d un repertoire de base donnee
81 System.Management.ObjectQuery oQueryPc = new
System.Management.ObjectQuery("SELECT Name from Win32_ComputerSystem");
82
83 //j execute la requete
84 ManagementObjectSearcher oSearcherPc = new
ManagementObjectSearcher(this.connect_wmi(),oQueryPc);
85
86 //je recupere le nom de l ordinateur avec la methode Get
87 ManagementObjectCollection oReturnCollectionPc = oSearcherPc.Get();
88
89 foreach(ManagementObject oReturnPc in oReturnCollectionPc)
90 {
91 _nom_pc = oReturnPc["name"].ToString();
92 }
93 return _nom_pc;
94 }
95
96 public System.Management.ManagementScope connect_wmi()
97 {
98 // fonction retournant l identifiant de connexion a WMI
99 this._oMs = new System.Management.ManagementScope("\\\\MachineX");
100 return this.oMs;
101 }
102
103 public static void Main(string[] args)
104 {
105 string nom_rep_mysql, sql_ajoute_dossier, sql_ajoute_acces, sql_pc;
106
107 wmi_scan_dossier un_scan = new wmi_scan_dossier();
108
109 ArrayList verif_login = new ArrayList(); // je declare un liste de
tableau dynamique qui contiendra la liste des utilisateurs uniques ayant des
droits sur les répertoires traités pour éviter les doublons
110 bool etre_doublon = false;
111
112 //Connection credentials to the remote computer - not needed if the
logged in account has access
113 ConnectionOptions oConn = new ConnectionOptions();
114
115 //j appel la liste des dossiers d un repertoire de base donnee
116 System.Management.ObjectQuery oQueryPc = new
System.Management.ObjectQuery("SELECT Name from Win32_ComputerSystem");
117
118 //j execute la requete
119 ManagementObjectSearcher oSearcherPc = new
ManagementObjectSearcher(un_scan.connect_wmi(),oQueryPc);
120
121 //je recupere le nom de l ordinateur avec la methode Get
122 ManagementObjectCollection oReturnCollectionPc = oSearcherPc.Get();
123
124 int j = args.Length;
125
126 if(j == 0)
127 {
128 Console.WriteLine ("Saisissez un paramètre pour utiliser le logiciel");
129 Console.WriteLine ("Exemple de synthaxe : test_ok.exe \"c:\\Apache\"
\"C:\\Documents and Settings\"");
130 Console.WriteLine ("Cette appel aura pour effet de scanner l'ensemble
des sous dossiers des répertoires c:\\Apache ET C:\\Documents and
Settings");
131
132 }
133 else
134 {
135 Console.WriteLine ("Début du scan du dossier ... patience ");
136 for(int compteur = 0; compteur < j ; compteur ++)
137 {
138 string nom_dossier = args[compteur].ToString();
139 nom_dossier = nom_dossier.Replace ("\\","\\\\");
140 //j appel la liste des dossiers d un repertoire de base donné en
parametre
141 string wql_dossier = "Select Name from Win32_Directory WHERE Name LIKE
'" + nom_dossier + "%'";
142 System.Management.WqlObjectQuery oQuery = new
System.Management.WqlObjectQuery(wql_dossier);
143
144 //j execute la requete
145 ManagementObjectSearcher oSearcher = new
ManagementObjectSearcher(un_scan.connect_wmi(),oQuery);
146
147 oSearcher.Options.ReturnImmediately = true;
148 oSearcher.Options.Rewindable = false;
149 oSearcher.Options.DirectRead = true;
150
151 //je recupere le resultat avec la methode Get
152 ManagementObjectCollection oReturnCollection = oSearcher.Get();
153
154 un_scan.connect_mysql();
155
156 //loop through found drives and write out info
157 foreach( ManagementObject oReturn in oReturnCollection )
158 {
159 string nom_rep = oReturn["Name"].ToString();
160 string verif_nom_rep = nom_rep.Replace("'","\\'"); // je remplace le
caractere ' qui fait planter la requete WMI par \'
161
162 if (nom_rep == verif_nom_rep) // si les 2 variables sont identiques c
est que le nom du repertoire ne contient pas le caractere '
163 {
164 nom_rep_mysql = nom_rep.Replace("\\","\\\\");
165 sql_ajoute_dossier = "REPLACE INTO repertoire VALUES ('" + nom_rep_mysql
+ "')";
166 un_scan.mysql_query(sql_ajoute_dossier);
167
168 ManagementObject LogicalFileSecuritySetting = new ManagementObject( new
ManagementPath( "ROOT\\CIMV2:Win32_LogicalFileSecuritySetting.Path='" +
nom_rep + "'"));
169 ManagementBaseObject inParams = null;
170 bool EnablePrivileges =
LogicalFileSecuritySetting.Scope.Options.EnablePrivileges;
171 LogicalFileSecuritySetting.Scope.Options.EnablePrivileges = true;
172 ManagementBaseObject outParams =
LogicalFileSecuritySetting.InvokeMethod("GetSecurityDescriptor", inParams,
null);
173 ManagementBaseObject Descriptor =
((ManagementBaseObject)(outParams.Properties["Descriptor"].Value));
174 LogicalFileSecuritySetting.Scope.Options.EnablePrivileges =
EnablePrivileges;
175
176 ManagementBaseObject[] DACLObject = ( ( ManagementBaseObject[] )(
Descriptor.Properties["DACL"].Value ) );
177
178 System.Collections.Stack stk = new System.Collections.Stack();
179
180 for(int i = 0; i < DACLObject.Length; i++)
181 {
182 ManagementBaseObject ACE=DACLObject[ i ];
183
184 stk.Push( ACE );
185
186 // si cette acces n a pas encore ete verifiee, je lajoute dans le
fichier et da ns mon arrayList
187 sql_ajoute_acces = "REPLACE INTO acces VALUES ('" + (nom_rep_mysql + "',
'" + ( (ManagementBaseObject) DACLObject[
i ].Properties["Trustee"].Value).Properties["Name"].Value + "', '" +
DACLObject.Properties["AccessMask"].Value + "', '" +
un_scan.trouve_nom_pc() + "', CURRENT_TIMESTAMP())"); // j ecrit le nom du
repertoire courant, le login et l'AccessMask dans le fichier
188 un_scan.mysql_query(sql_ajoute_acces);
189
190 etre_doublon = false;
191
192 foreach (string login in verif_login)
193 {
194 if (login == (string)(un_scan.trouve_nom_pc() + "|" +
((ManagementBaseObject) DACLObject[
i ].Properties["Trustee"].Value).Properties["Name"].Value) + "|" +
un_scan.trouve_nom_pc())
195 {
196 etre_doublon = true;
197 }
198 }
199
200 verif_login.Add (un_scan.trouve_nom_pc() + "|" + ((ManagementBaseObject)
DACLObject[ i ].Properties["Trustee"].Value).Properties["Name"].Value);
201
202 if (!etre_doublon)
203 {
204 sql_pc = "REPLACE pc VALUES ('" + un_scan.trouve_nom_pc() + "', '" +
(( (ManagementBaseObject) DACLObject[
i ].Properties["Trustee"].Value).Properties["Name"].Value + "')"); // j
ajoute le nom de l utilisateur dans la table utilisateur
205 un_scan.mysql_query(sql_pc);
206 }
207 }
208 }
209 }
210 }
211 un_scan.mysql_deconnect();
212 Console.WriteLine ("Analyse des dossiers terminées");
213 }
214 }
215 }
216 }