23 feb 2010

Gestione Collegamenti LNK tramite VBS

È un dato di fatto: i desktop dei PC aziendali sono una schifezza. Sono pieni di collegamenti, magari vecchi ed obsoleti o che puntano al percorso errato.

A volte sono pieni di collegamenti scritti con le maiuscole, o con troppi spazi, o con troppo pochi spazi, oppure capitalizzati senza un criterio logico e comprensibile.

Spesso ancora i collegamenti vengono creati sul desktop (e quindi nel profilo) di ogni singolo utente, mentre a volte se ne starebbero più felici e contenti nel profilo All Users del computer.

Come rimediare ad una situazione del genere, e dare un tocco di pulizia e professionalità ai catorci PC della nostra azienda?
Con un poco di codice VBS, naturalmente!

Casi di utilizzo
Si potrebbero voler eliminare tutti i collegamenti non più necessari, quali ad esempio \\ServerAziendale\Documenti\Incentivi\.

Oppure si potrebbero voler aggiornare dei collegamenti con un nuovo percorso (ad es. i collegamenti ad http://it.wikipedia.org potrebbero essere aggiornati alla nuova versione dell'enciclopedia all'indirizzo http://nonciclopedia.wikia.com).

In questo esempio farò molto di più!

Vado alla ricerca del collegamento ad un determinato programma (\\ServerAziendale\Programma\Start.exe) sul desktop di ogni singolo utente. Se almeno un utente dispone di questo link, li cancello tutti quanti, e ne ricreo uno solo (con il nome bello, pulito, e capitalizzato come si deve) nel desktop di All Users.

The Code
Set Start_Exe = CreateObject("System.Collections.ArrayList")

La variabile Start_Exe conterrà tutti gli eventuali link al nostro programma.
Rem *** Ricerca in tutti i profili ***

Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS         = &H80000003

strComputer = "."

Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
Set ws = CreateObject("Wscript.Shell")
Set oFs = CreateObject("Scripting.FileSystemObject")

strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys

For Each objSubkey In arrSubkeys
  strValueName = "ProfileImagePath"
  strSubPath = strKeyPath & "\" & objSubkey
  objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE, strSubPath, strValueName, strProfile
  ScanDesktop(strProfile & "\Desktop") ' dispongo del percorso del desktop!
Next

strAllUsersDesktopPath = ws.SpecialFolders.Item("AllUsersDesktop")

rem *** se si vogliono ricreare anche i collegamenti in AllUsers già esistenti,
rem *** decommentare le seguenti righe
'ScanDesktop(strAllUsersDesktopPath)
Il codice precedente legge l'elenco dei percorsi dei profili, a partire dalla chiave HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList. Che fare se il desktop è stato redirezionato da qualche parte? Ci pensiamo un'altra volta, please!


Ed ecco il codice che ricrea i collegamenti:
Rem ***verifica se ci sono collegamenti al programma
If Start_Exe.Count > 0 Then
  Set objShtCut = ws.CreateShortcut(strAllUsersDesktopPath & "\Programma Aziendale.lnk")
  objShtCut.TargetPath = "\\ServerAziendale.dominio.dc\Programma\Start.exe"
  objShtCut.WorkingDirectory = "\\ServerAziendale.dominio.dc\Programma\"
  objShtCut.Save
  Set objShtCut = Nothing

  For Each Lnk in Start_Exe
    Set fl = oFs.GetFile(Lnk)
    fl.Delete
    Set fl = Nothing
  Next
End If

Manca niente? Manca il codice che scansiona ogni singolo Despol:

Sub ScanDesktop(profile)
  If oFs.FolderExists(profile) Then
    Set oFolder = oFs.GetFolder(profile)

    For Each oFile In oFolder.Files
    name = oFile.Name
    if len(name)>4 and UCase(right(name,4)) = ".LNK" then
      Set objShtCut = ws.CreateShortcut(profile & "\" & oFile.Name)
      Select Case UCase(objShtCut.TargetPath)
      Case "\\SERVERAZIENDALE\PROGRAMMA\START.EXE"
        Start_Exe.Add profile & "\" & oFile.Name
      Case "\\SERVERAZIENDALE.DOMINIO.DC\PROGRAMMA\START.EXE
        Start_Exe.Add profile & "\" & oFile.Name
      End Select
      Set objShtCut = Nothing
    End If
End Sub
Naturalmente nella nostra sub ScanDesktop possiamo identificare i collegamenti tramite il metodo che preferiamo.
E naturalmente, come al solito, sto allegramente ignorando molte condizioni d'errore. Ma la vita è troppo corta per la gestione adeguata degli errori. E in VBS non vi è traccia di Try Catch Finally... oppure sì?

17 feb 2010

Sostituzione stringa in un file di testo, in vbs

Va bene, so che questo codice non è proprio originale ma è stato preso qua e là dalla rete e riadattato, e so che ciò mi costerà qualche cosa in termini di - già povero - PageRank.

Ma avevo bisogno di modificare una stringa in un file di sistema all'avvio del PC. Cosa c'è di meglio di uno script VBS per fare il lavoro? E per distribuirlo, le buone vecchie policy di Active Directory vanno sempre bene:

Dim WshShell, objEnv
Dim FileContents, dFileContents
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objEnv = WshShell.Environment("Process")

FileContents = GetFile(objEnv("ProgramFiles") & "\ProgrammaCattivo\Config.cfg")
dFileContents = Replace(FileContents, "StringaVecchia", "StringaNuova", 1, -1, 1)

If dFileContents <> Filecontents Then
  WriteFile objEnv("ProgramFiles") & "\ProgrammaCattivo\Config.cfg", dFileContents
End If

Function GetFile(FileName)
  Dim FS, FileStream
  Set FS = CreateObject("Scripting.FileSystemObject")
  Set FileStream = FS.OpenTextFile(FileName)
  GetFile = FileStream.ReadAll
End Function

Function WriteFile(FileName, Contents)
  Dim OutStream, FS
  Set FS = CreateObject("Scripting.FileSystemObject")
  Set OutStream = FS.OpenTextFile(FileName, 2, True)
  OutStream.Write Contents
End Function

E poi, naturalmente, è sempre utile sapere se e quando lo script è stato eseguito per davvero. Magari possiamo aggiungere anche qualche altra informazione di debug, che non fa mai male.


WshShell.RegWrite "HKLM\Software\MiaAzienda\Init_Settings_Eseguito", Now(), "REG_SZ"
WshShell.RegWrite "HKLM\Software\MiaAzienda\Init_Settings_Sostituzioni", conteggio, "REG_SZ"
etc...

Happy scripting, guys!

8 feb 2010

Motion Graphics

Bello il mondo WYSIWYG, ma devo ammettere di essere sempre rimasto affascinato dalla possibilità di scrivere un programma via codice e vederlo poi girare, dal buttare giù una pagina Web in HTML/CSS e vederla generata a video, dall'impaginare un documento con LaTeX pronto per essere compilato e stampato.

Forse non è un caso che mi sia avvicinato alla Computer Music tramite i Tracker!

E forse è per questo che mi sono affezionato al pacchetto Office: c'è qualche cosa di magico nel riempire un file di testo di dati o parole, scrivere un programma VBA che lo interpreta, e vedere che si genera a video un bel foglio Excel o un bel documento di Word od un grafico in Visio, con un livello di perfezione irraggiungibile con il solo mouse! Ehm forse sto esagerando? Ovviamente so che nessuno utilizza Office così!

Ma noto con piacere che Google, con le sue Google Documents List Data API, e tutte le altre API, sta andando nella giusta direzione...

Così, devo dire di aver trovato molto interessante l'articolo Beautiful Motion Graphics Created With Programming: Showcase, Tools and Tutorials tratto dall'ottimo Smashing Magazine. Mi si potrebbe aprire un nuovo mondo!

Tra tutti i programmi sto giocando un pochino con Processing e nel frattempo... se avrò un po' più di tempo libero ho capito a che cosa mi dovrò dedicare nella prossima vita.