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.Sql Client;
10 using System.Data.Com mon;
11 using System.Manageme nt;
12 using System.Collecti ons;
13 using ByteFX;
14 using ByteFX.Data.MyS qlClient;
15 using System.Diagnost ics;
16 using System.Componen tModel;
17
18 namespace System.Manageme nt
19
20 {
21 class wmi_scan_dossie r
22 {
23 private string _nom_pc;
24 private MySqlConnection _id_con_mysql;
25 private System.Manageme nt.ManagementSc ope _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.Manageme nt.ManagementSc ope 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 ConnectionStrin g = ConnectionStrin g = "Database=toto; Data
Source=localhos t;User Id=root;Passwor d=XXX";
54 MySqlConnection _id_con_mysql = new MySqlConnection (ConnectionStri ng);
55 _id_con_mysql.O pen();
56 this.id_con_mys ql = _id_con_mysql;
57 }
58
59 void mysql_query(str ing sql)
60 {
61 //this.connect_my sql();
62 MySqlCommand query_ajoute_do ssier = new MySqlCommand(sq l,
this.id_con_mys ql);
63 query_ajoute_do ssier.ExecuteNo nQuery();
64 }
65
66 void mysql_deconnect ()
67 {
68 this.id_con_mys ql.Close();
69 }
70
71 public string trouve_nom_pc()
72 {
73 ConnectionOptio ns oConn = new ConnectionOptio ns();
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.Manageme nt.ManagementSc ope oMs = new
System.Manageme nt.ManagementSc ope("\\\\Machin eX", oConn);
78 //System.Manageme nt.ManagementSc ope oMs = new
System.Manageme nt.ManagementSc ope("\\\\Machin eX");
79
80 //j appel la liste des dossiers d un repertoire de base donnee
81 System.Manageme nt.ObjectQuery oQueryPc = new
System.Manageme nt.ObjectQuery( "SELECT Name from Win32_ComputerS ystem");
82
83 //j execute la requete
84 ManagementObjec tSearcher oSearcherPc = new
ManagementObjec tSearcher(this. connect_wmi(),o QueryPc);
85
86 //je recupere le nom de l ordinateur avec la methode Get
87 ManagementObjec tCollection oReturnCollecti onPc = oSearcherPc.Get ();
88
89 foreach(Managem entObject oReturnPc in oReturnCollecti onPc)
90 {
91 _nom_pc = oReturnPc["name"].ToString();
92 }
93 return _nom_pc;
94 }
95
96 public System.Manageme nt.ManagementSc ope connect_wmi()
97 {
98 // fonction retournant l identifiant de connexion a WMI
99 this._oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX");
100 return this.oMs;
101 }
102
103 public static void Main(string[] args)
104 {
105 string nom_rep_mysql, sql_ajoute_doss ier, sql_ajoute_acce s, sql_pc;
106
107 wmi_scan_dossie r un_scan = new wmi_scan_dossie r();
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 ConnectionOptio ns oConn = new ConnectionOptio ns();
114
115 //j appel la liste des dossiers d un repertoire de base donnee
116 System.Manageme nt.ObjectQuery oQueryPc = new
System.Manageme nt.ObjectQuery( "SELECT Name from Win32_ComputerS ystem");
117
118 //j execute la requete
119 ManagementObjec tSearcher oSearcherPc = new
ManagementObjec tSearcher(un_sc an.connect_wmi( ),oQueryPc);
120
121 //je recupere le nom de l ordinateur avec la methode Get
122 ManagementObjec tCollection oReturnCollecti onPc = oSearcherPc.Get ();
123
124 int j = args.Length;
125
126 if(j == 0)
127 {
128 Console.WriteLi ne ("Saisissez un paramètre pour utiliser le logiciel");
129 Console.WriteLi ne ("Exemple de synthaxe : test_ok.exe \"c:\\Apache \"
\"C:\\Docume nts and Settings\"");
130 Console.WriteLi ne ("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.WriteLi ne ("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.Rep lace ("\\","\\\\" );
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.Manageme nt.WqlObjectQue ry oQuery = new
System.Manageme nt.WqlObjectQue ry(wql_dossier) ;
143
144 //j execute la requete
145 ManagementObjec tSearcher oSearcher = new
ManagementObjec tSearcher(un_sc an.connect_wmi( ),oQuery);
146
147 oSearcher.Optio ns.ReturnImmedi ately = true;
148 oSearcher.Optio ns.Rewindable = false;
149 oSearcher.Optio ns.DirectRead = true;
150
151 //je recupere le resultat avec la methode Get
152 ManagementObjec tCollection oReturnCollecti on = oSearcher.Get() ;
153
154 un_scan.connect _mysql();
155
156 //loop through found drives and write out info
157 foreach( ManagementObjec t oReturn in oReturnCollecti on )
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_doss ier = "REPLACE INTO repertoire VALUES ('" + nom_rep_mysql
+ "')";
166 un_scan.mysql_q uery(sql_ajoute _dossier);
167
168 ManagementObjec t LogicalFileSecu ritySetting = new ManagementObjec t( new
ManagementPath( "ROOT\\CIMV2:Wi n32_LogicalFile SecuritySetting .Path='" +
nom_rep + "'"));
169 ManagementBaseO bject inParams = null;
170 bool EnablePrivilege s =
LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges;
171 LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges = true;
172 ManagementBaseO bject outParams =
LogicalFileSecu ritySetting.Inv okeMethod("GetS ecurityDescript or", inParams,
null);
173 ManagementBaseO bject Descriptor =
((ManagementBas eObject)(outPar ams.Properties["Descriptor "].Value));
174 LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges =
EnablePrivilege s;
175
176 ManagementBaseO bject[] DACLObject = ( ( ManagementBaseO bject[] )(
Descriptor.Prop erties["DACL"].Value ) );
177
178 System.Collecti ons.Stack stk = new System.Collecti ons.Stack();
179
180 for(int i = 0; i < DACLObject.Leng th; i++)
181 {
182 ManagementBaseO bject 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_acce s = "REPLACE INTO acces VALUES ('" + (nom_rep_mysql + "',
'" + ( (ManagementBase Object) DACLObject[
i ].Properties["Trustee"].Value).Propert ies["Name"].Value + "', '" +
DACLObject[i].Properties["AccessMask "].Value + "', '" +
un_scan.trouve_ nom_pc() + "', CURRENT_TIMESTA MP())"); // j ecrit le nom du
repertoire courant, le login et l'AccessMask dans le fichier
188 un_scan.mysql_q uery(sql_ajoute _acces);
189
190 etre_doublon = false;
191
192 foreach (string login in verif_login)
193 {
194 if (login == (string)(un_sca n.trouve_nom_pc () + "|" +
((ManagementBas eObject) DACLObject[
i ].Properties["Trustee"].Value).Propert ies["Name"].Value) + "|" +
un_scan.trouve_ nom_pc())
195 {
196 etre_doublon = true;
197 }
198 }
199
200 verif_login.Add (un_scan.trouve _nom_pc() + "|" + ((ManagementBas eObject)
DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value);
201
202 if (!etre_doublon)
203 {
204 sql_pc = "REPLACE pc VALUES ('" + un_scan.trouve_ nom_pc() + "', '" +
(( (ManagementBase Object) DACLObject[
i ].Properties["Trustee"].Value).Propert ies["Name"].Value + "')"); // j
ajoute le nom de l utilisateur dans la table utilisateur
205 un_scan.mysql_q uery(sql_pc);
206 }
207 }
208 }
209 }
210 }
211 un_scan.mysql_d econnect();
212 Console.WriteLi ne ("Analyse des dossiers terminées");
213 }
214 }
215 }
216 } 11 7079
why are you using WMI? That's got to be the slowest way to get a directory
listing.
For the current machine, use the DirectoryInfo class with the name of the
local directory you need to scan.
If you have network access to a machine, you can use the same method
remotely as you can locally. Just use \\servername\c$ \directory as the
format for the string to pass to DirectoryInfo.
--- Nick
"nico" <te*@hotmail.co m> wrote in message
news:ue******** ******@TK2MSFTN GP09.phx.gbl... 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.Sql Client; 10 using System.Data.Com mon; 11 using System.Manageme nt; 12 using System.Collecti ons; 13 using ByteFX; 14 using ByteFX.Data.MyS qlClient; 15 using System.Diagnost ics; 16 using System.Componen tModel; 17 18 namespace System.Manageme nt 19 20 { 21 class wmi_scan_dossie r 22 { 23 private string _nom_pc; 24 private MySqlConnection _id_con_mysql; 25 private System.Manageme nt.ManagementSc ope _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.Manageme nt.ManagementSc ope 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 ConnectionStrin g = ConnectionStrin g = "Database=toto; Data Source=localhos t;User Id=root;Passwor d=XXX"; 54 MySqlConnection _id_con_mysql = new MySqlConnection (ConnectionStri ng); 55 _id_con_mysql.O pen(); 56 this.id_con_mys ql = _id_con_mysql; 57 } 58 59 void mysql_query(str ing sql) 60 { 61 //this.connect_my sql(); 62 MySqlCommand query_ajoute_do ssier = new MySqlCommand(sq l, this.id_con_mys ql); 63 query_ajoute_do ssier.ExecuteNo nQuery(); 64 } 65 66 void mysql_deconnect () 67 { 68 this.id_con_mys ql.Close(); 69 } 70 71 public string trouve_nom_pc() 72 { 73 ConnectionOptio ns oConn = new ConnectionOptio ns(); 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.Manageme nt.ManagementSc ope oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX", oConn); 78 //System.Manageme nt.ManagementSc ope oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX"); 79 80 //j appel la liste des dossiers d un repertoire de base donnee 81 System.Manageme nt.ObjectQuery oQueryPc = new System.Manageme nt.ObjectQuery( "SELECT Name from Win32_ComputerS ystem"); 82 83 //j execute la requete 84 ManagementObjec tSearcher oSearcherPc = new ManagementObjec tSearcher(this. connect_wmi(),o QueryPc); 85 86 //je recupere le nom de l ordinateur avec la methode Get 87 ManagementObjec tCollection oReturnCollecti onPc = oSearcherPc.Get (); 88 89 foreach(Managem entObject oReturnPc in oReturnCollecti onPc) 90 { 91 _nom_pc = oReturnPc["name"].ToString(); 92 } 93 return _nom_pc; 94 } 95 96 public System.Manageme nt.ManagementSc ope connect_wmi() 97 { 98 // fonction retournant l identifiant de connexion a WMI 99 this._oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX"); 100 return this.oMs; 101 } 102 103 public static void Main(string[] args) 104 { 105 string nom_rep_mysql, sql_ajoute_doss ier, sql_ajoute_acce s, sql_pc; 106 107 wmi_scan_dossie r un_scan = new wmi_scan_dossie r(); 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 ConnectionOptio ns oConn = new ConnectionOptio ns(); 114 115 //j appel la liste des dossiers d un repertoire de base donnee 116 System.Manageme nt.ObjectQuery oQueryPc = new System.Manageme nt.ObjectQuery( "SELECT Name from Win32_ComputerS ystem"); 117 118 //j execute la requete 119 ManagementObjec tSearcher oSearcherPc = new ManagementObjec tSearcher(un_sc an.connect_wmi( ),oQueryPc); 120 121 //je recupere le nom de l ordinateur avec la methode Get 122 ManagementObjec tCollection oReturnCollecti onPc = oSearcherPc.Get (); 123 124 int j = args.Length; 125 126 if(j == 0) 127 { 128 Console.WriteLi ne ("Saisissez un paramètre pour utiliser le
logiciel"); 129 Console.WriteLi ne ("Exemple de synthaxe : test_ok.exe \"c:\\Apache \" \"C:\\Docume nts and Settings\""); 130 Console.WriteLi ne ("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.WriteLi ne ("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.Rep lace ("\\","\\\\" ); 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.Manageme nt.WqlObjectQue ry oQuery = new System.Manageme nt.WqlObjectQue ry(wql_dossier) ; 143 144 //j execute la requete 145 ManagementObjec tSearcher oSearcher = new ManagementObjec tSearcher(un_sc an.connect_wmi( ),oQuery); 146 147 oSearcher.Optio ns.ReturnImmedi ately = true; 148 oSearcher.Optio ns.Rewindable = false; 149 oSearcher.Optio ns.DirectRead = true; 150 151 //je recupere le resultat avec la methode Get 152 ManagementObjec tCollection oReturnCollecti on = oSearcher.Get() ; 153 154 un_scan.connect _mysql(); 155 156 //loop through found drives and write out info 157 foreach( ManagementObjec t oReturn in oReturnCollecti on ) 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_doss ier = "REPLACE INTO repertoire VALUES ('" +
nom_rep_mysql + "')"; 166 un_scan.mysql_q uery(sql_ajoute _dossier); 167 168 ManagementObjec t LogicalFileSecu ritySetting = new ManagementObjec t(
new ManagementPath( "ROOT\\CIMV2:Wi n32_LogicalFile SecuritySetting .Path='" + nom_rep + "'")); 169 ManagementBaseO bject inParams = null; 170 bool EnablePrivilege s = LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges; 171 LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges = true; 172 ManagementBaseO bject outParams = LogicalFileSecu ritySetting.Inv okeMethod("GetS ecurityDescript or", inParams, null); 173 ManagementBaseO bject Descriptor = ((ManagementBas eObject)(outPar ams.Properties["Descriptor "].Value)); 174 LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges = EnablePrivilege s; 175 176 ManagementBaseO bject[] DACLObject = ( ( ManagementBaseO bject[] )( Descriptor.Prop erties["DACL"].Value ) ); 177 178 System.Collecti ons.Stack stk = new System.Collecti ons.Stack(); 179 180 for(int i = 0; i < DACLObject.Leng th; i++) 181 { 182 ManagementBaseO bject 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_acce s = "REPLACE INTO acces VALUES ('" + (nom_rep_mysql +
"', '" + ( (ManagementBase Object) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value + "', '" + DACLObject[i].Properties["AccessMask "].Value + "', '" + un_scan.trouve_ nom_pc() + "', CURRENT_TIMESTA MP())"); // j ecrit le nom du repertoire courant, le login et l'AccessMask dans le fichier 188 un_scan.mysql_q uery(sql_ajoute _acces); 189 190 etre_doublon = false; 191 192 foreach (string login in verif_login) 193 { 194 if (login == (string)(un_sca n.trouve_nom_pc () + "|" + ((ManagementBas eObject) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value) + "|" + un_scan.trouve_ nom_pc()) 195 { 196 etre_doublon = true; 197 } 198 } 199 200 verif_login.Add (un_scan.trouve _nom_pc() + "|" +
((ManagementBas eObject) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value); 201 202 if (!etre_doublon) 203 { 204 sql_pc = "REPLACE pc VALUES ('" + un_scan.trouve_ nom_pc() + "', '" + (( (ManagementBase Object) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value + "')"); // j ajoute le nom de l utilisateur dans la table utilisateur 205 un_scan.mysql_q uery(sql_pc); 206 } 207 } 208 } 209 } 210 } 211 un_scan.mysql_d econnect(); 212 Console.WriteLi ne ("Analyse des dossiers terminées"); 213 } 214 } 215 } 216 }
"Nick Malik" <ni*******@hotm ail.nospam.com> a écrit dans le message de
news:WNUHc.6248 0$XM6.61369@att bi_s53... why are you using WMI? That's got to be the slowest way to get a
directory listing. For the current machine, use the DirectoryInfo class with the name of the local directory you need to scan.
If you have network access to a machine, you can use the same method remotely as you can locally. Just use \\servername\c$ \directory as the format for the string to pass to DirectoryInfo.
--- Nick
Ok thanks but if I scan all directory recursively, I will have too connect
to WMI X time where X is the number of directory that I need to scan.
By using a WQL QUERY I need to connect only one time to WMI and brownse the
array of object.
I perhaps was not clear.
The DirectoryInfo class does not use WMI. It is fast. I can scan thousands
of files and directories in a few seconds.
I will repeat my first question, in a different form:
I do not understand what business reason you have for using WMI?
Please explain so I can help you find a better solution.
--- Nick
"nico" <te*@hotmail.co m> wrote in message
news:On******** ******@TK2MSFTN GP12.phx.gbl... "Nick Malik" <ni*******@hotm ail.nospam.com> a écrit dans le message de news:WNUHc.6248 0$XM6.61369@att bi_s53... why are you using WMI? That's got to be the slowest way to get a directory listing. For the current machine, use the DirectoryInfo class with the name of
the local directory you need to scan.
If you have network access to a machine, you can use the same method remotely as you can locally. Just use \\servername\c$ \directory as the format for the string to pass to DirectoryInfo.
--- Nick
Ok thanks but if I scan all directory recursively, I will have too connect to WMI X time where X is the number of directory that I need to scan.
By using a WQL QUERY I need to connect only one time to WMI and brownse
the array of object.
"Nick Malik" <ni*******@hotm ail.nospam.com> a écrit dans le message de
news:G06Ic.5690 3$IQ4.15869@att bi_s02... I perhaps was not clear.
The DirectoryInfo class does not use WMI. It is fast. I can scan
thousands of files and directories in a few seconds.
I will repeat my first question, in a different form: I do not understand what business reason you have for using WMI? Please explain so I can help you find a better solution.
--- Nick
I need WMI because I need to retrieve all permission for all local user for
all directory on my computer and write the AccessMask and Username and
Directory into a MySQL database.
> The DirectoryInfo class does not use WMI. It is fast. I can scan thousands of files and directories in a few seconds.
actually in my experience it is not fast.
my task was to write code to search for files on disk - and email the
contents using SMTP - I wrote this first in Perl (using fork to
'multithread' the emailing bit).
I then re-wrote in C# because I thought the multithreading code but
would be cleaner using threads than fork - it was, but I found the
that searching for the files on disk was *much* slower in C#.
Actually I used the Directory class instead of DirectoryInfo - which
should be the faster choice in my scenario.
anyone know the *fastest* way to do a recursive file search in C# ?
Oliver.
This is very useful information Oliver. I thank you.
Compared to WMI, Directory and DirectoryInfo are both about 100 times
faster.
WMI is the slowest possible method for gaining access to this information,
and that is the course of this thread.
--- N
"Oliver" <sp************ *@yahoo.com> wrote in message
news:58******** *************** ***@posting.goo gle.com... The DirectoryInfo class does not use WMI. It is fast. I can scan
thousands of files and directories in a few seconds.
actually in my experience it is not fast.
my task was to write code to search for files on disk - and email the contents using SMTP - I wrote this first in Perl (using fork to 'multithread' the emailing bit).
I then re-wrote in C# because I thought the multithreading code but would be cleaner using threads than fork - it was, but I found the that searching for the files on disk was *much* slower in C#.
Actually I used the Directory class instead of DirectoryInfo - which should be the faster choice in my scenario.
anyone know the *fastest* way to do a recursive file search in C# ? Oliver.
> > I do not understand what business reason you have for using WMI? Please explain so I can help you find a better solution.
--- Nick I need WMI because I need to retrieve all permission for all local user
for all directory on my computer and write the AccessMask and Username and Directory into a MySQL database.
No, you do not need WMI to do that.
There are at least three and perhaps four ways to get the information that
you want. Each way has its advantages and disadvantages. The method you
chose, WMI, has the disadvantage of being very very slow.
I'm trying to get you to consider a different way.
(Analogy: You are driving on a crowded city street, where there is a major
highway one mile a way that will take you where you want to go... I'm trying
to get you to look for the signs to the highway).
See DirectoryInfo at: http://msdn.microsoft.com/library/de...mberstopic.asp
See Directory at: http://msdn.microsoft.com/library/de...classtopic.asp
To get the ACL of a directory or file, use the following object: http://www.codeproject.com/dotnet/ntsecuritynet.asp
Hope this helps,
--- N
Your query is wrong, you need to include the drive as search criteria,
otherwise you will scan ALL logical drives attached to the system including
the mapped network shares (No wonder it is slow :-) this can take hours when
a lot of drives are mapped).
Change your query into:
Select Name from Win32_Directory WHERE drive='c:' and Name LIKE '.....'
Willy.
"nico" <te*@hotmail.co m> wrote in message
news:ue******** ******@TK2MSFTN GP09.phx.gbl... 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.Sql Client; 10 using System.Data.Com mon; 11 using System.Manageme nt; 12 using System.Collecti ons; 13 using ByteFX; 14 using ByteFX.Data.MyS qlClient; 15 using System.Diagnost ics; 16 using System.Componen tModel; 17 18 namespace System.Manageme nt 19 20 { 21 class wmi_scan_dossie r 22 { 23 private string _nom_pc; 24 private MySqlConnection _id_con_mysql; 25 private System.Manageme nt.ManagementSc ope _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.Manageme nt.ManagementSc ope 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 ConnectionStrin g = ConnectionStrin g = "Database=toto; Data Source=localhos t;User Id=root;Passwor d=XXX"; 54 MySqlConnection _id_con_mysql = new MySqlConnection (ConnectionStri ng); 55 _id_con_mysql.O pen(); 56 this.id_con_mys ql = _id_con_mysql; 57 } 58 59 void mysql_query(str ing sql) 60 { 61 //this.connect_my sql(); 62 MySqlCommand query_ajoute_do ssier = new MySqlCommand(sq l, this.id_con_mys ql); 63 query_ajoute_do ssier.ExecuteNo nQuery(); 64 } 65 66 void mysql_deconnect () 67 { 68 this.id_con_mys ql.Close(); 69 } 70 71 public string trouve_nom_pc() 72 { 73 ConnectionOptio ns oConn = new ConnectionOptio ns(); 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.Manageme nt.ManagementSc ope oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX", oConn); 78 //System.Manageme nt.ManagementSc ope oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX"); 79 80 //j appel la liste des dossiers d un repertoire de base donnee 81 System.Manageme nt.ObjectQuery oQueryPc = new System.Manageme nt.ObjectQuery( "SELECT Name from Win32_ComputerS ystem"); 82 83 //j execute la requete 84 ManagementObjec tSearcher oSearcherPc = new ManagementObjec tSearcher(this. connect_wmi(),o QueryPc); 85 86 //je recupere le nom de l ordinateur avec la methode Get 87 ManagementObjec tCollection oReturnCollecti onPc = oSearcherPc.Get (); 88 89 foreach(Managem entObject oReturnPc in oReturnCollecti onPc) 90 { 91 _nom_pc = oReturnPc["name"].ToString(); 92 } 93 return _nom_pc; 94 } 95 96 public System.Manageme nt.ManagementSc ope connect_wmi() 97 { 98 // fonction retournant l identifiant de connexion a WMI 99 this._oMs = new System.Manageme nt.ManagementSc ope("\\\\Machin eX"); 100 return this.oMs; 101 } 102 103 public static void Main(string[] args) 104 { 105 string nom_rep_mysql, sql_ajoute_doss ier, sql_ajoute_acce s, sql_pc; 106 107 wmi_scan_dossie r un_scan = new wmi_scan_dossie r(); 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 ConnectionOptio ns oConn = new ConnectionOptio ns(); 114 115 //j appel la liste des dossiers d un repertoire de base donnee 116 System.Manageme nt.ObjectQuery oQueryPc = new System.Manageme nt.ObjectQuery( "SELECT Name from Win32_ComputerS ystem"); 117 118 //j execute la requete 119 ManagementObjec tSearcher oSearcherPc = new ManagementObjec tSearcher(un_sc an.connect_wmi( ),oQueryPc); 120 121 //je recupere le nom de l ordinateur avec la methode Get 122 ManagementObjec tCollection oReturnCollecti onPc = oSearcherPc.Get (); 123 124 int j = args.Length; 125 126 if(j == 0) 127 { 128 Console.WriteLi ne ("Saisissez un paramètre pour utiliser le logiciel"); 129 Console.WriteLi ne ("Exemple de synthaxe : test_ok.exe \"c:\\Apache \" \"C:\\Docume nts and Settings\""); 130 Console.WriteLi ne ("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.WriteLi ne ("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.Rep lace ("\\","\\\\" ); 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.Manageme nt.WqlObjectQue ry oQuery = new System.Manageme nt.WqlObjectQue ry(wql_dossier) ; 143 144 //j execute la requete 145 ManagementObjec tSearcher oSearcher = new ManagementObjec tSearcher(un_sc an.connect_wmi( ),oQuery); 146 147 oSearcher.Optio ns.ReturnImmedi ately = true; 148 oSearcher.Optio ns.Rewindable = false; 149 oSearcher.Optio ns.DirectRead = true; 150 151 //je recupere le resultat avec la methode Get 152 ManagementObjec tCollection oReturnCollecti on = oSearcher.Get() ; 153 154 un_scan.connect _mysql(); 155 156 //loop through found drives and write out info 157 foreach( ManagementObjec t oReturn in oReturnCollecti on ) 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_doss ier = "REPLACE INTO repertoire VALUES ('" + nom_rep_mysql + "')"; 166 un_scan.mysql_q uery(sql_ajoute _dossier); 167 168 ManagementObjec t LogicalFileSecu ritySetting = new ManagementObjec t( new ManagementPath( "ROOT\\CIMV2:Wi n32_LogicalFile SecuritySetting .Path='" + nom_rep + "'")); 169 ManagementBaseO bject inParams = null; 170 bool EnablePrivilege s = LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges; 171 LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges = true; 172 ManagementBaseO bject outParams = LogicalFileSecu ritySetting.Inv okeMethod("GetS ecurityDescript or", inParams, null); 173 ManagementBaseO bject Descriptor = ((ManagementBas eObject)(outPar ams.Properties["Descriptor "].Value)); 174 LogicalFileSecu ritySetting.Sco pe.Options.Enab lePrivileges = EnablePrivilege s; 175 176 ManagementBaseO bject[] DACLObject = ( ( ManagementBaseO bject[] )( Descriptor.Prop erties["DACL"].Value ) ); 177 178 System.Collecti ons.Stack stk = new System.Collecti ons.Stack(); 179 180 for(int i = 0; i < DACLObject.Leng th; i++) 181 { 182 ManagementBaseO bject 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_acce s = "REPLACE INTO acces VALUES ('" + (nom_rep_mysql + "', '" + ( (ManagementBase Object) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value + "', '" + DACLObject[i].Properties["AccessMask "].Value + "', '" + un_scan.trouve_ nom_pc() + "', CURRENT_TIMESTA MP())"); // j ecrit le nom du repertoire courant, le login et l'AccessMask dans le fichier 188 un_scan.mysql_q uery(sql_ajoute _acces); 189 190 etre_doublon = false; 191 192 foreach (string login in verif_login) 193 { 194 if (login == (string)(un_sca n.trouve_nom_pc () + "|" + ((ManagementBas eObject) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value) + "|" + un_scan.trouve_ nom_pc()) 195 { 196 etre_doublon = true; 197 } 198 } 199 200 verif_login.Add (un_scan.trouve _nom_pc() + "|" + ((ManagementBas eObject) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value); 201 202 if (!etre_doublon) 203 { 204 sql_pc = "REPLACE pc VALUES ('" + un_scan.trouve_ nom_pc() + "', '" + (( (ManagementBase Object) DACLObject[ i ].Properties["Trustee"].Value).Propert ies["Name"].Value + "')"); // j ajoute le nom de l utilisateur dans la table utilisateur 205 un_scan.mysql_q uery(sql_pc); 206 } 207 } 208 } 209 } 210 } 211 un_scan.mysql_d econnect(); 212 Console.WriteLi ne ("Analyse des dossiers terminées"); 213 } 214 } 215 } 216 }
"Nick Malik" <ni*******@hotm ail.nospam.com> wrote in message
news:C0xIc.6247 5$%_6.4386@attb i_s01... This is very useful information Oliver. I thank you.
Compared to WMI, Directory and DirectoryInfo are both about 100 times faster.
WMI is the slowest possible method for gaining access to this information, and that is the course of this thread.
--- N
Hmmm.... Why using WMI?
Simply because this is the most simple way to do without resorting to
unmanaged code.
DirectoryInfo has not the features offered by the WIn32_Directory (tough not
used here), nor give it back the NTFS security info.
Sure WMI WIn32_Directory is slower than DirectoryInfo but not 100 times as
you incorrectly state, but only 10 times.
F.I scanning c:\program files (1598 subdirs) on a fast 7200RPM local drive
takes:
0.22 sec. using DirectoryInfo
1.12 sec. using WMI
This is only 5 times slower.
However over a network (and that's exactly what OP is doing)
6.0 sec. using DirectoryInfo
0.72 sec the second run (effect of server side caching)
7.2 sec. using WMI
2.2 sec the second run (effect of server side caching)
Here it's only 3 times slower.
Now it's up to you to decide it's fast enough, but there's more, the caller
needs access permission to whole directory tree using DirectoryInfo using an
UNC path, so he needs to run with admin privileges on the remote server,
this while WMI only needs to impersonate the caller's credentials supplied
in code.
And last but not least, OP needs NTFS security info (but hell I don't know
why he ever needs to store this in a DB) from the scanned dirs, something
that can easily be done (but you should never do whatever technology you
use) using ... right WMI.
And this http://www.codeproject.com/dotnet/ntsecuritynet.asp can only be
used for local drives.
Willy. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: anders |
last post by:
Hi!
Im trying to add a A record to a domain name in MS DNS with C#, it's done
from a webpage with this code:
ManagementClass rr = new ManagementClass(@"root\MicrosoftDNS",
"MicrosoftDNS_ResourceRecord",
new ObjectGetOptions(null,new TimeSpan(100), true));
string _ResellerDomainName = "mydomain.net.";
object rrText = "web IN A 123.123.123.123";
|
by: Andrew Gomes |
last post by:
Does anyone know if there is an alternative to reading Exchange 2003 public
folders with WMI?
I am using WMI in VB.NET to read a list of public folders on an Exchange
2003 server. My problem is that it is INCREDIBLY slow!!! It seems to reads
in chunks from the server with a long delay between "chunks." The other
problem is that the server has over 60,000 public folders! (So you can
imagine how long this takes!)
Is there an...
|
by: Bob Hollness |
last post by:
Hi all. I am using WMI to read some printing information. It runs soooo
sssslllooooowwww for me though when retrieving information. My computer is
pretty quick so I don't think it is the PC. Is this normal?
--
I'll have a B please Bob.
|
by: rbt |
last post by:
Here's a quick and dirty version of winver.exe written in Python:
http://filebox.vt.edu/users/rtilley/public/winver/winver.html
It uses wmi to get OS information from Windows... it works well, but
it's slow... too slow. Is there any way to speed up wmi?
In the past, I used the platform and sys modules to do some of what
winver.exe does and they were rather fast. However, since switching to
wmi (for a more accurate representation)...
|
by: Salvador |
last post by:
Hi,
I am using WMI to gather information about different computers (using win2K
and win 2K3), checking common classes and also WMI load balance. My
application runs every 1 minute and reports the status of the machines.
Upon we follow the .NET object lifetime recommendations the application is
constantly consuming more memory! The problem is on the
ManagementObjectSearch, upon we Dispose the object it seems that is not
releasing the...
| |
by: deppy_3 |
last post by:
Hi.I am started learning Programm language C before some time.I am
trying to make a programm about a very simple "sell shop".This programm
hasn't got any compile problem but when i run it i face some other
ploblems which i can not correct.I would appreciated if someone take a
look at my programm so as to help me.I tried many times to find out
where my mistakes are but i didn't manage something.
I have made some comments due to the programm...
|
by: Babillon |
last post by:
Hello all. I'm writting a little application to help me expand my knowledge
in a few different areas. The app is, as you might of guessed from the
subject, a system metrics display using WMI. For now I'm doing it with
Windows Forms, but later on I will be changing it to use DirectX's Overlays.
The question I have right now is how to get the information gathered from
WMI to easily, and efficiantly, update what is shown. I've tried using...
|
by: ttan |
last post by:
Hi,
I have 7 computers and 5 controllers(no OS) connected to Domain controller.
when I used WMI to query for registry, it take a long time (about 60
minutes) to return the result. if it a controller then there is no WMI and
return a NULL ManagementClass. Does anyone know there is another way to make
it run faster?
protected static ManagementClass ConnectToConfigProv(string host, string
managementClass)
|
by: Viliam |
last post by:
I have written a decoupled WMI provider in C# using COM/Interop interface.
I've converted WbemClient,WbemProviders and WbemUtilities TLBs to assemblies
and i have a provider class that implements IWbemProviderInit and
IWbemProviderServices interface.
The problem is that when I call Get or Put WMI methods, the call takes about
2 minutes. Debugging the provider showed that GetObjectAsync method in
provider is called immediately and it...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |