[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 'Option Explicit 2 3 ' Client wpkg - Etablit la connexion au serveur en attendant que les services réseau aient démarrés 4 ' - Lance l'exécution de wpkg-se3.js 5 ' - Gère les remontées des rapports 6 ' 7 ' ## $Id: wpkg-client.vbs.orig 3585 2009-03-08 15:12:47Z jlebail $ ## 8 ' 9 ' Syntaxe : cscript wpkg-client.vbs[ /noTempo][ /cpuLoad xx] 10 ' /noTempo : pour avoir des tempo réduites (utile pour un lancement en ligne de commande sans avoir à attendre...) 11 ' /cpuLoad xx : Attend (charge cpu en %) < xx avant de démarrer (10% par defaut). 12 ' /Tempo nn : Attend nn sec avant de démarrer (30 par defaut). 13 ' /debug : Affiche en temps réel les msg lors de l'exécution de wpkg-se3.js. 14 15 On Error Resume Next 16 17 Const ForReading=1, ForWriting=2, ForAppending=8 18 19 ' ---------------------------------------------------------------------------------- 20 ' 21 ' Vous pouvez personnaliser ici le paramétrage du client wpkg. 22 ' 23 Dim LogMode : LogMode = 2 ' Type de log. 0=Pas de log, 2=Log dernière execution, 8=Log avec conservation de l'historique 24 Dim secBeforeStart : secBeforeStart = 30 ' Nombre de secondes à attendre avant démarrer 25 Dim secAfterRun : secAfterRun = 5 ' Nombre de secondes à attendre pour RemoveNetworkDrive 26 Dim maxCpuLoad : maxCpuLoad = 10 ' % Charge CPU maxi autorisée pour démarrer 27 Dim ServeurWpkg : ServeurWpkg = "$SE3" ' Serveur utilisé par les clients wpkg 28 Dim testCPU : testCPU = false ' test CPU désactivé par défaut à cause des soucis de détection sur les nouveaux CPU : 06/2013 29 ' Par défaut, le serveur se3 est utilisé pour déployer les applications. 30 ' Vous pouvez cependant préférer utiliser un autre serveur (par ex. si se3 est très chargé). 31 ' Pour utiliser le serveur 'NomDuServeur' à la place de 'se3', il faut : 32 ' - créer un partage nommé 'install' sur le serveur 'NomDuServeur' 33 ' - créer sur ce serveur un utilisateur 'adminse3' ayant le mot de passe indiqué dans http://se3:909/setup (password_admin_local) 34 ' - permettre à adminse3 d'écrire dans \\NomDuServeur\install\wpkg\rapports 35 ' (un accès en lecture suffit pour les autres dossiers et fichiers de ce partage) 36 ' - définir ci-dessus ServeurWpkg = "NomDuServeur" et enregistrer ce fichier (\\se3\install\wpkg\wpkg-client.vbs) , 37 ' - recopier le contenu de \\se3\install dans \\NomDuServeur\install 38 ' 39 ' De plus, pour que la gestion de la configuration des applis continue à se faire par l'interface web de se3, 40 ' Définir sur MonServeur un compte WWWSE3 mot de passe PassWWWSE3 ayant un acces rw sur le partage \\NomDuServeur\install 41 ' puis sur le se3 : 42 ' cp -p /var/se3/unattended/install /var/se3/unattended/install.bak 43 ' rm -R /var/se3/unattended/install/* 44 ' mount -t smbfs -o username=WWWSE3,password=PassWWWSE3 //NomDuServeur/install /var/se3/unattended/install 45 ' ou ( USER=NomDuServeur/WWWSE3%PassWWWSE3 46 ' smbmount //NomDuServeur/install /var/se3/unattended/install ) 47 ' Rmq. Le nom d'utilisateur WWWSE3 et le mot de passe PassWWWSE3 doivent bien sûr être adapté selon votre imagination... 48 ' 49 ' Au prochain démarrage des postes, le client wpkg sera mis à jour avec son nouveau paramétrage. 50 ' 51 '------------------------------------------------------------------------------------ 52 53 Dim printOutput : printOutput = True 54 Dim watchDog : watchDog = 18000 ' Temps maxi en secondes pour l'exécution de wpkg-se3.js 55 Dim CodeSortie : CodeSortie = 0 56 57 Dim UNC : UNC = "\\" & ServeurWpkg & "\install" 'Chemin du partage install 58 Dim Z : Z="z:" 'unité à mapper 59 Dim RunningStatus 60 Dim oNet, User, ComputerName, UserDomain 61 Dim oShell, WinDir, ComSpec 62 Dim fso, f, tf, fLog, iLog : iLog=0 63 Set fLog = Nothing 64 Dim i 65 Dim MAC, addmac, mac2 66 Dim TypeWin 67 68 Dim objArgs : Set objArgs = WScript.Arguments 69 Dim arg 70 Dim Tempo : Tempo = True 71 Dim debugVbs : debugVbs = False 72 Dim FinExec 73 74 Set oShell = WScript.CreateObject("WScript.Shell") 75 Set fso = CreateObject("Scripting.FileSystemObject") 76 If fso.FileExists(oShell.ExpandEnvironmentStrings("%SystemDrive%") & "\netinst\wpkg-notempo.txt") Then 77 Tempo = False 78 End If 79 80 WinDir = oShell.ExpandEnvironmentStrings("%WinDir%") 81 ComSpec = oShell.ExpandEnvironmentStrings("%ComSpec%") 82 83 Dim ageLastLog, ageLastTxt 84 dateLastLog 85 86 If Not fso.FolderExists(oShell.ExpandEnvironmentStrings("%SystemDrive%") & "\netinst\logs") Then 87 If Not fso.FolderExists(oShell.ExpandEnvironmentStrings("%SystemDrive%") & "\netinst") Then 88 fso.CreateFolder(oShell.ExpandEnvironmentStrings("%SystemDrive%") & "\netinst") 89 End If 90 fso.CreateFolder(oShell.ExpandEnvironmentStrings("%SystemDrive%") & "\netinst\logs") 91 End If 92 93 ' Conversion OEM -> ANSI 94 Dim oem 95 InitOEM 96 97 Dim debug : debug=false ' Permet d'avoir des logs plus détaillés. 98 Dim logdebug : logdebug=false ' Pour avoir des logs en temps réel sur le serveur. 99 Dim force : force=false ' Pour tester la présence ou l'absence effective de chaque appli sur le poste. 100 Dim forceinstall : forceinstall=false ' Pour installer ou désinstaller les applications même si les tests 'check' sont vérifiés. 101 Dim nonotify : nonotify=false ' Pour ne pas avertir l'utilisateur logué des opérations de wpkg (si false, le service messenger doit être activé). 102 Dim norunningstate : norunningstate=false ' Pour que wpkg n'écrive pas running : norunningstate=false ' Pour que wpkg n'écrive pas running=true dans la base de registre lorsqu'il s'exécute. 103 Dim dryrun : dryrun=false ' Pour que wpkg simule une exécution mais n'installe ou ne désinstalle rien. 104 Dim nowpkg : nowpkg=false ' Pour ne pas exécuter wpkg sur le poste. 105 Dim noforcedremove : noforcedremove=false ' Mettre à true pour ne pas retirer les zombies de la base de donnée locale. 106 107 ' Ajouts version 1.1.2 de wpkg.js (Olikin) 108 Dim noreboot : noreboot=true ' Pour ne pas rebooter en cours de session, même si un programme le nécessite. 109 Dim logLevel : logLevel=23 ' Masque binaire : 0 disable logging. 1 log errors only 2 log warnings 4 log information 8 log audit success 16 log audit failure 110 111 ParseArguments 112 113 Dim Ligne1 114 Ligne1 = TimeStamp() & " wpkg-client.vbs : Debut" 115 AttendUnPeu 116 117 Dim oWMIService 118 If Not WaitWMIService() Then WScript.Quit 15 119 120 Dim MsgErrNoRun : MsgErrNoRun="" 121 Dim cProc 122 Dim oProc, cpuLoadOK, cpuLoad 123 If testCPU And Not TestCpuLoad() Then 124 MsgErrNoRun = "La charge cpu est trop élevée. Pas d'exécution de wpkg." 125 nowpkg=true 126 CodeSortie = 14 127 ' WScript.Quit 14 128 End If 129 130 If Not SetComputerName() Then ' Défini ComputerName, User et UserDomain 131 MsgErrNoRun = "Erreur lors de la détermination de ComputerName, User et UserDomain. Pas d'execution de wpkg." 132 nowpkg=true 133 CodeSortie = 13 134 WScript.Quit 13 135 End If 136 137 Z=MapZ() 138 If Z = "" Then WScript.Quit 12 139 Dim WPKGSE3JS : WPKGSE3JS= Z & "\wpkg\wpkg-se3.js" 140 If Not fso.FileExists(WPKGSE3JS) Then 141 print "Erreur: script '" & WPKGSE3JS & "' absent !" 142 WScript.Quit 13 143 Else 144 print "Script '" & WPKGSE3JS & "' présent." 145 End If 146 147 fso.DeleteFile oShell.ExpandEnvironmentStrings("%TEMP%\wpkgcmd*.bat"), true 148 fso.DeleteFile oShell.ExpandEnvironmentStrings("%TEMP%\wpkgex*.log"), true 149 wpkgAuBoot 'execute s'il existe %Windir%\wpkgAuBoot.bat 150 151 If Not TestRunningStatus() Then 152 print "Erreur RunningStatus." 153 MsgErrNoRun = "Erreur RunningStatus." 154 WScript.Quit 1 155 End If 156 'WScript.Echo "dbg: Après TestRunningStatus" 157 158 Dim cmd, sStd, sStdOut, CodeRetour, oExec 159 Dim NoPrint : NoPrint = False 160 161 ' ---------------- Exécution wpkg-se3.js -------------------- 162 dim fNameLog : fNameLog = Z & "\wpkg\rapports\" & ComputerName & ".log" 163 dim fLocalLog : fLocalLog = WinDir & "\wpkg.log" 164 dim fLocalTxt : fLocalTxt = WinDir & "\wpkg.txt" 165 dim fLocal : fLocal = fLocalLog ' Puis devient fLocalTxt pour sauvegarder l'etat 166 dim lenLog ' Taille du fichier fLocalLog déjà lu 167 dim bufferLog : bufferLog = "" 168 dim timerLog : timerLog = Timer 169 170 InitLogFile 171 172 ' Initialisation variables pour les tooltip 173 Dim MSGfile : MSGfile = WinDir & "\wpkg-msg.exe" 174 Dim MSGlog : MSGlog = WinDir & "\wpkg-msg.txt" 175 Dim Dest 176 ' sur windows 7, le dossier Démarrage de AllUsers est différent. 177 ' C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup 178 If InStr(GetTypeWin, "winxp") > 0 Or InStr(GetTypeWin, "win2k") > 0 Then 179 ' on est sur windows XP ou 2000 180 Dest=oShell.ExpandEnvironmentStrings("%AllUsersProfile%") & "\Menu Démarrer\Programmes\Démarrage\" 181 Else 182 'on est sur windows 7 ou vista ou sucesseur. 183 Dest=oShell.ExpandEnvironmentStrings("%AllUsersProfile%") & "\Microsoft\Windows\Start Menu\Programs\Startup\" 184 End If 185 Dim TOOLTIPfile : TOOLTIPfile = Dest & "tooltip.exe" 186 Dim tooltipActifs : tooltipActifs = true 187 If InStr(GetTypeWin, "Server") > 0 Then 188 tooltipActifs = false ' ToolTip inactifs sur les Windows Server. 189 TooltipDelete() ' nettoyage des tooltips antérieurement déployés sur les OS serveurs 190 End If 191 192 If tooltipActifs Then 193 TooltipInit 'initialisation de la configuration du poste, si besoin. 194 End If 195 196 If MiseAJourClient() Then WScript.Quit ' Teste si un nouveau client est dispo sur le serveur 197 198 If Not nowpkg Then ExecIni ' Exécution du vbs ini\%ComputerName%.ini pour initialiser le paramétrage 199 200 ' Décommenter Si les paramètres de la ligne de commande sont prioritaires devant la conf ini 201 'ParseArguments 202 203 Dim NoWpkgTxt : NoWpkgTxt=oShell.ExpandEnvironmentStrings("%SystemDrive%") & "\netinst\nowpkg.txt" 204 If fso.FileExists(NoWpkgTxt) Then 205 nowpkg = True 206 dump "Le fichier '" & NoWpkgTxt & "' existe." & vbCrLf & _ 207 " Pas de synchro des applis pour cette fois." & vbCrLf & _ 208 " Suppression du fichier pour qu'à la prochaine exécution du client la synchro ait lieu." 209 fso.DeleteFile(NoWpkgTxt) 210 End If 211 212 ' on impose /noDownload car les downloads sont geres cote serveur sur SE3. Cela evite de patcher wpkg.js a chaque maj pour ce point. 213 ' mise à jour 1.3 : on impose /applymultiple:true car, dans l'interface SE3, plusieurs profiles s'appliquent à un seul poste. 214 dim WPKG_OPTIONS : WPKG_OPTIONS = "/synchronize /noDownload /applymultiple:true" 215 216 Dim oSysEnv 217 218 WpkgSynchronize 'Exécute wpkg-se3.js pour synchroniser les applications 219 EtatPoste ' Détermine l'état des applis sur le poste et remonte l'info sur le serveur 220 221 If tooltipActifs Then 222 TooltipEnd ' ajout de FIN WPKG dans le fichier MSGfile. 223 End If 224 225 ' ---------------- Déconnexion se3 -------------------- 226 RemoveNetwork 227 print "Fin" 228 229 WScript.Quit CodeRetour 230 231 Function EtatPoste() 232 Dim f, tf, Retour 233 fLocal = fLocalTxt 234 sStd = InfoPoste() 235 Set f = fso.OpenTextFile(fLocal, 2, True) 'ForWriting 236 f.Write sStd 237 f.Close 238 239 cmd = "%ComSpec% /C cscript //NoLogo " & WPKGSE3JS & " /query:a" & " >>" & fLocal & " 2>&1" 240 print "Remontée des applis installées sur le poste ..." 241 PrintOutput = False 242 Retour = RunCmd(Cmd) 243 PrintOutput = True 244 If Retour > 0 Then print "Code de Retour=" & Retour 245 246 Set tf = fso.GetFile(fLocal) 247 If Err.Number > 0 Then 248 dump "Erreur ouverture fichier " & fLocal 249 Err.Clear 250 Else 251 tf.Copy Z & "\wpkg\rapports\" & ComputerName & ".txt", True 252 If Err.Number > 0 Then 253 dump "Erreur ouverture fichier " & Z & "\wpkg\rapports\" & ComputerName & ".txt" 254 Err.Clear 255 End If 256 End If 257 End Function 258 Function RemoveNetwork() 259 Dim i 260 i = secAfterRun 261 Do While i>0 262 If Tempo Then 263 Wscript.Sleep 1000 264 Else 265 Wscript.Sleep 100 266 End If 267 i = i - 1 268 Loop 269 Set oDrives = oNet.EnumNetworkDrives 270 For i = 0 to oDrives.Count - 1 Step 2 271 'print "Lecteur " & oDrives.Item(i) & " = " & oDrives.Item(i+1) 272 print "RemoveNetworkDrive " & oDrives.Item(i) 273 oNet.RemoveNetworkDrive oDrives.Item(i), True 274 If Err.Number > 0 Then 275 print "Erreur RemoveNetworkDrive " & oDrives.Item(i) & " = " & oDrives.Item(i+1) 276 End If 277 Next 278 ' print "RemoveNetworkDrive IPC$" 279 ' oNet.RemoveNetworkDrive "\\" & ServeurWpkg & "\IPC$", True 280 ' If Err.Number > 0 Then print "Erreur RemoveNetworkDrive \\" & ServeurWpkg & "\IPC$" 281 End Function 282 Function WpkgSynchronize() 'Exécute wpkg-se3.js pour synchroniser les applications 283 On Error Resume Next 284 SetEnvironnement 285 oSysEnv("WPKG_OPTIONS") = WPKG_OPTIONS 286 287 cmd = "%ComSpec% /C cscript.exe //NoLogo //T:" & watchDog & " " & WPKGSE3JS & " " & WPKG_OPTIONS & " 1>>" & fLocal &" 2>&1" 288 289 ' Execution de wpkg-se3.js 290 If nowpkg = False Then 291 dump cmd & vbCrLf 292 CodeRetour = RunCmd(Cmd) 293 'If logDebug Then NoPrint=True 294 'dump sStd 295 'NoPrint = False 296 297 If codeRetour = -10 Then 298 dump "---- " & TimeStamp() & " Erreur : Arrêt du script au bout de " & watchDog & " secondes. ----" 299 If Err.Number > 0 Then Err.Clear 300 oShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running" 301 If Err.Number > 0 Then 302 Err.Clear 303 Else 304 dump "La clé HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running a été supprimée." 305 End If 306 Else 307 dump "---- " & TimeStamp() & " CodeRetour=" & CodeRetour & " ----" 308 End If 309 Else 310 dump "noWpkg=true : Pas d'exécution de Wpkg." 311 End If 312 313 'If Not debugVbs Then print "sStd=" & vbCrLf & sStd 314 'Recopie de wpkg.log local vers le serveur 315 If fso.FileExists( fLocal ) Then 316 fso.CopyFile fLocal, Z & "\wpkg\rapports\" & ComputerName & ".log", true 317 End If 318 End Function 319 Function SetComputerName() 320 SetComputerName = True 321 i = 60 ' 60sec maxi 322 Set oNet = CreateObject("WScript.Network") 323 User = oNet.UserName 324 Do While ((Err.Number > 0) Or (User = "")) And (i>0) 325 print "oNet.UserName=" & oNet.UserName 326 If Tempo Then 327 Wscript.Sleep 1000 328 Else 329 Wscript.Sleep 10 330 End If 331 i = i - 1 332 Set oNet = CreateObject("WScript.Network") 333 User = oNet.UserName 334 Loop 335 If i<=0 Then 336 SetComputerName = False 337 Else 338 ComputerName = LCase(oNet.ComputerName) 339 UserDomain = oNet.UserDomain 340 print "User=" & User & ", ComputerName=" & ComputerName &", UserDomain=" & UserDomain 341 End If 342 End Function 343 Function WaitWMIService() 344 Dim i 345 i = 60 ' 60sec maxi 346 Set oWMIService = GetObject( "winmgmts:" ) 347 Do While (Err.Number > 0) And (i>0) 348 print "GetObject('winmgmts:')" 349 If Tempo Then 350 Wscript.Sleep 1000 351 Else 352 Wscript.Sleep 10 353 End If 354 i = i - 1 355 Set oWMIService = GetObject( "winmgmts:" ) 356 Loop 357 If i<=0 Then 358 print "Erreur : Pas de service WMI. FIN." 359 360 WaitWMIService = False 361 Else 362 print "oWMIService : OK" 363 WaitWMIService = True 364 End If 365 End Function 366 Function AttendUnPeu() 367 Dim i 368 If Tempo Then 369 Ligne1 = Ligne1 & " Tempo " & secBeforeStart & " sec." 370 print "Debut Tempo " & secBeforeStart & " sec." 371 ' Attente avant début 372 i = secBeforeStart 373 Do While (i > 0) And Tempo 374 Wscript.Sleep 1000 ' secBeforeStart x 1 seconde d'attente 375 i = i - 1 376 Loop 377 print "Fin Tempo Start" 378 End If 379 End Function 380 Function ParseArguments() 381 Dim i 382 For i = 0 to objArgs.Count - 1 383 arg = Ucase( objArgs(i)) 384 Select Case arg 385 case "/DEBUG" 386 debugVbs = True 387 case "/NOWPKG" 388 nowpkg = True 389 case "/NOTEMPO" 390 Tempo = False 391 case "/APPENDLOG" 392 ' Pour ajouter le log au log précédent 393 LogMode = 8 394 case "/CPULOAD" 395 i = i + 1 396 If IsNumeric(objArgs(i)) Then 397 maxCpuLoad = 0 + objArgs(i) 398 Else 399 print "Syntaxe : /cpuLoad xx ou xx est le %cpu maxi autorisé pour démarrer" 400 End If 401 case "/TEMPO" 402 i = i + 1 403 If IsNumeric(objArgs(i)) Then 404 secBeforeStart = 0 + objArgs(i) 405 Else 406 print "Syntaxe : /Tempo nn ou nn est le nbre de sec à attendre avant de démarrer" 407 End If 408 End Select 409 Next 410 End Function 411 Function TestCpuLoad 412 ' Calcul le taux d'occupation processeur du system consommé par les process sur une durée de 5 secondes 413 ' toutes les 30 secondes. Si ce taux d'occupation est en dessous de la charge maximum demandée pour lancer WPKG 414 'la fonction sort de la boucle et retourne vrai. Au bout de 15 minutes de taux d'occupation supérieur 415 'la fonction retourne faux. 416 bExitFlag = False 417 ' Résultat par défaut. 418 TestCpuLoad = False 419 ' Délai entre deux check pour le calcul de performance (5 secondes). 420 iDelayBetweenCheck = 5000 421 ' Délai entre deux tests de performance de charge (25 secondes). 422 iWaitDelay = 25000 423 ' Nombre de tests de performance maximum a effectuer (un test = 60s). 424 iRetryCount = 30 425 iRetryCounter =1 426 do 427 Set oPPPFirstCheck = oWMIService.Get("Win32_PerfRawData_PerfOS_Processor.Name='_Total'") 428 ' Taux d'occupation cpu premier check. 429 pptFirstCheck = oPPPFirstCheck.PercentProcessorTime 430 tssFirstCheck = oPPPFirstCheck.TimeStamp_Sys100NS 431 Wscript.Sleep(iDelayBetweenCheck) 432 Set oPPPSecondCheck = oWMIService.Get("Win32_PerfRawData_PerfOS_Processor.Name='_Total'") 433 ' Taux d'occupation cpu second check. 434 pptSecondCheck = oPPPSecondCheck.PercentProcessorTime 435 tssSecondCheck = oPPPSecondCheck.TimeStamp_Sys100NS 436 437 ' CounterType - PERF_100NSEC_TIMER_INV 438 ' Formula - (1- ((N2 - N1) / (D2 - D1))) x 100 439 pptCPUConsumed = (1 - ((pptSecondCheck - pptFirstCheck)/(tssSecondCheck-tssFirstCheck)))*100 440 Wscript.Echo "% Processor Time=" , pptCPUConsumed 441 If pptCPUConsumed > maxCpuLoad Then 442 Wscript.Echo "cpuLoad = " & pptCPUConsumed & "% > " & maxCpuLoad & "%" 443 Wscript.Echo "Nouveau test de la charge CPU dans " & ((iWaitDelay + iDelayBetweenCheck)/1000) & " secondes. Veuillez patienter." 444 Else 445 TestCpuLoad = True 446 Wscript.Echo "cpuLoad : OK ( " & pptCPUConsumed & "% <= " & maxCpuLoad & "% )" 447 Exit Do 448 End If 449 WScript.Sleep(iWaitDelay) 450 iRetryCounter = IRetryCounter + 1 451 If iRetryCounter > iRetryCount Then 452 Wscript.Echo "Durée maxi d'attente écoulée. Le PC est trop chargé." 453 Exit Do 454 End if 455 loop while (bExitFlag=false) 456 End Function 457 Function wpkgAuBoot() 458 ' Execute s'il existe %WinDir%\wpkgAuBoot.bat 459 Dim cmd 460 wpkgAuBootBat = WinDir & "\wpkgAuBoot.bat" 461 If Not WScript.Interactive Then ' Uniquement si le client a été lancé avec //B (tâche planifiée au boot) 462 If fso.FileExists( wpkgAuBootBat ) Then 463 print "Exécution de " & WinDir & "\wpkgAuBoot.bat" 464 oShell.Run wpkgAuBootBat, 0, False 465 End If 466 End If 467 End Function 468 Function dateLastLog() 469 If fso.FileExists(fLocalLog) Then 470 Set f = fso.GetFile(fLocalLog) 471 ageLastLog = ( Now - f.DateLastModified) * 24 * 60 ' Ancienneté du dernier log wpkg en mn 472 Else 473 ageLastLog = -1 474 End If 475 If fso.FileExists(fLocalTxt) Then 476 Set f = fso.GetFile(fLocalTxt) 477 ageLastTxt = ( Now - f.DateLastModified) * 24 * 60' Ancienneté du dernier txt wpkg en mn 478 Else 479 ageLastTxt = -1 480 End If 481 End Function 482 Function TestRunningStatus() 483 'print "Dbg: In TestRunningStatus" 484 RunningStatus = LireRegistre("HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running") 485 dump "RunningStatus = " & RunningStatus & ". LastLog = " & ageLastLog & " mn. LastTxt = " & ageLastTxt & " mn." 486 TestRunningStatus = True 487 If RunningStatus = "true" Then 488 If Not WScript.Interactive Then 489 ' Ce script a été lancé par la tâche planifiée au boot 490 ' Il y a un un problème 491 dump "Ce n'est pas normal !" 492 oShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running" 493 dump "La clé HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running a été supprimée." 494 Else 495 ' Lancement manuel de wpkg 496 If ageLastLog > 60 Then ' Plus de 60mn depuis le dernier lancement 497 ' Suppression de l'entrée registre 498 print "RunningStatus = " & RunningStatus & ". Wpkg est indiqué en exécution depuis plus de 1h. C'est sûrement une erreur." 499 oShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running" 500 print "La clé HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running a été supprimée." 501 Else 502 If ageLastLog < 0 Then ' wpkg.log absent 503 ' Suppression de l'entrée registre 504 print "RunningStatus = " & RunningStatus & ". Wpkg est indiqué en exécution mais wpkg.log est absent." 505 oShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running" 506 print "La clé HKEY_LOCAL_MACHINE\SOFTWARE\WPKG\running a été supprimée." 507 Else 508 'Moins de 60mn depuis le dernier rapport 509 print "RunningStatus = " & RunningStatus & ". Wpkg est déjà indiqué en cours d'exécution. FIN." 510 TestRunningStatus = False 511 End If 512 End If 513 End If 514 End If 515 'print "Dbg: Sortie TestRunningStatus RunningStatus=" & RunningStatus 516 End Function 517 Function MiseAJourClient() 518 Dim argCh, oExec, i 519 MiseAJourClient = False 520 If UpdateFile(Z & "\wpkg\wpkg-client.vbs", Windir & "\wpkg-client.vbs") = 1 Then 521 dump TimeStamp() & " Mise à jour du client." 522 ' Redémarrage avec le nouveau client 523 argCh = "" 524 For i = 0 to objArgs.Count - 1 525 argCh = argCh & " " & objArgs(i) 526 Next 527 Set oDrives = oNet.EnumNetworkDrives 528 For i = 0 to oDrives.Count - 1 Step 2 529 'print "Lecteur " & oDrives.Item(i) & " = " & oDrives.Item(i+1) 530 print "RemoveNetworkDrive " & oDrives.Item(i) 531 oNet.RemoveNetworkDrive oDrives.Item(i), True 532 If Err.Number > 0 Then 533 print "Erreur RemoveNetworkDrive " & oDrives.Item(i) & " = " & oDrives.Item(i+1) 534 Err.Clear 535 End If 536 Next 537 dump TimeStamp() & " Redémarrage avec le nouveau client." 538 Set oExec = oShell.Exec("%ComSpec% /C cscript.exe //NoLogo " & WScript.ScriptFullName & argCh & " 2>&1") 539 Do While oExec.Status = 0 540 ' WScript.Sleep 300 541 WScript.StdOut.Write oExec.StdOut.Read(1) 542 Loop 543 dump TimeStamp() & " Fin d'exécution du client d'origine. oExec.ExitCode=" & oExec.ExitCode 544 WScript.Quit oExec.ExitCode 545 'WScript.Run "cscript.exe //NoLogo " & WScript.ScriptFullName & argCh & " 2>&1" 546 MiseAJourClient = True 547 End If 548 End Function 549 Function SetEnvironnement() 550 Set oSysEnv = oShell.Environment("PROCESS") 551 oSysEnv("TypeWin") = GetTypeWin() 552 oSysEnv("ServeurWpkg") = ServeurWpkg 553 oSysEnv("Z") = Z 554 oSysEnv("WPKGROOT") = Z & "\wpkg" 555 oSysEnv("SOFTWARE") = Z & "\packages" 556 oSysEnv("DRIVERS") = Z & "\drivers" 557 oSysEnv("PRINTERS") = Z & "\printers" 558 oSysEnv("WINLANG") = "fra" 559 560 If debug Then WPKG_OPTIONS = WPKG_OPTIONS & " /debug:true" 561 If logdebug Then WPKG_OPTIONS = WPKG_OPTIONS & " /log_file_path:" & Z & "\wpkg\rapports /logfilePattern:" & ComputerName & ".log" 562 If force Then WPKG_OPTIONS = WPKG_OPTIONS & " /force:true" 563 If forceinstall Then WPKG_OPTIONS = WPKG_OPTIONS & " /forceinstall:true" 564 If nonotify Then WPKG_OPTIONS = WPKG_OPTIONS & " /nonotify:true" 565 If norunningstate Then WPKG_OPTIONS = WPKG_OPTIONS & " /norunningstate:true" 566 If dryrun Then WPKG_OPTIONS = WPKG_OPTIONS & " /dryrun:true" 567 If noforcedremove Then WPKG_OPTIONS = WPKG_OPTIONS & " /noforcedremove:true" 568 'Ajout wpkg.js 1.3 (Olikin) 569 If noreboot Then WPKG_OPTIONS = WPKG_OPTIONS & " /noreboot:true" 570 WPKG_OPTIONS = WPKG_OPTIONS & " /logLevel:" & logLevel 571 572 End Function 573 Function ExecIni 574 ' Exécution du vbs ini\%ComputerName%.ini pour initialiser le paramétrage 575 dim iniFile, iniData 576 iniFile = Z & "\wpkg\ini\" & ComputerName & ".ini" 577 If fso.FileExists( iniFile) Then 578 Set f = fso.OpenTextFile(iniFile, 1) 579 iniData = f.ReadAll 580 f.Close 581 If Len(iniData) > 0 Then 582 dump "Fichier d'initialisation trouvé " & iniFile & " (" & Len(iniData) & " octets)." 583 Execute iniData 584 dump "logdebug=" & logdebug 585 Else 586 dump "Fichier " & iniFile & " vide !" 587 End If 588 End If 589 End Function 590 Function InitLogFile() 591 Dim tf 592 On Error Resume Next 593 If LogMode > 0 Then 594 Set tf = fso.OpenTextFile(fLocalLog, LogMode, true) 595 If Err.Number > 0 Then 596 print "Erreur ouverture fichier " & fLocalLog 597 Err.Clear 598 Else 599 If WScript.Interactive Then 600 tf.WriteLine "-----" + TimeStamp() & " Démarrage de wpkg sur " & ComputerName & " (Mode interactif) -----" 601 Else 602 tf.WriteLine "-----" + TimeStamp() & " Démarrage de wpkg sur " & ComputerName & " -----" 603 End If 604 If MsgErrNoRun <> "" Then 605 tf.WriteLine MsgErrNoRun 606 End If 607 tf.Close 608 End If 609 If logdebug Then 610 Set tf = fso.OpenTextFile(fNameLog, LogMode, true) 611 If Err.Number > 0 Then 612 print "Erreur ouverture fichier " & fNameLog 613 Err.Clear 614 Else 615 tf.WriteLine "-----" + TimeStamp() & " Démarrage de wpkg sur " & ComputerName & " -----" 616 If MsgErrNoRun <> "" Then 617 tf.WriteLine MsgErrNoRun 618 End If 619 tf.Close 620 End If 621 End If 622 End If 623 If Err.Number > 0 Then Err.Clear 624 End Function 625 Function dump(msg) 626 ' Ecrit sur le terminal 627 Dim tf, ErreurEnCours 628 ErreurEnCours = 0 629 630 If Err.Number > 0 Then 631 ErreurEnCours=Err.Number 632 Err.Clear 633 If Not NoPrint Then print msg 634 Else 635 If Not NoPrint Then print msg 636 End If 637 On Error Resume Next 638 639 'WScript.Echo "Set tf = fso.OpenTextFile(" & fLocal & ", 8, true)" 640 'Set tf = fso.OpenTextFile(fLocal, 8, true) 641 'If Err.Number > 0 Then 642 ' print "Erreur d'ouverture fichier " & fLocal 643 ' Err.Clear 644 'Else 645 ' If ErreurEnCours > 0 Then 646 ' tf.Write "Erreur " & ErreurEnCours & vbCrLf 647 ' End If 648 ' tf.Write msg & vbCrLf 649 ' tf.Close 650 'End If 651 End Function 652 Function MapZ 653 On Error Resume Next 654 Dim Z0, i, oDrives 655 Dim MapZok : MapZok=True 656 i = 6 ' 60sec maxi (6 * 10) 657 Z0=Z 658 Do 659 print "Map " & Z0 & " " & UNC 660 oNet.MapNetworkDrive Z0, UNC 661 If Err.Number > 0 Then 662 MapZok = False 663 print " MapNetworkDrive Err." 664 If Tempo Then 665 Wscript.Sleep 1000 666 Else 667 Wscript.Sleep 10 668 End If 669 oNet.MapNetworkDrive Z0, UNC 670 If Err.Number > 0 Then 671 Set oDrives = oNet.EnumNetworkDrives 672 For i = 0 to oDrives.Count - 1 Step 2 673 print "Lecteur " & oDrives.Item(i) & " = " & oDrives.Item(i+1) 674 Next 675 print " MapNetworkDrive2 Err " 676 'Essai avec une autre unité après 2 échecs 677 If Z0="x:" Then Z0="w:" 678 If Z0="y:" Then Z0="x:" 679 If Z0="z:" Then Z0="y:" 680 Else 681 MapZok=True 682 print "Map " & Z0 & " " & UNC & " : OK" 683 End If 684 Else 685 MapZok=True 686 print "Map " & Z0 & " " & UNC & " : OK" 687 End If 688 i = i - 1 689 Loop Until MapZok Or (i<=0) 690 If i<=0 Then 691 MapZ="" 692 Else 693 MapZ=Z0 694 End If 695 End Function 696 Function InfoPoste() 697 Set MAC = CreateObject("Scripting.Dictionary") 'Contient Mac et ips associées 698 Dim i, s, ip 699 s = Now & " " & ComputerName 700 getMacIp 701 For Each addmac in MAC.keys 702 s = s & " " & addmac & " (" 703 For each ip in MAC(addmac).keys 704 If MAC(addmac)(ip) = 1 Then 705 If Right(s, 1) <> "(" Then s = s & " " 706 s = s & ip 707 End If 708 If MAC(addmac)(ip) = 2 Then 709 ' Masque de sous-reseau 710 s = s & "/" & ip 711 End If 712 Next 713 s = s & ")" 714 Next 715 InfoPoste = s & " " & GetTypeWin() 716 End Function 717 Function RunCmd(Cmd) 718 Dim nTest, T0, finOK 719 T0 = Timer 720 sStdOut="" 721 FinExec = False 722 723 If fso.FileExists(fLocal) Then 724 lenLog = fso.GetFile(fLocal).size 725 Else 726 lenLog = 0 727 End If 728 Set oExec = oShell.Exec(cmd) 729 nTest = 0 730 finOK = False 731 Do While (Timer < (T0 + watchDog)) And (Not FinExec) 732 If Not ReadOutput() Then 733 If nTest > 5 And oExec.Status = 1 Then 734 '5 sec après la fin d'exécution, s'il n'y a plus rien a lire, on quitte 735 finOK = True 736 FinExec = True 737 Exit Do 738 End If 739 nTest = nTest + 1 740 If Tempo Then 741 Wscript.Sleep 500 742 End If 743 Else 744 nTest = 0 745 End If 746 Wscript.Sleep 100 747 Loop 748 If finOK Then 749 RunCmd = oExec.ExitCode 750 Else 751 If Timer < (T0 + watchDog) Then 752 RunCmd = -1 753 Else 754 ' Fin par TimeOut 755 RunCmd = -10 756 End If 757 End If 758 End Function 759 Function ReadOutput() 760 Dim s, t, f, fichier 761 ReadOutput = False 762 'WScript.Echo "dbg: In ReadOutput, lenLog= " & lenLog 763 If lenLog > 0 Then 764 Set fichier = fso.GetFile(fLocal) 765 fichier.Copy "NUL" ' flush 766 s = fichier.size 767 If s > lenLog Then 768 'Lecture des nouveaux octets arrivés dans le fichier pour les afficher 769 Set f = fichier.OpenAsTextStream(1) ' ForReading 770 f.Skip lenLog 771 t = f.Read( s - lenLog) 772 f.Close 773 sStd = sStd & t 774 If PrintOutput Then WScript.StdOut.Write t 775 lenLog = s 776 ReadOutput = True 777 End If 778 End If 779 End Function 780 Function ReadOutputBAK() 781 Dim poub, s, printNextLigne 782 printNextLine = True 783 ReadOutput = False 784 Do Until oExec.StdOut.AtEndOfStream And (Not FinExec) 785 s = oExec.StdOut.Read(1) 786 If s <> vbCr Then 787 sStdOut = sStdOut & s 788 If oExec.StdOut.AtEndOfLine Then 789 790 'If Left(sStdOut, 1) = vbLf Then sStdOut = Mid(sStdOut, 2) 791 'sStdOut = oem2ansi(sStdOut) 792 sStd = sStd & sStdOut 793 If printOutput Then 794 If (sStdOut = vbCrLf) And Not printNextLine Then 795 printNextLine = True 796 Else 797 If Left(sStdOut, 2) = vbCrLf Then sStdOut = Mid(sStdOut, 3) 798 WScript.Echo sStdOut 799 printNextLine = False 800 End IF 801 End If 802 If sStdOut = "L'exécution du script a pris fin." Then 803 FinExec = True 804 End If 805 sStdOut = "" 806 End If 807 Else 808 sStdOut = sStdOut & s 809 End If 810 ReadOutput = True 811 Loop 812 'WScript.Echo "Dbg: oExec.Status=" & oExec.Status & ", oExec.StdErr.AtEndOfStream=" & oExec.StdErr.AtEndOfStream 813 End Function 814 Function UpdateFile(src, dst) 815 ' Met à jour le fichier dst à partir de src et retourne 816 ' 0 si dst est plus récent (pas de maj) 817 ' 1 si src a été copié en dst 818 ' -1 si src absent ou err copie 819 On Error Resume Next 820 Dim retour : retour=0 821 Dim fSrc, fDst 822 Dim doCopy : doCopy=false 823 Dim dateSrc, dateDst 824 825 If Not fso.FileExists(src) Then 826 UpdateFile = -1 827 Else 828 Set fSrc = fso.GetFile(src) 829 dateSrc = fSrc.DateLastModified 830 If Not fso.FileExists(dst) Then 831 doCopy=true 832 Else 833 Set fDst = fso.GetFile( dst ) 834 dateDst = fDst.DateLastModified 835 ' print "dateSrc=" & dateSrc & ", dateDst=" & dateDst & ", dateDst>=dateSrc = " & (dateDst >= dateSrc) 836 If dateDst >= dateSrc Then 837 ' Dst est à jour 838 UpdateFile = 0 839 Else 840 doCopy=true 841 End If 842 End If 843 If doCopy Then 844 ' copie de src dans dst 845 fso.CopyFile src, dst, true ' Copie avec éventuellemnet écrasement 846 If Err.Number > 0 Then 847 UpdateFile = -1 848 Err.Clear 849 Else 850 UpdateFile = 1 851 End If 852 End If 853 End If 854 End Function 855 Function InitOEM 856 Dim i 857 oem=array( &HC7, &HFC, &HE9, &HE2, &HE4, &HE0, &HE5, &HE7, &HEA, &HEB, &HE8, &HEF, &HEE, &HEC, &HC4, &HC5, &HC9, &HE6, &HC6, &HF4, &HF6, &HF2, &HFB, &HF9, &HFF, &HD6, &HDC, &HF8, &HA3, &HD8, &HD7, &H83, &HE1, &HED, &HF3, &HFA, &HF1, &HD1, &HAA, &HBA, &HBF, &HAE, &HAC, &HBD, &HBC, &HA1, &HAB, &HBB, &HA6, &HA6, &HA6, &HA6, &HA6, &HC1, &HC2, &HC0, &HA9, &HA6, &HA6, &H2B, &H2B, &HA2, &HA5, &H2B, &H2B, &H2D, &H2D, &H2B, &H2D, &H2B, &HE3, &HC3, &H2B, &H2B, &H2D, &H2D, &HA6, &H2D, &H2B, &HA4, &HF0, &HD0, &HCA, &HCB, &HC8, &H69, &HCD, &HCE, &HCF, &H2B, &H2B, &HA6, &H5F, &HA6, &HCC, &HAF, &HD3, &HDF, &HD4, &HD2, &HF5, &HD5, &HB5, &HFE, &HDE, &HDA, &HDB, &HD9, &HFD, &HDD, &HAF, &HB4, &HAD, &HB1, &H3D, &HBE, &HB6, &HA7, &HF7, &HB8, &HB0, &HA8, &HB7, &HB9, &HB3, &HB2, &HA6, &HA0) 858 For i = 128 To 255 859 oem(i - 128) = Chr(oem(i-128)) 860 Next 861 End Function 862 Function oem2ansi(Texte) 'Conversion OEM -> ANSI 863 dim i, s(), l, c, a 864 L = Len(Texte) 865 Redim s(L) 866 For i = 1 To L 867 c = Mid(Texte, i, 1) 868 a = asc(Mid(Texte, i, 1)) - 128 869 If a > 0 Then 870 s(i) = oem(a) 871 Else 872 s(i) = c 873 End If 874 Next 875 oem2ansi = Join(s, "") 876 End Function 877 Function print (a) 878 Dim li 879 li = TimeStamp() & " " & a 880 If (Err.Number > 0) Then 881 li = li & vbCrLf & " Err " & Err.Number & " " & Err.Description & " (" & Err.Source & ")" & vbCrLf 882 Err.Clear 883 End If 884 WScript.Echo li 885 End Function 886 Function TimeStamp() ' Retourne la date formattée pour le fichier de Log ou XML (format : '2006-09-25 16:58:37' ) 887 Dim n 888 n = Now 889 TimeStamp = Year(n) & "-" & Right("00"&Month(n), 2) & "-" & Right("00"&Day(n), 2) & " " & Right("00"&Hour(n), 2) & ":" & Right("00"&Minute(n), 2) & ":" & Right("00"&Second(n), 2) 890 End Function 891 Function DumpError 892 print "Err=" & Err.Number & " " & Err.description 893 Err.Clear 894 On Error Resume Next 895 End Function 896 Function getMacIp() 897 Dim strIPAddress, strIPSubnet 898 Dim objWMI : Set objWMI = GetObject("winmgmts:") 899 Dim objNetworkAdapters : Set objNetworkAdapters = objWMI.ExecQuery("select * from Win32_NetworkAdapterConfiguration where IPEnabled = 1") 900 Dim addmac, ip 901 Dim objAdapter 902 For Each objAdapter In objNetworkAdapters 903 addmac = objAdapter.MacAddress 904 Set MAC(addmac) = CreateObject("Scripting.Dictionary") 905 For Each strIPAddress in objAdapter.IPAddress 906 MAC(addmac).Add strIPAddress, 1 907 Next 908 For Each strIPSubnet in objAdapter.IPSubnet 909 MAC(addmac)(strIPSubnet) = 2 910 Next 911 Next 912 If MAC.Count >=1 Then 913 getMacIp = 1 914 Else 915 getMacIp = 0 916 End If 917 Set objWMI = Nothing 918 Set objAdapter = Nothing 919 Set objNetworkAdapters = Nothing 920 End Function 921 Function LireRegistre(cle) 922 Dim WshShell : Set WshShell = CreateObject("WScript.Shell") 923 Dim bKey 924 On Error resume Next 925 bKey = WshShell.RegRead(cle) 926 If Err.Number <> 0 Then 927 LireRegistre = "" 928 Err.Clear 929 Else 930 LireRegistre = bKey 931 End If 932 'On Error Goto 0 933 End Function 934 935 Function GetTypeWin() 936 Dim TypeWin 937 Dim ProductName, CurrentVersion, ServicePack, CurrentBuildNumber 938 ProductName = LireRegistre("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName") 939 CurrentVersion = LireRegistre("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion") 940 ServicePack = LireRegistre("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CSDVersion") 941 CurrentBuildNumber = LireRegistre("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentBuildNumber") 942 If InStr(ProductName, "Windows XP") > 0 Then 943 TypeWin = "winxp" 944 If InStr(ServicePack, "Pack 3") Then 945 TypeWin = TypeWin & "sp3" 946 End If 947 If InStr(ServicePack, "Pack 2") Then 948 TypeWin = TypeWin & "sp2" 949 End If 950 If InStr(ServicePack, "Pack 1") Then 951 TypeWin = TypeWin & "sp1" 952 End If 953 Else 954 If InStr(ProductName, "Windows 2000") > 0 Then 955 TypeWin = "win2k" 956 If InStr(ServicePack, "Pack 4") Then 957 TypeWin = TypeWin & "sp4" 958 End If 959 If InStr(ServicePack, "Pack 3") Then 960 TypeWin = TypeWin & "sp3" 961 End If 962 If InStr(ServicePack, "Pack 2") Then 963 TypeWin = TypeWin & "sp2" 964 End If 965 If InStr(ServicePack, "Pack 1") Then 966 TypeWin = TypeWin & "sp1" 967 End If 968 Else 969 TypeWin = ProductName 970 End If 971 End If 972 GetTypeWin = TypeWin 973 End Function 974 975 Function TooltipInit() 976 ' Mise en place des tooltips avec les actions suivantes: 977 '0. Efface le fichier de log au début de l'exécution de wpkg pour éviter que celui-ci ne soit trop important à terme. 978 '1. copie du fichier wpkg-msg.exe dans %Z%\wpkg\tools\tooltip\wpkg-msg.exe vers %windir% 979 '2. copie en local de %Z%\wpkg\tools\tooltip\tooltip.exe vers %allusersprofile%\Menu Démarrer\Programmes\Démarrage 980 ' Des tests doivent permettre une exécution instantanée de cette fonction en dehors de la mise en place initiale. 981 'Dim oFSO 982 'Set oFSO = CreateObject("Scripting.FileSystemObject") 983 984 If fso.FileExists(MSGlog) Then 985 fso.DeleteFile MSGlog,True 986 End If 987 988 If Not fso.FileExists(MSGfile) Then 989 ' on copie le wpkg-msg.exe vers %windir% 990 'MsgBox("copie de " & Z & "\wpkg\tools\tooltip\wpkg-msg.exe vers " & WinDir) 991 fso.CopyFile Z & "\wpkg\tools\tooltip\wpkg-msg.exe", WinDir & "\", True 992 End If 993 994 If Not fso.FileExists(TOOLTIPfile) Then 995 'MsgBox(TOOLTIPfile & "absent") 996 fso.CopyFile Z & "\wpkg\tools\tooltip\tooltip.exe", Dest , True 997 End If 998 End Function 999 1000 Function TooltipEnd() 1001 ' Ajoute "FIN WPKG" au fichier de log MSGlog => met fin à l'exécution de tooltip.exe dans la session de l'utilisateur logué. 1002 Const ForAppend = 8 1003 Dim f 1004 'Msgbox("MSGlog," & ForAppend & " , True") 1005 Set f = fso.OpenTextFile(MSGlog, ForAppend, True) 1006 f.WriteLine("FIN WPKG") 1007 ' on fait une pause de 2 secondes pour permettre à tooltip.exe d'avoir le temps de lire "FIN WPKG", puisqu'il lit le fichier toutes les secondes. 1008 Wscript.Sleep 2000 1009 ' on écrit une autre ligne à la fin de wpkg-msg.txt afin d'éviter le problème "un user ouvre la session avant que wpkg ne soit lancé" qui provoquerait immédiatement l'arrêt de tooltip.exe 1010 f.WriteLine("") 1011 f.Close 1012 End Function 1013 1014 Function TooltipDelete() 1015 ' Suppression des tooltips : prévu pour nettoyer les OS Windows Server de Caen 1016 If fso.FileExists(MSGlog) Then 1017 fso.DeleteFile MSGlog, True 1018 End If 1019 If fso.FileExists(MSGfile) Then 1020 fso.DeleteFile MSGfile, True 1021 End If 1022 If Not fso.FileExists(TOOLTIPfile) Then 1023 fso.DeleteFile TOOLTIPfile, True 1024 End If 1025 End Function
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |