Buongiorno Mr Script! Utilizzo di database di Access in Windows PowerShell

The Microsoft Scripting Guys

i database sono comprensibile componenti software. Nella forma più semplice sono niente più gli armadietti di archiviazione per la memorizzazione delle informazioni. Chiave reale inizia con l'applicazione di questo informazioni archiviate. Naturalmente, più beautifully progettato database senza i record è niente di più di un esercizio Academic Search. È il dato che il database. Ogni volta che si sente su chi dispone di un database di grandi dimensioni, gli utenti rispondere con awe. Non a causa di database, ma per i dati contiene.

Come tutti i dati ottengono in un database? Immissione manuale dei dati in un database è destinata la con uccelli e causa uscita con schede Perforatore chiave. Per creare un database sufficientemente grande da impress i tuoi amici e fornire il grado di sbloccare mysteries della rete, è necessario automatizzare. Oggi, ciò significa che Windows PowerShell e in questo articolo, questo è ciò che si utilizzerà per raccogliere alcuni dati sul computer locale e scriverlo in un database Office Access denominato ComputerData.mdb. Questo database può essere creato manualmente oppure utilizzare lo script trovato nell'articolo" Come È possibile creare un database con più di una tabella." Abbiamo chiamerà script WriteToAccessDatabase.ps1 in modo verrà sappiamo cosa accade.

Iniziamo creando la funzione di percorso di archiviazione, che verrà utilizzata per verificare che il database esista. Per creare la funzione, è utilizzare la parola chiave Function, assegnare la funzione di un nome e definire le variabili di input potrebbe essere necessario per la ricezione. La prima cosa che percorso di archiviazione è utilizzare il cmdlet percorso test per verificare se esiste la directory nel percorso del database. A tale scopo, viene utilizzato il cmdlet percorso divisa per suddividere il percorso in una parte padre e una parte figlio. È necessario solo la parte principale del percorso per verificare l'esistenza della directory. Ecco come utilizziamo percorso divisa per recuperare il percorso padre:

PS C:\> Split-Path C:\fso\ComputerData.mdb -Parent
C:\fso

Invece di controllare la presenza del percorso, è possibile utilizzare l'operatore NOT (!) per cercare la sua assenza. Se la cartella non esiste, la parola di chiave throw viene utilizzata per generare un errore:

Function Check-Path($Db)
{
 If(!(Test-Path -path (Split-Path -path $Db -parent)))
   { 
     Throw "$(Split-Path -path $Db -parent) Does not Exist" 
   }

Anche se la cartella esiste, il file di database potrebbe essere manca. Viene utilizzato la parola chiave ELSE per introdurre condizione alternativo. Ancora una volta, è utilizzare l'istruzione IF per rilevare la presenza del file database e la parola chiave throw per generare un errore se non esiste:

  ELSE
  { 
   If(!(Test-Path -Path $Db))
     {
      Throw "$db does not exist"
     }
  }
} #End Check-Path

È davvero non necessario utilizzare la costruzione IF…ELSE per verificare l'esistenza del database. Una semplice chiamata per il cmdlet Test-percorso utilizzando il parametro –path funzionerebbe. Tuttavia, la utilizzando IF…ELSE fornisce un livello superiore di feedback. Si desidera sapere se la directory esista e, in caso affermativo, il file esiste? È certamente possibile il database potrebbe essere manca dalla cartella, ma è anche possibile che la cartella stessa potrebbe essere manca. Questo fornisce maggiore commenti e suggerimenti e può facilitare nella risoluzione dei problemi.

Quando si hanno garantita che il database esiste, è creare la funzione Get-BIOS per ottenere le informazioni del BIOS dalla classe WMI Win32_Bios. Ecco la funzione Get-BIOS:

Function Get-Bios
{
 Get-WmiObject -Class Win32_Bios
} #End Get-Bios

Incapsulando la chiamata WMI in una funzione, è possibile ottenere la possibilità di modificare facilmente la funzione, ad esempio, aggiunta di funzionalità remoto o l'accettazione delle credenziali. La modifica può essere eseguita qui senza influire il resto dello script. In effetti, dal punto di vista del test, se non funziona, sufficiente commento il codice della funzione e lo script rimanente continua a funzionare. Per assistenza nella ricerca le informazioni relative alle classi WMI, è possibile utilizzare la Windows PowerShell Scriptomaticillustrato nella Figura 1 . Questo strumento consente di esaminare facilmente spazi dei nomi WMI e le classi e crea anche lo script di Windows PowerShell per recuperare le informazioni.

fig01.gif

Figura 1 versione di Windows PowerShell dell'utilità Scriptomatic

Successivamente, si verrà creare la funzione Get-video per recuperare informazioni video dalla classe Win32_VideoController WMI. Come può notare, questa funzione è simile la funzione Get-BIOS:

Function Get-Video
{
 Get-WmiObject -Class Win32_VideoController
} #End Get-Video

A questo punto è necessario stabilire una connessione al database. A tale scopo, è utilizzare la funzione database connessione. È creare due parametri di input per la funzione di connessione a database: –DB e –Tables i cui valori vengono memorizzati nella DB $ $ tabelle variabili all'interno la funzione. La prima cosa che è all'interno la connessione a database funzione consiste nell'assegnare valori a una coppia di variabili che vengono utilizzate per controllare il modo in cui che il RecordSet viene aperto. Il metodo Open dell'oggetto RecordSet può accettare fino a cinque parametri diversi, come illustrato di seguito:

RecordSet.Open Source, ActiveConnection, CursorType, LockType, Options 

Il primo è il parametro di origine, che restituisce un oggetto command valido, un'istruzione SQL, un nome di tabella, una chiamata di stored procedure, un URL o il nome di un oggetto file o flusso contenente un oggetto Recordset salvato in modo permanente. Il secondo parametro è la ActiveConnection, una stringa che restituisce un oggetto di connessione valida, oppure una stringa che contiene i parametri connectionstring. Il parametro CursorType (ADO) viene utilizzato per determinare il tipo di cursore che verrà utilizzato durante l'apertura il RecordSet. I valori consentiti per il tipo di cursore sono illustrati nella Figura 2 .

Costanti di enumerazione di tipo cursore ADO nella Figura 2 e valori
Costante Valore Descrizione
adOpenDynamic 2 Viene utilizzato un cursore dinamico. Le aggiunte, modifiche e le eliminazioni eseguite da altri utenti sono visibili e tutti i tipi di spostamento all'interno dell'oggetto Recordset sono consentiti, tranne per i segnalibri, se il provider non li supporta.
adOpenForwardOnly 0 Impostazione predefinita. Viene utilizzato un cursore forward-only. Identico a un cursore statico, ad eccezione del fatto che è possibile solo scorrere avanti i record. Questo consente di migliorare le prestazioni quando è necessario eseguire un solo passaggio all'interno di un oggetto Recordset.
adOpenKeyset 1 Viene utilizzato un cursore keyset. Come un cursore dinamico, ad eccezione del fatto che non è possibile visualizzare i record aggiunti dagli altri utenti e i record che altri utenti di eliminano siano non accessibili dall'oggetto Recordset. Le modifiche di dati da altri utenti sono ancora visibili.
adOpenStatic 3 Utilizza un cursore statico, è una copia statica di un set di record che è possibile utilizzare per trovare i dati o generare report. Le aggiunte, modifiche o le eliminazioni eseguite da altri utenti non sono visibili.
adOpenUnspecified -1 Non specifica il tipo di cursore.

Il parametro LockType è utilizzato per determinano il tipo di blocco da utilizzare durante l'aggiornamento dei record e il parametro options è utilizzato per indicare il provider come valutare il parametro di origine. I valori consentiti per il parametro LockType sono illustrati nella Figura 3 .

Nella figura 3 blocco ADO tipo di enumerazione costanti e valori
Costante Valore Descrizione
AdLockBatchOptimistic 4 Indica aggiornamenti ottimistici in blocco. Richiesto per la modalità di aggiornamento in blocco.
AdLockOptimistic 3 Indica blocco ottimistico, record per record. Il provider utilizza il blocco ottimistico, che blocca i record solo quando si chiama il metodo Update.
AdLockPessimistic 2 Indica blocco pessimistico, record per record. Il provider esegue sia necessaria per garantire la corretta modifica dei record, in genere bloccando i record nell'origine dei dati dopo la modifica.
adLockReadOnly 1 Indica i record di sola lettura. È impossibile modificare i dati.
adLockUnspecified -1 Non specifica un tipo di blocco. Per i cloni, il clone viene creato con il tipo di blocco stesso dell'originale.

Tutte le cinque dei parametri per il metodo Open dell'oggetto RecordSet sono facoltativi, in genere, si utilizzano solo i quattro primo. Dopo è avere assegnato i valori da utilizzare per l'enumerazione del cursore e il tipo di blocco, è utilizzare il cmdlet oggetto nuovo per creare un nuovo oggetto ADODB.Connection che è possibile memorizzare nella variabile di connessione $. Quindi utilizziamo il metodo Open dall'oggetto Connection, che richiede il nome del provider e l'origine dati. È quindi, chiamare la funzione di record di aggiornamento e passa la variabile di tabelle $. Ecco la funzione di DataBase di connessione:

Function Connect-Database($Db, $Tables)
{
  $OpenStatic = 3
  $LockOptimistic = 3
  $connection = New-Object -ComObject ADODB.Connection
  $connection.Open("Provider = Microsoft.Jet.OLEDB.4.0;Data Source=$Db" )
  Update-Records($Tables)
} #End Connect-DataBase

Nella funzione record di aggiornamento, la prima cosa che facciamo è creare un'istanza di oggetto ADODB.Recordset. È possibile utilizzare il cmdlet oggetto nuovo per eseguire questa operazione e memorizzare l'oggetto RecordSet appena creato nella variabile $ RecordSet. Quindi, utilizziamo il ciclo For Each istruzione per scorrere la matrice delle tabelle. I nomi delle tabelle vengono memorizzati nella variabile $ tabelle e vengono assegnati all'avvio di script. All'interno del ciclo ForEach, è necessario creare la query, è una selezione piuttosto generica * dalla tabella $. Il vantaggio di tramite una variabile per il nome di tabella è che è solo necessario scrivere il codice una volta; il nome della tabella nella query Ottiene modificato ogni volta che si scorrere la matrice di nomi di tabelle.

È ora sono al metodo aperte dell'oggetto RecordSet. È specificare la query che viene memorizzata nella variabile $ query, l'oggetto connessione in variabile $ connessione, il valore di OpenStatic $ e controllare il RecordSet viene aperto il modo in cui il valore di LockOptimistic $. È quindi utilizzare il cmdlet espressione Invoke per eseguire il valore di una stringa. Questa operazione è è necessaria poiché sono stati creati due funzioni sono progettati per aggiornare le tabelle di database diversi. Le tabelle che si aggiorna è denominata le funzioni. Non è consentiti chiamare un nome di funzione quando metà della è una variabile, è necessario risolvere la variabile e quindi chiamare la funzione.

Ma che non sia, almeno non direttamente. Si desidera eseguire consiste nel gestire il nome della funzione come se fosse una stringa e non un comando. Ma si desidera eseguire come un comando. A tale scopo, è possibile utilizzare espressioni di Invoke. Questo cmdlet richiama ognuna delle funzioni di aggiornamento differenti. All'interno del ciclo che passa attraverso la matrice di nomi di tabelle, è chiudere ognuno degli oggetti RecordSet, quindi tornare al successivo elemento della matrice di nomi di tabelle, creare una nuova query, aprire un nuovo oggetto RecordSet e chiamare una funzione di nuova. Il problema persiste per ogni tabella nomi nella matrice delle tabelle, come in modo da:

Function Update-Records($Tables)
{
  $RecordSet = new-object -ComObject ADODB.Recordset
   ForEach($Table in $Tables)
     {
      $Query = "Select * from $Table"
      $RecordSet.Open($Query, $Connection, $OpenStatic, $LockOptimistic)
      Invoke-Expression "Update-$Table"
      $RecordSet.Close()
     }

Una volta i record vengono aggiornati, è possibile chiudere la connessione. A tale scopo, utilizziamo il metodo Close dall'oggetto di connessione:

   $connection.Close()
} #End Update-Records

La funzione di record di aggiornamento chiama due funzioni di supporto, BIOS Update e aggiornamento, video, ovvero sono progettati per aggiornare i campi appropriati nella tabella di database relativi. Se si deve aggiungere altre tabelle del database, è necessario aggiungere una funzione di aggiornamento * aggiuntiva per aggiornare le nuove tabelle. Ottimale, si consiglia di mantenere i nomi dei campi di database lo stesso i nomi di proprietà WMI. Semplice operazioni molto tenere traccia di. Quando si scrive uno script per aggiornare un database esistente, potresti voler controllare lo schema del database per le tabelle, colonne e tipi di dati contenuti nei campi. Lo schema del database per il database ComputerData è illustrato nella Figura 4 . Questa visualizzazione è stata generata dallo script dall'articolo" Come È possibile verificare le tabelle e colonne vengono in un database senza, apertura?"

fig04.gif

Nella figura 4 il schema di database per il database ComputerData

Nella funzione BIOS di aggiornamento, è innanzitutto registrare un messaggio indicante che si sono aggiornare le informazioni del BIOS. È quindi chiamare la funzione Get-BIOS e memorizzare l'oggetto WMI Win32_Bios restituito in variabile BiosInfo di $. A questo punto è necessario aggiungere un record alla tabella di database. A tale scopo, è necessario chiamare il metodo AddNew dall'oggetto RecordSet. Quando si dispone di un nuovo record, è possibile aggiungere informazioni a ciascuno dei campi nella tabella. Quando tutti i campi sono stati aggiornati, chiamiamo il metodo Update per eseguire il commit il record nella tabella. La funzione di BIOS aggiornamento completa è visualizzata di seguito:

Function Update-Bios
{
 "Updating Bios"
 $BiosInfo = Get-Bios
 $RecordSet.AddNew()
 $RecordSet.Fields.Item("DateRun") = Get-Date
 $RecordSet.Fields.Item("Manufacturer") = $BiosInfo.Manufacturer
 $RecordSet.Fields.Item("SerialNumber") = $BiosInfo.SerialNumber
 $RecordSet.Fields.Item("SMBIOSBIOSVersion") = $BiosInfo.SMBIOSBIOSVersion
 $RecordSet.Fields.Item("Version") = $BiosInfo.Version
 $RecordSet.Update()
} #End Update-Bios

Quando la tabella del BIOS è stata aggiornata, è necessario aggiornare la tabella video. A tale scopo, è possibile chiamare la funzione video di aggiornamento, che è esattamente lo stesso la funzione di BIOS di aggiornamento. Si presentano un messaggio indicante che si sta aggiornando il video, chiamare la funzione Get-video per recuperare le informazioni di video, chiamare il metodo AddNew per aggiungere un nuovo record alla tabella video e scrivere tutte le informazioni ai campi appropriati. Dopo è terminati, chiamiamo il metodo Update.

Un potenziale problema di raccolta delle informazioni video indica il numero di controller video nel computer. Il computer personale include una scheda figlia e report più controller video. Per gestire questa eventualità, è possibile utilizzare l'istruzione ForEach per scorrere un insieme di Win32_VideoControllers. Se non sono interessati alle informazioni di configurazione scheda figlia o se la scheda video è canale doppio e rapporti le stesse informazioni due volte, è possibile rimuovere il ciclo ForEach e selezionare $ VideoInfo [0] al indice direttamente nel primo record è dichiarato. Il problema con questo approccio è che se la query restituisce un singleton, si genererà un errore poiché è impossibile indicizzare in un unico record:

Function Update-Video
{ "Updating video" $VideoInformation = Get-Video 
Foreach($VideoInfo in $VideoInformation)  
  {
   $RecordSet.AddNew()   $RecordSet.Fields.Item("DateRun") = Get-Date
   $RecordSet.Fields.Item("AdapterCompatibility") = $VideoInfo.AdapterCompatibility
   $RecordSet.Fields.Item("AdapterDACType") = $VideoInfo.AdapterDACType
   $RecordSet.Fields.Item("AdapterRAM") = $VideoInfo.AdapterRAM
   $RecordSet.Fields.Item("Description") = $VideoInfo.Description
   $RecordSet.Fields.Item("DriverDate") = $VideoInfo.DriverDate
   $RecordSet.Fields.Item("DriverVersion") = $VideoInfo.DriverVersion
   $RecordSet.Update()
  }
} 
#End Update-Video

Il punto di ingresso per lo script punta al database, verranno elencate le tabelle e quindi chiama la funzione di connessione a DataBase, come illustrato di seguito:

$Db = "C:\FSO\ComputerData.mdb"+
$Tables = "Bios","Video"
Check-Path -db $Db
Connect-DataBase -db $Db -tables $Tables

Dopo aver eseguito lo script, i nuovi record vengono scritti nel database ComputerData.mdb, come illustrato nella Figura 5 . Lo script WriteToAccessDatabase.ps1 completo può essere visualizzato nella Figura 6 .

fig05.gif

Nella figura 5 nuovi record aggiunti al database ComputerData.mdb

Nella figura 6 WriteToAccessDataBase.ps1

Function Check-Path($Db)
{
 If(!(Test-Path -path (Split-Path -path $Db -parent)))
   { 
     Throw "$(Split-Path -path $Db -parent) Does not Exist" 
   }
  ELSE
  { 
   If(!(Test-Path -Path $Db))
     {
      Throw "$db does not exist"
     }
  }
} #End Check-Path

Function Get-Bios
{
 Get-WmiObject -Class Win32_Bios
} #End Get-Bios

Function Get-Video
{
 Get-WmiObject -Class Win32_VideoController
} #End Get-Video

Function Connect-Database($Db, $Tables)
{
  $OpenStatic = 3
  $LockOptimistic = 3
  $connection = New-Object -ComObject ADODB.Connection
  $connection.Open("Provider = Microsoft.Jet.OLEDB.4.0;Data Source=$Db" )
  Update-Records($Tables)
} #End Connect-DataBase

Function Update-Records($Tables)
{
  $RecordSet = new-object -ComObject ADODB.Recordset
   ForEach($Table in $Tables)
     {
      $Query = "Select * from $Table"
      $RecordSet.Open($Query, $Connection, $OpenStatic, $LockOptimistic)
      Invoke-Expression "Update-$Table"
      $RecordSet.Close()
     }
   $connection.Close()
} #End Update-Records

Function Update-Bios
{
 "Updating Bios"
 $BiosInfo = Get-Bios

 $RecordSet.AddNew()
 $RecordSet.Fields.Item("DateRun") = Get-Date
 $RecordSet.Fields.Item("Manufacturer") = $BiosInfo.Manufacturer
 $RecordSet.Fields.Item("SerialNumber") = $BiosInfo.SerialNumber
 $RecordSet.Fields.Item("SMBIOSBIOSVersion") = $BiosInfo.SMBIOSBIOSVersion
 $RecordSet.Fields.Item("Version") = $BiosInfo.Version
 $RecordSet.Update()
} #End Update-Bios

Function Update-Video
{
 "Updating video"
 $VideoInformation = Get-Video
 Foreach($VideoInfo in $VideoInformation)
  { 
   $RecordSet.AddNew()
   $RecordSet.Fields.Item("DateRun") = Get-Date
   $RecordSet.Fields.Item("AdapterCompatibility") = $VideoInfo.AdapterCompatibility
   $RecordSet.Fields.Item("AdapterDACType") = $VideoInfo.AdapterDACType
   $RecordSet.Fields.Item("AdapterRAM") = $VideoInfo.AdapterRAM
   $RecordSet.Fields.Item("Description") = $VideoInfo.Description
   $RecordSet.Fields.Item("DriverDate") = $VideoInfo.DriverDate
   $RecordSet.Fields.Item("DriverVersion") = $VideoInfo.DriverVersion
   $RecordSet.Update()
  }
} #End Update-Video

# *** Entry Point to Script ***

$Db = "C:\FSO\ComputerData.mdb"
$Tables = "Bios","Video"
Check-Path -db $Db
Connect-DataBase -db $Db -tables $Tables

Se si desidera ottenere ulteriori informazioni sull'uso con database Office Access di in Windows PowerShell, consultare la "Hey, Scripting Guy!" archivio per la settimana del 20 febbraio 2009. Inoltre, il 2009 estate Scripting giochi sono Prossimamente! Visitare il sito scriptingguys.com Per ulteriori informazioni.

ed Wilson , un noto esperto di script è l'autore di otto libri, tra cui Windows PowerShell Scripting Guide (2008) e Microsoft Windows PowerShell Step by Step (2007). Ed contiene più di 20 certificazioni del settore, tra cui Microsoft Certified Systems Engineer (MCSE) e informazioni Certified di Systems Security Professional (CISSP). Nel tempo riserva, ha apprezzino woodworking, fotografia subacquee e scuba subacquee. E macchie.

Craig Liebendorfer è wordsmith e longtime editor Web di Microsoft. Craig ancora non ritiene c'è un processo che paga gli lavorare con le parole ogni giorno. Uno dei suoi elementi preferiti è irreverent umorismo in modo che deve adattare destra in questa posizione. Ha considerato suo accomplishment maggiore nella vita da sua figlia magnificent.