Mostrando entradas con la etiqueta Power Shell. Mostrar todas las entradas
Mostrando entradas con la etiqueta Power Shell. Mostrar todas las entradas

jueves, 23 de mayo de 2013

Powershell y passwords

EnPower Shell a veces tenemos la necesidad de manejar claves, para lo que tenemos que por ejemplo para leer una clave y que aparezcan los típicos asteriscos, cada vez que pulsamos una tecla hacemos:

$psw = Read-Host "Ingrese la clave" -AsSecureString


Donde, con  "-AsSecureString" le indicamos que guarde lo ingresado en un string seguro. Bueno, ahora si ponemos

Write-Host $psw


vemos que la respuesta es

System.Security.SecureString


Lo cual nos deja un poco perplejos, para ver el valor ingresado debemos hacer

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($psw)

Write-Host [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)


...lo que nos mostrará la clave ingresada por el usuario.

miércoles, 15 de mayo de 2013

PowerShell: Búsqueda Binaria en arrays de objetos personalizados

El problema del IComparer

Siguiendo con el tema de la búsqueda rápida (haciendo búsqueda binaria), en éste artículo ya había encontrado cómo hacer una búsqueda binaria sobre un ArrayList desde Power Shell, pero al complicar un poco el tema, usando arreglos de objetos propios encontré un problema...
El problema es que al ser objetos propios debemos indicarle sobre qué campo hacer la búsqueda y cómo se ordenan los objetos... El mismo problema tenemos al ordenar (hacer un sort) sobre un Array o ArrayList.
Veamos a un ejemplo, tenemos un ArrayList de objetos Empleado, con atributos Nombre, Apellido, Legajo... por ej uso esta funcion para crearlos:

function Nuevo-Empleado(){
    param ($Nombre, $Apellido, $Codigo)
   
    $empleado= New-Object PSObject
   
    $empleado| Add-Member -type NoteProperty -Name Nombre -Value $Nombre
    $empleado| Add-Member -type NoteProperty -Name Apellido -Value $Apellido
    $empleado| Add-Member -type NoteProperty -Name Legajo -Value $Codigo

    return $empleado
}

Y supongamos que los cargamos de un archivo csv desordenado y queremos buscar por nro de legajo...

[System.Collections.ArrayList] $listaEmpleados = New-Object System.Collections.ArrayList
$listaEmpleados =  Import-Csv  -h Nombre, Apellido, Codigo
$listaEmpleados = $listaEmpleados | sort Codigo # ordeno por codigo


Ahora el tema es.. cómo hace para ordenar por  código... bueno, supongamos que código es string... luego, para poder hacer el BinarySearch...

La función de comparación

$src = @'

using System;
using System.Collections;
using System.Management.Automation;

   public sealed class ScriptBlockComparer : IComparer
   {
      ScriptBlock _Comparer;
      
      public ScriptBlockComparer(ScriptBlock Comparer) { ComparerScript = Comparer; }
      
      public ScriptBlock ComparerScript
      {
         get { return _Comparer; }
         set { _Comparer = value; }
      }
      
      public int Compare(object x, object y)
      {
         try {
            return (int)ComparerScript.Invoke(x, y)[0].BaseObject;
         } catch(Exception ex) {
            throw new InvalidOperationException("Comparer Script failed to return an integer!", ex);
         }
      }
      
   }
   
'@

Add-Type -TypeDefinition $src -Language CSharpVersion3

$cmp = New-Object ScriptBlockComparer {
    Param($primero, $segundo)
    $pos = $primero.Codigo.CompareTo($segundo)
   
    return $pos
}



.......
..........
mas codigo
...........
... y...

$pos = $list.BinarySearch($codigoABuscar, $cmp)


Y nos devuelve en pos la posición del elemento buscado en el array (empezando desde 0) y un nro <0 si no se encontró. Espero les sirva de ayuda!

Nota: si les tira error con la version de .Net  pueden intentar cambiar
Add-Type -TypeDefinition $src -Language CSharpVersion3
Por:
Add-Type -TypeDefinition $src -Language CSharp
Ya que espera tener instalado el Framework .Net versión 3.5

lunes, 6 de mayo de 2013

Sonidos desde power shell


Con estas 4 líneas de abajo puedo ver dos cosas importantes en Power Shell,
  • ... una es resolver el path relativo a un archivo, como se ve,
    resolve-path .\warning.wav deja en $advertencia el path del archivo warning.wav, dentro del directorio en el que estamos trabajando.
  • ... la segunda, es como escuchar un sonido de un archivo wav


$advertencia = resolve-path .\warning.wav
$sound = New-Object System.Media.SoundPlayer
$sound.soundLocation = $rango
$sound.Play()


Hacer sonar algunos sonidos del sistema...

[System.Media.SystemSounds]::Asterisk.Play();
[System.Media.SystemSounds]::Beep.Play();
[System.Media.SystemSounds]::Exclamation.Play();
[System.Media.SystemSounds]::Hand.Play();
[System.Media.SystemSounds]::Question.Play(); 




Búsqueda rápida en Power Shell

Problema

Se debe hacer una búsqueda en power shell en una gran cantidad de datos, digamos un archivo de texto con 200 mil registros, de a uno por línea. La búsqueda común en powershell tarda mucho.

Solución

Se realiza la búsqueda utilizando ArrayLists (System.Collections.ArrayList)


clear
#leo el archivo
$db = get-content miArchivo
 
#cargo el contenido del archivo en un ArrayList
[System.Collections.ArrayList] $list = New-Object System.Collections.ArrayList 
 
foreach ($item in $db){
    [void] $list.Add($item)
} 
 
#ordeno el archivo (sin esto no funciona la búsqueda binaria)
$list.Sort()

$reg = Read-Host "Ingrese el registro a buscar"
$pos = $list.BinarySearch($reg)
if ($pos -ge 0){
    Write-Host "El registro se encuentra en la posición: " + $pos
}else{
    Write-Host "No se encuentra el registro"
}

Más info en:

ArrayList (sort)

viernes, 3 de mayo de 2013

Problema de permisos Power Shell

Al tratar de ejecutar un power shell por primera vez suele tirar algunas veces

File  cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.


El problema se soluciona abriendo la consola power shell con usuario administrador y corriendo las siguientes líneas

Set-ExecutionPolicy Unrestricted
Set-ExecutionPolicy RemoteSigned


Ambas solicitan confirmación.

jueves, 10 de enero de 2013

Mouse click en PowerShell

Tuve que recorrer media internet para encontrar finalmente como hacer un click del mouse con  Power Shell sin tener que usar otros programas externos. Así que acá finalmente pude armar una función que hace clicks del mouse en la posición indicada de la pantalla...

# Ejecuta un click del mouse
function MouseClick ($Button = "left", $x, $y, $cant = 1){
    $signature = @'
          [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
          public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'@
    [Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y);
    $SendMouseClick = Add-Type -memberDefinition $signature -name "Win32MouseEventNew" -namespace Win32Functions -passThru 
    for ($i = 1; $i -le $cant; $i++){
        if($Button -eq "left"){
            $SendMouseClick::mouse_event(0x00000002, 0, 0, 0, 0);
            $SendMouseClick::mouse_event(0x00000004, 0, 0, 0, 0);
        }
        if($Button -eq "right"){
            $SendMouseClick::mouse_event(0x00000008, 0, 0, 0, 0);
            $SendMouseClick::mouse_event(0x00000010, 0, 0, 0, 0);
        }
        if($Button -eq "middle"){
            $SendMouseClick::mouse_event(0x00000020, 0, 0, 0, 0);
            $SendMouseClick::mouse_event(0x00000040, 0, 0, 0, 0);
        }
    }
}



lunes, 7 de enero de 2013

Tips PowerShell


  • Para ejecutar desde la consola DOS usar: powershell <path del script> o bien powershell .\nombre_del_script.ps1 en caso que esté en el mismo directorio.
  • Los comentarios dentro de los script se inician con numeral (#)
  • Algunas funciones útiles
    • Escribir texto en colores por la consola DOS: 
      • Escribir una línea en color: Write-Host "Texto rojo en fondo verde" -foregroundcolor red -backgroundcolor green
      • Cambiar los colores de la consola: $HOST.UI.RawUI.BackgroundColor = "Black"
        $HOST.UI.RawUI.ForegroundColor = "Red"
    • Para detener la ejecución del programa: Start-Sleep -m 10000 si se usa -m se refiere a milisegundos, si se quieren usar segundos se usa -s (ej Start-Sleep -1 10 es equivalente al ejemplo anterior)
  • Para concatenar strings se usa el signo +
  • Para invocar programas se usa &, por ejemplo & "C:\Program Files\Winamp\winamp.exe" abrirá el winamp. 
    • o bien $winamp = "C:\Program Files\Winamp\winamp.exe"
      & $winamp 
  • Para escribir comandos multilínea se usa el acento invertido `, ejemplo 
                    $msg = "mi mensaje empieza en esta línea " + [Environment]::NewLine  `

                              + "... y sigue en esta segunda línea"
  • [Environment]::NewLine  es el caracter de nueva línea
  • Apagar y reiniciar
    • Stop-Computer para apagar la computadora 
    • Restart-Compute para reiniciar 
    • Ambos se pueden usar con la opción -computer "nombrepc1, nombrepc2, nombreotrapc, etc " -force para apagar o reiniciar computadoras que se encuentren en la red.
  •  Operaciones con archivos
    • Borrar: Remove-Item c:\borrame.txt
    • Copiar: Copy-Item  Origen Destino
    • Escribir en archivo: "escribime en archivo" > c:\archivo.txt
  • Operadores de comparación
    • -eq: igual
    • -ne: distinto
    • -gt: mayor
    • -ge: mayor o igua
    • -lt: menor
    • -le: menor o igual
    • -like: comparacion entre caracteres
    • -notlike: -like negado
    • -match: Que machee el segundo operando
    • -notmatch: -match negado
  • Operadore lógicos
    • -and: and lógico
    • -or: or lógico
    • -not: not lógico
  • Finalizar la ejecución del programa: exit 
  • Variables de error (PowerShell utiliza varias variables globales para guardar estados de error y otras informaciones importantes) aquí algunas:
    • $? contiene el estado de ejecución de la última operación. True indica que todo salio Ok, false indica que hubo error o ejecución parcial (se basa en el exit code de los programas windows, un exit code 0 debería indicar que todo termino ok, cualquier valor distinto de 0 indicaría error, pero no todos los programas respetan esta convención, ver $LASTEXITCODE).
    • $LASTEXITCODE guarda el código de salida de la ejecución de la última operación, sirve para interpretar la salida de programas que no respeten la convención de exit code diferente de 0 para ejecuciones con errores o no completas (ver el punto anterior).
    • $Error ArrayList de los errores ocurridos en la sesion, los nuevos errores se agregan al principio del arraylist, dejando el último error en posición 0.
  • Otras
    • $true es true
    • $false es false
    • $null es un objeto null
    • $_ el objeto actual (por ejemplo en un foreach-object o en un where-object, etc)
    • Para obtener la fecha y hora: get-date -format u


    Try, catch, finally en PowerShell

    Acá les dejo un ejemplo de try - catch - finally en powerwhell que me fue de utilidad



    
    try
    {
        $ErrorActionPreference = "Stop"; #esto se hace para que stopee en los errores
        Copy-Item file_origin file_dest #copio un archivo
    }catch{
        Write-Host $Error[0].exception # muestro el mensaje de error
        $ErrorActionPreference = "Continue"; #vuelvo a setear la acción por defecto en los errores
        Exit # Termino la ejecución si hubo error
    }finally{
       $ErrorActionPreference = "Continue"; #vuelvo a setear la acción por defecto en los errores
    }
    

    :-)

    Power Shell - ¿Cómo llamar a una función que está en otro script?

    Bueno, acá explico como llamar desde un script PowerShell (ps1) a una función que se encuentra en otro script...
    Supongamos que tenemos los script funciones.ps1 y principal.ps1, siendo:

    funciones.ps1:
    Function test(){
        Write-Host "Dentro de la funcion"
    }
    


    Para llamar a la funcion test desde principal.ps1 se hace
    . .\funciones.ps1 # acá incluyo al script funciones.ps1
                      # notar que hay un espacio entre . y .\funciones.ps1
    
    #luego llamo a la función
    test
    


    En el ejemplo estoy llamando al script de forma relativa, suponiendo que están en el mismo directorio, si no fuera así habría que hacer algo tipo ". C:\<path del script funciones.ps1>\funciones.ps1...

    Espero que les sea de utilidad....