473,809 Members | 2,731 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

[C# and WMI] : Programm run to slow

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 }
Nov 16 '05 #1
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 }

Nov 16 '05 #2

"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.
Nov 16 '05 #3
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.

Nov 16 '05 #4

"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.
Nov 16 '05 #5
> 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.
Nov 16 '05 #6
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.

Nov 16 '05 #7
> > 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
Nov 16 '05 #8

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 }

Nov 16 '05 #9

"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.
Nov 16 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
9701
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";
1
3715
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...
4
1726
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.
0
1092
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)...
7
6938
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...
83
7883
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...
3
3977
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...
2
5592
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)
0
1570
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...
0
9721
marktang
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...
0
9601
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,...
0
10635
Oralloy
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...
0
10115
tracyyun
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...
0
9198
agi2029
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...
1
7653
isladogs
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...
0
5550
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...
2
3861
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3013
bsmnconsultancy
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.