Hé, le scripteur ! Utilisation de bases de données Access dans Windows PowerShell

The Microsoft Scripting Guys

les bases de données sont mysterious pièces de logiciel. Dans leur forme la plus simple qu'ils sont rien armoires de classement pour stocker des informations. La magie réelle commence par l'application de ces informations stockées. Bien sûr, plus merveille conçu de base de données sans aucun enregistrement n'est plus qu'un exercice universitaire rien. Il est les données qui constitue la base de données. Chaque fois que nous savoir sur les personnes disposant d'une énorme base de données, les personnes réagissent avec awe. Pas dû à la base de données, mais pour les données, elle contient.

Comment toutes les données obtenir dans une base de données ? Saisie manuelle des données dans une base de données est pour les oiseaux et il s'est passé les avec les cartes perforation touches. Pour créer une base de données suffisamment grande pour Impressionnez vos amis et offrent la possibilité de déverrouiller les mysteries de votre réseau, vous devez automatiser. Aujourd'hui, cela signifie que Windows PowerShell, et dans cet article, c'est ce que nous utiliserons pour collecter des données sur l'ordinateur local et l'écrire à une base de données Office Access appelé ComputerData.mdb. Cette base de données peut être créée manuellement, ou vous pouvez utiliser le script trouvé dans l'article » Comment je peut de créer une base de données avec plusieurs tables ?." Il appelle notre script WriteToAccessDatabase.ps1 afin que nous sachent ce qu'elle fait.

Nous allons commencer, créez la fonction de chèque-chemin d'accès, qui sera utilisée pour vous assurer que la base de données existe. Pour créer la fonction, nous utiliser le mot clé, fonction, donner un nom à la fonction et définir les variables entrées il devrez recevoir. La première chose Qu'archivage chemin d'accès n'est la cmdlet Test-chemin d'accès permet de voir si le répertoire dans le chemin d'accès à la base de données existe. Pour ce faire, il utilise la cmdlet de double-chemin d'accès pour diviser le chemin d'accès en une partie parente et une partie enfant. Nous devons uniquement la partie parent du chemin à vérifier l'existence de l'annuaire. Voici comment nous utilisons double-chemin d'accès pour récupérer le chemin d'accès parent :

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

Au lieu de vérifier la présence du chemin d'accès, nous utilisons l'opérateur NOT (!) pour rechercher son absence. Si le dossier n'existe pas, le mot clé jeter est utilisé pour générer une erreur :

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

Même si le dossier existe, le fichier de base de données est peut-être manquant. Nous utilisons le mot-clé ELSE pour présenter cette condition substitution. Une fois encore, nous utiliser l'instruction IF pour rechercher la présence du fichier de base de données et le mot clé jeter pour générer une erreur s'il n'existe pas :

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

Nous avons vraiment ne devez utiliser la construction IF…ELSE pour vérifier l'existence de la base de données. Un simple appel à la cmdlet Test-chemin d'accès à l'aide du paramètre –path fonctionnerait. Cependant, à l'aide de IF…ELSE fournit un niveau plus élevé de commentaires. Nous vous voulez savoir si le répertoire existe et, si tel est le cas, le fichier existe ? Il est certainement possible la base de données manquant provient peut-être du dossier de, mais il est également possible de que le dossier lui-même peut être manquant. Cette donne plus granulaire des commentaires et peut faciliter la résolution des problèmes.

Lorsque nous avez vérifié que la base de données existe, nous créer la fonction Get-BIOS pour obtenir les informations BIOS de la classe WMI Win32_Bios. Voici la fonction Get-BIOS :

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

En encapsulant l'appel WMI dans une fonction, nous obtenir la possibilité de facilement modifier la fonction, comme ajout de fonctionnalité à distance ou accepter les informations d'identification. La modification a pu être établie ici, sans impact sur le reste du script. En fait, du point de vue test, si elle ne fonctionne pas, vous commentaire simplement le code de fonction et le script restant continue à fonctionner. Pour obtenir de l'aide à trouver des informations concernant les classes WMI, vous pouvez utilisez les Windows PowerShell Scriptomaticmontre la figure 1 . Cet outil vous permet d'explorer facilement les espaces de noms WMI et classes et même crée le script Windows PowerShell pour récupérer les informations.

fig01.gif

Figure 1, version de Windows PowerShell de l'utilitaire Scriptomatic

Ensuite, nous allons créer la fonction Get-vidéo pour récupérer les informations vidéo à partir de la classe WMI Win32_VideoController. Comme vous pouvez le voir, cette fonction est similaire à la fonction Get-BIOS :

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

Nous devons maintenant établir une connexion à la base de données. Pour ce faire, nous utilisons la fonction de la base de données de connexion. Nous créons deux paramètres d'entrée de la fonction de la base de données de connexion : –DB et –Tables dont les valeurs sont stockés dans la BD $ et $ des variables de tables dans la fonction. La première chose que nous dans la base de données se connecter fonctionnent consiste à affecter valeurs à deux variables sont utilisées pour contrôler la façon dont le RecordSet est ouvert. La méthode Open de l'objet RecordSet peut accepter à cinq différents paramètres, comme suit :

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

Le premier est le paramètre source, qui renvoie un objet de commande valide, une instruction SQL, un nom de table, un appel de procédure stockée, une URL ou le nom d'un objet fichier ou un flux contenant un objet Recordset stocké avec persistance. Le deuxième paramètre est le ConnexionActive, une chaîne qui renvoie un objet de connexion valide ou une chaîne qui contient les paramètres connectionstring. Le paramètre CursorType est utilisé pour déterminer le type de curseur qui sera utilisé lorsque vous ouvrez le RecordSet. Les valeurs autorisées pour le type de curseur sont présentées dans la figure 2 .

La figure 2 ADO curseur type énumération constantes et valeurs
Constante Valeur Description
adOpenDynamic 2 Utilise un curseur dynamique. Les ajouts, modifications et les suppressions effectués par d'autres utilisateurs sont visibles, et tous les types de déplacements à l'intérieur du Recordset sont permis, à l'exception des signets, si le fournisseur ne les prend pas en charge.
adOpenForwardOnly 0 Par défaut. Utilise un curseur avant uniquement. Identique à un curseur statique, sauf que vous pouvez uniquement défiler avant enregistrements. Les performances sont améliorées si vous ne devez n'effectuer qu'un seul passage dans un objet Recordset.
adOpenKeyset 1 Utilise un curseur keyset. Comme un curseur dynamique, sauf que vous ne pouvez pas voir les enregistrements dont les autres utilisateurs et enregistrements supprimés par d'autres utilisateurs sont inaccessibles à partir de votre objet Recordset. Modifications apportées aux données par d'autres utilisateurs sont toujours visibles.
adOpenStatic 3 Utilise un curseur statique, ce qui est une copie statique d'un jeu d'enregistrements que vous pouvez utiliser pour rechercher des données ou générer des rapports. Ajouts, modifications ou les suppressions effectués par d'autres utilisateurs ne sont pas visibles.
adOpenUnspecified -1 Ne spécifie pas le type de curseur.

Le paramètre LockType est utilisé pour déterminer le type de verrou à utiliser pour mettre à jour les enregistrements et le paramètre options est utilisé pour indiquer le fournisseur comment évaluer le paramètre source. Les les valeurs autorisées pour le paramètre LockType sont présentées dans la figure 3 .

La figure 3 ADO verrouiller type énumération constantes et valeurs
Constante Valeur Description
AdLockBatchOptimistic 4 Indique les mises à jour par lot optimiste. Requis pour le mode de mise à jour par lot.
AdLockOptimistic 3 Indique le verrouillage optimiste, enregistrement par enregistrement. Le fournisseur utilise le verrouillage optimiste, qui verrouille enregistrements uniquement lorsque vous appelez la méthode Update.
AdLockPessimistic 2 Indique le verrouillage pessimiste, enregistrement par enregistrement. Le fournisseur est nécessaire garantir réussi modification des enregistrements, généralement en verrouillant les enregistrements à la source de données immédiatement après avoir modifié.
adLockReadOnly 1 Indique les enregistrements en lecture seule. Vous ne pouvez pas modifier les données.
adLockUnspecified -1 Ne spécifie pas un type de verrou. Pour les clones, le clone est créé avec le même type de verrou que l'original.

Toutes les cinq des paramètres de la méthode Open de l'objet RecordSet sont facultatifs ; en règle générale, nous utilisons uniquement les quatre premières. Après que nous avez affecté des valeurs à utiliser pour l'énumération de curseur et le type de verrou, nous utilisons la cmdlet New-Object pour créer un nouvel objet ADODB.Connection que nous stocker dans la variable de connexion $. Nous utilisons ensuite la méthode Open de l'objet Connection, qui nécessite le nom du fournisseur et la source de données. Nous appeler la fonction mise à jour-enregistrements puis transmettre la variable de tables $. Voici la fonction de la base de données de connexion :

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

Dans la fonction mise à jour-les enregistrements, la première chose que nous est créer une instance de l'objet ADODB.Recordset. Nous utilisons la cmdlet New-Object pour ce faire et de stocker l'objet RecordSet nouvellement créé dans la variable RecordSet $. Ensuite, nous utiliser le pour chaque instruction pour revue notre tableau de tableaux. Les noms des tables sont stockées dans la variable de tables $ et sont affectés au début du script. Dans la boucle ForEach, nous tout d'abord créer notre requête, qui est une sélection plutôt générique * de table $. L'avantage d'utiliser une variable pour le nom de table est que nous suffit d'écrire le code une seule fois ; le nom de table dans la requête récupère change chaque fois que nous boucle dans le tableau des noms de table.

Nous sont maintenant à la méthode ouverte de l'objet RecordSet. Nous spécifions la requête qui est stockée dans la variable $ la requête, l'objet de connexion dans la variable de connexion $, la valeur OpenStatic $ et la valeur de LockOptimistic $ pour contrôler la façon dont le RecordSet est ouvert. Nous utilisons ensuite la cmdlet Invoke-expression pour exécuter la valeur de chaîne. Nous faire parce que nous ont créées de deux fonctions qui sont conçues pour vous mettez à jour les tables de base de données différente. Nous avons nommé les fonctions après la mise à jour les tables. Nous ne peuvent pas appeler un nom de fonction lorsque la moitié des il étant une variable, nous devez résoudre la variable, puis appelle la fonction.

Mais qui ne fonctionne pas soit, du moins pas directement. Ce que nous voulons faire est de traiter le nom de la fonction comme s'il s'agissait d'une chaîne et non une commande. Mais nous exécuter comme une commande. Pour ce faire, nous Utilisez expression de Invoke. Cette cmdlet appelle chacune de ces fonctions autre mise à jour. Dans la boucle qui passe par le tableau des noms de table, nous fermer tous les objets RecordSet, puis revenir à l'élément suivant dans le tableau de noms de tables, créez une nouvelle requête ouvrir un nouvel objet RecordSet et appeler une nouvelle fonction. Ceci continue de chacun de la table noms dans le tableau des tables, souhaitez pour :

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()
     }

Après la mise à jour les enregistrements, nous pouvez fermer la connexion. Pour ce faire, nous utilisons la méthode Close à partir de l'objet Connection :

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

La fonction mise à jour-enregistrements appelle deux fonctions prise en charge, mise à jour-BIOS et mise à jour-vidéo, qui sont conçues pour mettre à jour les champs appropriés la table de base de données respectifs. Si vous deviez ajouter des tables supplémentaires à votre base de données, vous devez ajouter une fonction de mise à jour * supplémentaire pour mettre à jour les nouvelles tables. Raisons, nous vous recommandons de conserver les noms des champs de base de données identique les noms des propriétés WMI. Il facilite choses effectuer le suivi des. Lorsque vous écrivez un script pour mettre à jour une base de données existante, vous souhaiterez peut-être consulter le schéma de base de données pour les tables, colonnes et types de données contenus dans les champs. Le schéma de base de données de la base de données ComputerData est illustré figure 4 . Cet affichage était généré par le script à partir de l'article » Comment peut je savoir quelles tables et sont les colonnes dans une base de données sans son ouverture?"

fig04.gif

La figure 4, le schéma de base de données de la base de données ComputerData

Dans la fonction mise à jour-BIOS, nous publier tout d'abord un message indiquant que nous sont mettre à jour les informations du BIOS. Nous puis appelez la fonction Get-BIOS et stocker de l'objet WMI Win32_Bios renvoyé dans la variable BiosInfo $. Nous devons maintenant ajouter un enregistrement à la table de base de données. Pour ce faire, nous appelons la méthode AddNew à partir de l'objet RecordSet. Après que nous avons un nouvel enregistrement, nous ajouter des informations relatives à chacun des champs de la table. Lorsque tous les champs ont été mis à jour, nous appeler la méthode Update pour valider l'enregistrement dans la table. La fonction de mise à jour-BIOS complète est affichée ici :

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

Lorsque la table BIOS a été mis à jour, nous devons mettre à jour la table vidéo. Pour ce faire, nous pouvez appeler la fonction mise à jour-vidéo, qui est exactement le même que la fonction mise à jour-BIOS. Nous présenter un message indiquant que nous mis à jour la vidéo, appelez la fonction Get-vidéo pour récupérer les informations vidéo, appelez la méthode AddNew pour ajouter un nouvel enregistrement à la table vidéo et écrire toutes les informations dans les champs appropriés. Lorsque nous avez terminés, nous appelons la méthode mise à jour.

Un problème potentiel de recueillir les informations vidéo est le nombre de contrôleurs vidéo sur l'ordinateur. Mon ordinateur personnel dispose d'une carte fille et rapports de plusieurs contrôleurs de vidéo. Pour gérer cette éventualité, nous utilisons l'instruction ForEach pour itérer dans une collection de Win32_VideoControllers. Si vous ne souhaitez pas dans les informations de configuration de carte fille ou si votre carte vidéo est double canal et rapports les mêmes informations, vous pouvez supprimer la boucle ForEach et sélectionner $ VideoInfo [0] à index directement dans la première enregistrer qui est signalée. Le problème avec cette approche est que si la requête renvoie un singleton, vous génère une erreur, car vous ne peut pas indexer en un seul enregistrement :

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

Le point d'entrée pour le script pointe vers la base de données, répertorie les tables et puis appelle la fonction de la base de données de connexion, comme illustré ici :

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

Après l'exécution le script, les nouveaux enregistrements sont écrits dans la base de données ComputerData.mdb comme illustré figure 5 . Le script WriteToAccessDatabase.ps1 complet peut être constaté dans figure 6 .

fig05.gif

La figure 5 nouveaux enregistrements ajoutés à la base de données ComputerData.mdb

La figure 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

Si vous souhaitez en savoir plus sur l'utilisation de bases de données Office Access à partir de Windows PowerShell, consultez Hey le », Scripting Guy!" archive de la semaine de 20 février 2009. En outre, le 2009 Jeux de script d'été sont bientôt ! Reportez-vous au scriptingguys.com Pour plus d'informations.

Édition Wilson , un expert de script bien connu, est l'auteur de huit livres, notamment Windows PowerShell Scripting Guide (2008) et Microsoft Windows PowerShell Step by Step (2007). Édition contient plus de 20 certifications industrie, y compris Microsoft Certified Systems Engineer (MCSE) et Certified Information Systems Security Professional (CISSP). Ses loisirs, il aime woodworking, underwater photographie et plongée sous-marine. Et thé.

Craig Liebendorfer est wordsmith et longtime éditeur Web de Microsoft. Craig ne peut pas pensez toujours il y a un travail paie lui pour travailler avec des mots chaque jour. Une des ses choses favoris est irreverent d'humour, afin qu'il doit ajuster droite ici. Il considère que ses accomplishment plus élevé dans la vie à sa fille magnificent.