diumenge, 7 d’abril del 2019

Programació de Windows amb Powershell

 Introducció a Powershell: cmdlets i objectes

Aquesta pàgina és una breu introducció al sistema d'scripting de Windows; se supposa que el lector té coneixements bàsics de programació a nivell de variables, paràmetres i estructure de control bàsiques.

Què és i per què serveix el Windows PowerShell?

  • És una interfície de consola (comandaments) per Windows molt més avançada que el seu predecessor cmd (command)
  • Està destinat a administradors de sistemes amb la finalitat principal d’automatitzar tasques
  • Es poden crear scripts powershell, a part d’utilitzar-se com a simple consola de comandes 
  • La seva característica principal és que les seves comandes són orientades a objectes, això vol dir que es veu el sistema operatiu com una col·lecció d'objectes virtuals; per exemple un procés del sistema és un objecte, i una carpeta del sistema de fitxers un altre objecte. Cada objecte té unes propietats i unes funcions, per exemple són propietats de l'objecte carpeta el seu nom i la seva data de creació, i són funcions el renombrar-la o mostrar el seu contingut.
  • Powershell (abreujadament PS) s’ inclou en Windows a partir del Windows Vista
 El podem iniciar anant a Inicio->Buscar Programas y archivos->Powershell.

Fig. 1: finestra de comandaments del Powershell

Comandaments del Powershell: cmdlets

Cmdlet és un nom creat pels desenvolupadors de Windows PowerShell.  Són les comandes que es poden utilitzar en PowerShell, diferents de les comandes tradicionals del cmd.exe

Fig. 2: els cmdlets get-process (informació d'un procés) i end-process (finalitzar procés)
Per veure tots els cmdlets disponibles usem el cmdlet Get-command:

Get-command –commandtype cmdlet

Per consultar el manual d’ajuda d’un cmdlet:

Get-help cmdlet 

Exemple: Get-help stop-process

Podem crear els anomenats alias, que permeten assignar noms de dreceres (“shortcuts” ) als cmdlets; per exemple, anomenar gh al cmdlet Get-help: gh stop-process)

Els cmdlets Get-item i Get-member


Get-member és un altre cmdlet que ens permet obtenir totes les propietats i mètodes d'un objecte al que hem vinculat la variable. Aquest objecte pot ser qualsevol, fins i tot un altre cmdlet. La forma de usar-lo es amb el símbol "|" per unir l'objecte amb el get-member, el resultat és un llistat complerta de propietats:

Fig.3: propietats del cmdlet get-process, obtingudes usant get-member
El cmdlet Get-item permet assignar (o vincular) una variable de Powershell amb un objecte; les variables en PS comencen sempre per $. Des del moment que assignem la variable a l'objecte, totes les accions que efectuem amb la variable afectaran a l'objecte (estan vinculats).

Exemple: amb Get-item vinculem una variable amb l'objecte que representa la carpeta C:\windows. A continuació, podem veure les seves propietats i mètodes amb Get-member.

Fig.4: assignació d'una variable a un objecte (carpeta) i mostrar les propietats

Les propietats dels objectes

Cada objecte té una llista de propietats, i cada propietat te un valor; per veure el valor d'una propietat simplement escribim el seu nom. Per exemple, en la fig.4 veiem que l'objecte carpeta te la propietat Mode, per veure el seu valor:

PS C:\Users\Administrador> $carpeta.mode
d----
PS C:\Users\Administrador>

La línia d---- indica que l'objecte és un fitxer de tipus "directori" (d). Un altre exemple amb la propietat name:


PS C:\Users\Administrador> $carpeta.name
system32
PS C:\Users\Administrador>
I un darrer exemple amb la propietat que ens dona la data de creació de la carpeta:

PS C:\Users\Administrador> $carpeta.CreationTime

martes, 14 de julio de 2009 4:37:07

Crear scripts (guions) de comandaments Powershell

Nivells de seguretat

Un script és una seqüencia de comandaments, és a dir, un programa.
Per defecte, l’execució d’scripts PS està deshabilitada per seguretat, degut a que PS és molt potent, és pot fer qualsevol cosa amb ell si tens drets d'execució.

Hi ha 4 nivells d’ execució d’scripts:
  1. Restricted: no es pot executar scripts
  2. AllSigned: tots els scripts que s’executen han d’estar signats digitalment
  3. RemoteSigned: tots els scripts descarregats d’internet han d’estar signats per un autor de confiança
  4. Unrestricted: es poden executar tots els scripts
Per comprovar i canviar el nivell: obrim el powershell com administradors (amb el botó dret del ratolí :”Run as administrator”), comprovem el nivell actual d’execució amb el cmdlet: Get-ExecutionPolicy, i si cal canviem el nivell amb el cmdlet Set-ExecutionPolicy:

PS C:\Users> get-executionpolicy
Unrestricted
PS C:\Users> set-executionpolicy allsigned

Cambio de directiva de ejecución
La directiva de ejecución le ayuda a protegerse de scripts en los que no confía. Si cambia dicha directiva podría exponerse a los riesgos de seguridad descritos en el tema de la Ayuda about_Execution_Policies. ¿Desea cambiar la directiva de ejecución?
[S] Sí  [N] No  [U] Suspender  [?] Ayuda (el valor predeterminado es "S"):
PS C:\Users>

Execució de scripts PS

Es poden crear utilitzant qualsevol editor de text o amb l’entorn integrat Windows PowerShell ISE. Un script PS és un fitxer de text amb l’extensió .ps1
Les diferents versions de Windows han anat incorporant noves versions de PS que fins la versió 5 han estat compatibles amb les anteriors. Els exemples d'aquesta pàgina han estat fets amb Windows 7 i PS v2; per evitar que algú executi un script específic per una versió moderna amb un PS antic només cal afegir al principi de l’script una línia amb la directiva #REQUIRES, per exemple per evitar que un script s'executi en versions anteriors a la 2a:  
#REQUIRES Version 2
Exemple: provem un script que modifica l'aspecte de l'antic comandament DIR. L'original mostra el llistat de fitxers i carpetes:

PS C:\Users> dir


    Directorio: C:\Users


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        24/07/2017     19:47            Administrador
d----        16/12/2016      8:06            alumne
d----        17/01/2018      8:07            jordi
d----        11/01/2017     13:47            prova
d-r--        25/07/2017     20:43            Public


Fem que mostri el contingut de la carpeta que li passem com a paràmetre
formatat en colors:

$carpeta = $args[0];
Write-Host ("Llistat de la carpeta $carpeta")
 

# recorre cada element de dins la carpeta
foreach ($i in Get-Childitem $carpeta) {
    if ($i.mode.substring(0,1) -eq "d") {
        Write-Host $i.name -foreground "Blue"
       }
    else {
        Write-Host $i.name -foreground "Green"
    }
 } 


El resultat d'executar aquest script, anomenat dir2.ps1, és:

Fig. 5: script que mostra el contingut d'una carpeta

Comentem l'script línia a línia:


$carpeta = $args[0]; args es un vector (o array) que conté la llista de paràmetres que pasem a l’script quan l’executem; per exemple si cridem a l’script així:
.\dir2.ps1 jordi
llavors args[0] valdrà «jordi»
si el cridem \dir2.ps1 jordi pepe
llavors args[0] valdrà «jordi» i args[1] valdrà «pepe», etc
Write-Host ("Llistat de la carpeta $carpeta") Write-Host és un cmdlet que mostra text, variables o una combinació de tots dos per pantalla. En aquest cas combina text amb la variable $carpeta
foreach ($i in Get-Childitem $carpeta) { La instrucció foreach és un cmdlet, especial: és una instrucció de control del programa que a més a més recorre cada element de una llista d’objectes.
La llista d’objectes són tots els continguts dintre de la carpeta $carpeta. S'obté aquesta llista gràcies al cmdlet Get-Childitem, que retorna tots els «fills» d’una carpeta.
La variable auxiliar $i va identificant-se succesivament amb tots els objectes de la llista d’objectes dins de la carpeta $carpeta
if ($i.mode.substring(0,1) -eq "d") { If és un altre estructura de control, s’anomena condicional. La clau { indica que comencen una serie de instruccions condicionals.
Per cada objecte $i, la seva propietat mode retorna si es un directori o un fitxer; la funció substring extreu 1 caràcter des de la posició 0 (la primera posició) i si és igual (expressió -eq) a «d», és que l’objecte és un directori.
Write-Host $i.name -foreground "Blue" Escriure el nom de l’objecte (propietat name) usant el color de fons blau
} Finalització de la primera part de l’estructura de control if
else { Inici de l’estructura de control else, continuació de la if
Write-Host $i.name -foreground "Green" Escriure el nom de l’objecte (propietat name) usant el color de fons verd; aixó pasarà quan la primera lletra de la propietat mode no sigui igual a «d», és a dir, quan l’objecte no sigui un directori.
} Finalització de l’estructura de control else
} Finalització de l’estructura de control foreach


Per fer comparacions en l'exemple s'ha usat l'operador lògic -eq, tenim tots aquests:

Ús de variables i constants

Les variables en PowerShell, no s’han de declarar abans d’utilitzar-les, com sí pasa en altres lleuguatges de programació. Totes van precedides del símbol $. Hi ha un conjunt de variables especials que es creen automàticament, com ara $Error  que conté el llistat d'errors d'execució que han succeït, o $Args que ja hem vist que conté la llista de paràmetres que pasem a l’script quan l’executem; no podem usar variables propies nostres que es diguin igual que les especials, obtindriem un error:










PS C:\Users> $error="hola"
No se puede sobrescribir la variable Error porque es de solo lectura o constante.
Les constants (valors amb un nom identificatiu que no han de canviar aquest valor) són tractades com a variables, amb la diferència que no canvien mai de valor, estan protegides contra canvis; es creen amb el cmdlet Set-Variable amb el paràmetre –option constant

Exemple:
PS C:\Users> set-variable -name pc -value "localhost"
PS C:\Users> set-variable -name tipus -value "portàtil" -option constant

PS C:\Users> $pc = "127.0.0.1"
PS C:\Users> $tipus = "torre"
No se puede sobrescribir la variable tipus porque es de solo lectura o constante.
Llista de variables especials (per Powershell v2):


Les variables poden ser "tipades" és a dir, restringides a contenir valors de cert tipus de dades, com ara nombres enters, un caràcter, una cadena de caràcters:



El tipus es defineix automàticament segons el contingut de la variable.
Exemple:
PS C:\Users> $a = 1; $b = 2
PS C:\Users> $c = $a + $b
PS C:\Users> $c
3
En canvi si usem valors de tipus cadena de caràcters:
PS C:\Users> $a = "1"; $b = "2" ; $c = $a + $b
PS C:\Users> $c
12
Aquest comportament automàtic està pensat per fer les coses fàcils al programador, però pot induïr a errors; quin serà el resultat de la següent operació que mescla caràcters amb nombres?
PS C:\Users> $a = "1"; $b = 2 ; $c = $a + $b
Alguns cmdlets per gestionar les variables són:
Altres variables especials són les variables d’entorn, mantingudes automàticament pel sistema operatiu.
  • Per veure les variables d’entorn del sistema escrivim dir env:
  • Per mostrar el valor d’una variable d’entorn, com ara la variable tmp, escrivim $env:tmp
  • Per modificar el valor d’una variable d’entorn, com ara userprofile, escrivim $env:userprofile=“C:\Users\profe”
  • Per afegir un valor a una variable d’entorn, com ara afegir "ps1" a la variable pathest, escrivim $env:pathext += “;ps1”
  • Per consultar el valor d'una variable d’entorn especificant si és global del sistema o local de l'usuari  la sintaxi és
[environment]::GetEnvironmentVariable(“nom de la variable”,”User”)
El paràmetre “User” si volem veure el valor de la variable per tots els usuaris posarem “Machine” enlloc de “User”.
  • Per modificar el valor d'una variable d’entorn de forma permanent la sintaxi és
[environment]::SetEnvironmentVariable(“nom de la variable”,nou valor,”User”)


Exemple
La variable d'entorn OS és global, no té un valor concret per l'usuari que té sessió oberta, com podem comprobar:
PS C:\Users> [environment]::GetEnvironmentVariable("OS","User")
PS C:\Users> [environment]::GetEnvironmentVariable("OS","Machine")
Windows_NT
Llavors podem donar un valor personalitzat a la variable OS per l'usuari que té la sessió oberta:
PS C:\Users> [environment]::SetEnvironmentVariable("OS","Windows 7","User")
Comprovem:
PS C:\Users> [environment]::GetEnvironmentVariable("OS","Machine")
Windows_NT
PS C:\Users> [environment]::GetEnvironmentVariable("OS","User")
Windows 7

Pipelines (canonades) en PS

Serveixen per passar informació d'un comandament a un altre (“canonades” de informació o “conduccions” que connecten comandaments). Per exemple si volem saber certa informació de tots els ordinadors d'un domini, podem obtenir amb Powershell una llista amb els noms dels ordinadors del domini, però després com passem aquesta llista a un altre comandament que proporcionai la informació desitjada? Connectant el resultat del primer comandament amb el segon.
Les canonades ja existien en la antiga consola MSDOS, per exemple:
Fig.6: canonada per filtrar totes les adreces de xarxa, lògiques i MACS
 Windows PowerShell no passa text com feia MSDOS, passa objectes; el comandament receptor podrà accedir a les propietats de l'objecte enviat directament. Per exemple el cmdlet format formata la informació rebuda usant plantilles:

PS C:\Users> get-ChildItem | format-table


    Directorio: C:\Users


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        24/07/2017     19:47            Administrador
d----        16/12/2016      8:06            alumne
d----        17/01/2018      8:07            jordi
d----        11/01/2017     13:47            prova
d-r--        25/07/2017     20:43            Public
-a---        06/04/2019     14:45        337 dir.ps1
-a---        07/04/2019     11:35        314 dir2.ps1


PS C:\Users> get-ChildItem | format-list


    Directorio: C:\Users



Name           : Administrador
CreationTime   : 12/01/2017 10:14:11
LastWriteTime  : 24/07/2017 19:47:04
LastAccessTime : 24/07/2017 19:47:04

Name           : alumne
CreationTime   : 16/12/2016 8:05:56
LastWriteTime  : 16/12/2016 8:06:20
LastAccessTime : 16/12/2016 8:06:20

Alguns cmdlets expressament pensats per actuar com a canonades, rebent informació d'un altre cmdlet:

Cmdlet/funció
Descripció
ConvertTo-Html
Converteix objectes a HTML
Export-Csv
Guarda objectes en fitxes separat per un coma
ForEach-Object
Retorna cada pipeline un darrera l’altre
Format-Table
Mostra resultats com una taula
Get-Unique
Elimina duplicats d’una llista de valors
Group-Object
Agrupa els resultats segons un criteri
more
Paginació pàgina a pàgina, amb pauses
Out-file
Escriu el resultat en un fitxer
Out-Host
Mostra el resultat pel terminal
Out-Host -paging
Mostra el resultat pel terminal per pàgines
Out-Null
Esborra el resultat
Out-Printer
Envia els resultat a una impressora
Select-Object
Filtra les propietats d’un objecte i limita el número de resultats
Sort-Object
Ordena el resultat
Where-Object
Filtra els resultats segons un criteri


Alguns exemples d'ús:
PS>Dir | sort-object
PS>Dir | sort LastWriteTime –descending
PS>Dir | format-table name, lastwritetime
PS>get-process | where-object { $_.name –eq “winlogon”}
PS>get-process | where-object { $_.CPU –gt 4}
PS>get-process | where-object { $_.name –notmatch “sys”}
PS>Dir | sort-object Length | select-object Name,Length | convertTo-html | out-file report.htm
En particular, el cmdlet foreach ens permet avaluar cada element del resultat d’una comanda anterior.

Exemples:

PS> get-process | foreach {write-output $_.Id}
PS> get-process | foreach {write-host $_.Id –f red}
PS> dir | foreach {echo $_.Name}
Les canonades són eines molt potents que obren moltes possibilitats; cal practicar una mica amb elles per adonar-se de les seves possibilitats. Per exemple, podem resoldre ràpidament problemes com els següents:

P1) Genera una llista dels 5 processos que consumeixen més temps de CPU.
PS C:\Users> get-process | sort-object CPU -descending | select-object -first 5

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1215      31    26160      25372   186    73,31    976 svchost
   1011      32    46372      38996   326    58,11   2348 explorer
    354      24    32948      17240   170    56,92    336 svchost
    558      13    46256      42900   123    44,13    896 svchost
    309       7     1480       4704    39    11,95    408 csrss
P2) Mostra els processos del teu sistema que estiguin utilitzant més de 50MB de memoria virtual

get-process | where-object {$_.virtualmemorysize –gt 52428800}

P3) Exporta el resultat de la consulta anterior en un fitxer amb format CSV
get-process | where-object {$_.virtualmemorysize –gt 52428800} | export-csv proc.csv

Accés al sistema de fitxers des de PS

Alguns cmdlets:
Exemples
  • Crear nous directoris: podem utilitzar l’alias md o la comanda New-item amb l’opció –type directory
PS> md exercici
PS> New-item exercici –type directory

  • Crear nous fitxers: podem utilitzar la comanda New-item amb l’opció –type file o també redireccionaments i pipelines:

PS> New-item ex.txt –type file
PS> dir > info1.txt
PS> dir | out-file info2.txt
PS> dir | set-content info3.txt
PS> set-content info4.txt “primera línia”
PS> add-content info4.txt “segona línia”
PS> “tercera línia” >> info4.txt
  • Per esborrar fitxers o carpetes, utilitzarem remove-item o l’alias del. En el cas de fitxers protegits amb “només lectura”, utilitzarem l’opció –force per esborrar-los.
  • Crear un fitxer normal, després protegir-lo amb “read-only” i eliminar-lo:
PS> $f = New-item ex.txt –type file
PS> $f.isreadonly

false
PS> $f.isreadonly = $true
PS> del ex.txt –force


  • Esborrar un directori que no està buit: PS> del directori –recurse 

Accés al permisos des de PS

En NTFS, els permisos d’accés determinen quins usuaris poden accedir a fitxers i carpetes. Aquests permisos estan a les llistes de control d’accés (ACL), cada entrada d’aquesta llista s’anomena acces control entry (ACE). Get-Acl i Set-Acl són cmdlets del PS per modificar permisos. Icacls és una comanda tradicional que també permet modificar permisos, d’una forma més àgil que els cmdlets de PS; per consultar la seva ajuda: icacls /?
Exemples
  • Comprovar el propietari: PS> (get-acl c:\users).owner
  • Llistar els permisos d’accés: PS> (get-acl c:\users).access
  • Clonar permisos entre dues carpetes: PS> $acl=get-acl carpeta1 seguit de PS> set-acl carpeta2 $acl

Accés al sistema operatiu des de PS

PS permet accedir a qualsevol element del sistema, no només a usuaris i sistemes de fitxers si no també al propi sistema operatiu i fins i tot al maquinari.
La classe d'objectes anomenada WMI (Windows Management Instrumentation) representa el sistema” en forma d'objectes, i  ens proporciona accés a qualsevol
element intern: processador, BIOS, memòria, usuaris, serveis, etc...El seu nom normalment consisteix en el prefix “Win32” i el nom de l’element al qual accedeix. Per ex: Win32_BIOS descriu la BIOS.

Get-WmiObject ens permet llegir el valor de les propietats d’una classe WMI. Exemple:
PS C:\Users> Get-WmiObject Win32_Bios | format-list

SMBIOSBIOSVersion : VirtualBox
Manufacturer      : innotek GmbH
Name              : Default System BIOS
SerialNumber      : 0
Version           : VBOX   - 1
Consulta d’una propietat d’una instància d'un objecte del sistema:
PS> $bios=Get-WmiObject Win32_Bios
PS> $bios | get-member
PS> $bios.version
Per poder modificar el valor d’una propietat d’una instància d’un WMI, s’han de cumplir 3 condicions:
  1. La propietat no ha de ser de només lectura
  2. S’ha de ser administrador, perquè el canvi afectarà a tots els usuaris
  3. En acabar, s’ha d’utilitzar la funció put() perquè els canvis tinguin efecte

Exemple: Canviem la descripció del processador
PS> $p=get-wmiobject win32_processor
PS> $p.description=“Model de la familia x64”
PS> $.put





















Cap comentari:

Publica un comentari a l'entrada

Gestió d'usuaris i grups en Linux

Usuaris i grups Linux  Els comptes de Linux són com els comptes de Windows o MacOS; però els detalls no, així que cal explicar alguns detall...