miércoles, 4 de diciembre de 2013

Modo compatibilidad o cambio de resolución en aplicación vía command line

 

Hola.

Se me ha presentado una necesidad y la solución es simple aunque un tanto rebuscada.

Ante la necesidad de marca el modo compatibilidad en un archivo .exe una vez instalada la aplicación, solo tenéis que usar el comando siguiente con sus variables:

set __COMPAT_LAYER= MODEXX  RESOLXXX   “c:\program files\aplicacion\aplicacion.exe”

En mi caso:

set __COMPAT_LAYER= WINSRV03SP1  640X480   “c:\program files\aplicacion\aplicacion.exe”

Las posibilidades son:

Windows 95 = WIN95

Windows 98 / Windows Me = WIN98

Windows NT 4.0 (Service Pack 5) = NT4SP5

Windows 2000 = WIN2000

Windows XP (Service Pack 2) = WINXPSP2

Windows XP (Service Pack 3) = WINXPSP3

Windows Server 2003 (Service Pack 1) = WINSRV03SP1

Windows Server 2008 (Service Pack 1) = WINSRV08SP1

Windows Vista = VISTARTM

Windows Vista (Service Pack 1) = VISTASP1

Windows Vista (Service Pack 2) = VISTASP2

Windows 7 = WIN7RTM

256 colors = 256Color

640 x 480 screen resolution = 640x480

Disable visual themes = DISABLETHEMES

Disable desktop composition = DISABLEDWM

Disable display scaling on high DPI settings = HIGHDPIAWARE

Saludos.

miércoles, 6 de noviembre de 2013

Crear .adm “templates” personalizados

 

Hola.

Pocas son las veces que utilizamos la posibilidad no de importar y exportar archivos .adm para añadir contenido a nuestras gpos en AD, sino que además creamos esos adm para modificar parámetros que en muchas ocasiones preferimos modificar vía script en log on, etc.

Sin embargo, todo administrador de AD elegiría la posibilidad de llegar vía gpo ya que por ejemplo, nos olvidamos de equipos que conectan por vpn y otras circunstancias a las que vía log on no llegamos y tenemos que ir creando tareas programadas y demás.

En este artículo, pretendo daros una nociones básicas de como crear vuestros propios archivos .adm para que pudieseis incluso crear una gpo general con modificaciones de diversos programas, donde, por ejemplo, podamos tener tanto la directiva de contraseñas como la personalización de los adobe reader que hay en todo equipo de la empresa.

CONCEPTOS

Antes de nada comentar que prácticamente todo se basa en la modificación del registro y para ello tenemos que tener bien claro la existencia  de los arboles “Hkey_local_machine” y Hkey_current_user” los cuales tiene prácticamente un reflejo directo en las directivas de equipo y usuario que sabéis, existen en cada gpo.

En relación a lo que tenemos entre manos, vamos a trabajar con estos conceptos básicos:

1. Class

2. Category

3.Policy

4.Keyname

5.Valuename

Los archivos que se importan en la consola de administración de directivas de grupo, tienen la extensión .adm y estos archivos los podéis generar simplemente con notepad, guardando no como texto si no como archivo sin formato y escribiendo tras el nombre, la extensión .adm.

 

EJEMPLO 1

En las capturas siguientes, podéis ver ejemplos y entender donde se ubica cada uno de estos “items”

image

image

 

Por tanto una estructura básica podría ser:

Class “clase”

    Category “Policy”

        Keyname “keyname”

        Valuename “Valuename”
        Valueon numeric 0
        Valueon numeric 1

    End Policy

End Category

 

Si además quisiéramos incluir texto en la solapa “Explain” tendríamos que poner al final del texto:

[strings]
policy = “texto”

Esto lo guardaríamos como archivo template.adm y luego lo importaríamos como se ve la siguiente captura:

(Consola de administración de directivas de grupo)

image

EJEMPLO 2

Un ejemplo más claro pero más complejo se muestra a continuación, en él, crearemos una directiva para adobe que nos modifica una clave del registro:

image

image

 

CLASS USER
    CATEGORY !!Adobe10Header
        CATEGORY "Adobe Reader 10"
            CATEGORY "Preferences"
                    CATEGORY "General"
                        CATEGORY "Application Startup"
                                POLICY "Show splash screen"
                                    KEYNAME "Software\Adobe\adobe acrobat\10.0\Originals"
                                    EXPLAIN !!ExplainNosplash
                                    VALUENAME "bDisplayedSplash"
                                    VALUEON NUMERIC 0
                                    VALUEOFF NUMERIC 1
                                END POLICY

                        END CATEGORY
                    END CATEGORY
            END CATEGORY
        END CATEGORY
    END CATEGORY

[strings]
Adobe10Header=Adobe 10
ExplainNosplash="When disabled, the program will not display a splashscreen on startup.\n\nWhen enabled, the splashscreen will be displayed."

El resultado es:

image

image

 

En vez de:

VALUENAME "bDisplayedSplash"

VALUEON NUMERIC 0

VALUEOFF NUMERIC 1

 

Podemos tener claves del tipo:

VALUENAME “path”

VALUE “c:\temp\imagen.bmp”

 

También podríamos poner un texto con el comando “PART” que iría en la tabla de texto, esto sería así:

PART “texto”

VALUENAME "bDisplayedSplash"

VALUEON NUMERIC 0

VALUEOFF NUMERIC 1

También podemos necesitar un DROPDOWNLIST tras el texto para lo que tendríamos que poner:


PART “Default Dictionary” DROPDOWNLIST

ITEMLIST
    NAME "English (United Kingdom)" VALUE "English (United Kingdom)"
    ACTIONLIST
        KEYNAME "Software\Adobe\Acrobat Reader\10.0\Spelling"
        VALUENAME "iDictionaryDefaultID" VALUE NUMERIC 7
    END ACTIONLIST
    NAME "English (United States)" VALUE "English (United States)"
    ACTIONLIST
        KEYNAME "Software\Adobe\Acrobat Reader\10.0\Spelling"
        VALUENAME "iDictionaryDefaultID" VALUE NUMERIC 2
    END ACTIONLIST
END ITEMLIST

image

 

O por ejemplo un simple CHECKBOX que sería:

PART “Texto” CHECKBOX

VALUENAME “Valuename”

VALUEON NUMERIC 0

VALUEOFF NUMERIC 1

 

Bueno y si buscáis más por internet vais a encontrar mucho. Yo os invito a que analicéis archivos .adm muy útiles como son:

Adobe

http://www.adobe.com/devnet-docs/acrobatetk/tools/AdminGuide/gpo.html#x-gpo-deployments.

Google Chrome

https://support.google.com/chrome/a/answer/187202?hl=es

 

Saludos.

miércoles, 14 de agosto de 2013

BranchCache Distributed 2/3

 

La descripción de funcionamiento de BranchCache en modo distribuido sería la siguiente.

Escenario:

1. Servidor Windows Server 2008 R2 con rol de servidor de ficheros, carpeta compartida y en esta última, tenemos marcada la opción de BranchCache o si se trata de http, debemos tener publicado la carpeta donde se almacena la web.

2. Equipo cliente A con Branchacache activado vía gpo o en gpedit local y reglas de firewall en modo permitido.

3. Equipo cliente A, tiene configurado mediante gpo o gpedit local, el tiempo de corte por el cual, si el servidor funciona más lento del tiempo establecido, el archivo se cacheará y será ofrecido a otros pcs de la Lan.

3. Equipo cliente B igual a equipo cliente A.

 

Funcionamiento:

1. El equipo cliente A, solicita a servidor los identificadores del archivo que necesita. Esta solicitud puede ser Http, bits o smb, mediante también https o ipsec.

2. El cliente A, busca en local y en su LAN mediante WS-Discovery, en este primer uso, el archivo nunca ha sido descargado.

3. El cliente A, descarga el archivo desde el servidor.

4. El cliente B, solicita a servidor los identificadores del archivo que necesita. Esta solicitud puede ser Http, bits o smb mediante también https o ipsec.

5. El cliente B, busca en local y en su LAN mediante WS-Discovery. En este segundo uso, el archivo previamente ha sido descargado por el Cliente A.

6. El cliente B, comprueba que la comunicación con el servidor es mayor y por tanto más lenta en milisegundos que lo establecido en la gpo o gpedit local.

6. El cliente A, ofrece a cliente B el archivo.

Hasta aquí, la descripción de como funciona el servicio.

 

Configuraciones

Servidor:

1. Instalar característica File server y  Branchcache.

2. Directiva de equipo local o gpo – Equipo – Plantillas administrativas – Red – Servidor lanman –Publicación de hash para BranchCache – Habilitado y elegir una de las opciones, yo prefiero – Permitir publicación de hash para shares con branchcache habilitado.

SMB

1. Activar rol de servidor de ficheros.

2.Compartir una carpeta

3. Propiedades – compartido – avanzado – cacheado – marcar “Enable BranchCache”.

SMB en clúster

Si vais a utilizar smb en clúster, tenéis que lanzar en todos los nodos el siguiente comando: netsh branchcache set key passphrase=“frase secreta”, debéis repetir la misma frase en todos los nodos.

HTTP

1. Lanzar CMD como adminsitrador

2. publish-bcwebcontent (ruta de la web: ej.c:\inetpub\wwwroot )

 

Equipos cliente:

1. La gpo o gpedit local en los equipos cliente deben tener configurado:

  1. Ir a Computer\Plantillas administrativas\network\BranchCache
  2. Activar BranchCache – Enable
  3. Establecer el modo Caché distribuida de BranchCache – Enable
  4. Configurar BranchCaché para archivos de red – 0ms. si queremos cachear siempre o más milisegundos si queremos un tiempo de corte.
  5. Establecer el porcentaje de espacio en disco usado por la memoria caché del equipo cliente – Cifra en porcentaje

2. Configuración de Firewall:

  1. Firewall de windows con seguridad avanzada
  2. Reglas de entrada-botón derecho-nueva regla-predefinida- BranchCache: detección del mismo nivel (usa WSD) y BranchCache: recuperación de contenido (usa HTTP).
    Si se trata de un pequeño número de equipos, también podéis lanzar el comando : netsh branchcache set service mode=Distributed, el cual os lo configurará todo, aunque siempre, la configuración llegada mediante gpo, tendrá prioridad.

Tras esta configuración, podemos lanzar en un cmd como administrador y consultar si todo está ok, gracias la comando netsh branchcache show status all, donde también podéis ver la cantidad de información cacheada en el equipo.

 

Probar Branchcache

Para probar la configuración y funcionamiento de BranchCache, solo tendrías que:

1. Instalar un emulador de linea, por ejemplo:

NetworkEmulatorToolkit_x32
NetworkEmulatorToolkit_x64

2. Instalar este emulador en el servidor , configurar y en los filtros configurar una latencia mayor que la configurada en la gpo de los equipos cliente (Equipos cliente punto 1.4).

3. Copiar a local en Equipo A o descargar de una web un archivo y observar el tiempo que tarda en finalizar el proceso.

4. Realizar el mismo proceso en Equipo B. El tiempo ha e ser considerablemente menor porque Equipo A ha de ser quien entrega los datos, contando con una latencia mínima en Lan.

BranchCaché en todo proyecto de centralización de datos en Cloud 1/3

Hola.

Este es el primero de varios artículos donde pretendo hablar de BranchCaché en un claro ejemplo de uso, una migración de datos actualmente descentralizados a una cloud privada centralizada. Este primer artículo nos pondrá en situación y describirá las partes importantes ante la toma de decisiones en la fase de diseño.

BranchCaché en todo proyecto de centralización de datos en Cloud 1/3

Dos proyectos combinados en los que estoy metido, tienen como fin el diseño y ejecución de una migración de file servers localizados en más de mil “sites” a una cloud privada. Se pretende consolidar y explotar al máximo las ventajas propias de la centralización de datos. Esto conlleva la combinación de un proyecto de migración y otro en paralelo, donde diseñamos y creamos un clúster contando con las mejoras ofrecidas por los roles de File Server y Storage de WS2012. Además de otros que no vienen tan a cuento pero que también son imprescindibles, como la creación de una CA Corporate.

Pues bien, centrándonos en el primero de ellos y contrariamente a lo que se puede pensar, el éxito de ese proyecto, no se basa tanto en los extremadamente importantes procedimientos de migración o en el estudio y mejora de anchos de banda, sino que la parte imprescindible en este proyecto se llama aceleración y en nuestro caso, la encontraemos gracias a BranchCache. Podemos resumirlo en que cualquier ancho de banda posible actualmente, no sustituirá nunca al antiguo servidor situado en la lan y dado esto, se asume cierta lentitud en algunos momentos versus ahorro y seguridad de datos, pero, para minimizar, incluso evitar esta lentitud, pongamos un servidor que haga funciones de hosted ya que además, este puede caer, ser formateado o reemplazado rápidamente sin correr grandes riesgos.

Dicho esto, es importante conocer el rol (http://technet.microsoft.com/en-us/network/dd425028.aspx) y su encaje en el escenario.

Bases:

1. Podremos utilizar Windows Server 2008 r2 o Ws2012 en los servidores pero Windows 7 en equipos cliente.

2. Podríamos utilizar sites con Caché distribuida o Hosted Caché (recordamos que el fin del proyecto es consolidar y por tanto, apagar la mayor cantidad de servidores de site posibles).

3. Anchos de banda limitados y no mejorables en multitud de sites.

4. Diferentes subredes en ciertas redes (Branchcaché distributed, solo cachea información entre equipos en la misma subred).

5. Hosted Caché en Ws2008R2 ya nos permite pre cachear información en el servidor previo a su puesta en producción.

6. Windows 7, al contrario de Windows 8, no detecta automáticamente al servidor hosted de la sede, por lo que se prone ligar una gpo con el servidor por cada site.

7. Hosted Caché se basa en la seguridad ofrecida por certificados de servidor, por lo que tenemos que contar con una CA Corporate.

8. Los servidores hosted ws2012 y Ws2008R2 pueden ser detectados automáticamente por futuros w8, por lo que se podría habilitar esta opción aun no siendo explotada actualmente.

9. Ante oscilaciones en las velocidades de conexión, se pretende cachear la mayor cantidad de información, independientemente al retardo con el servidor central.

Tras conocer todo esto, iremos desgranando como funciona y la puesta en marcha de BranchCaché distribuido y sobre todo Hosted, que es el que nos costará un poco más de montar.

Saludos.

miércoles, 7 de agosto de 2013

Configuración de BranchCaché web y smb, hosted en WS2008 R2 en adelante

Hola.

El siguiente paso a paso, configura Branchcaché en nuestra red, aprovechando incluso las nuevas funcionalidades de ws2012 y Windows 8, gracias las cuales, el equipo cliente utiliza el servidor hosted más próximo a él.

 

Entorno:

Servidor DC, web y smb

Server1, en dominio, será hosted server y cliente

Server2, en dominio, será, hosted server y cliente

 

Configuración:

1. Crear una gpo con nombre BranchCache clientes, por ejemplo.

  • Ir a computer configuration\policies\administrative templates\network\branchcache
  • Habilitar las siguientes opciones: “ turn on BranchCache”, “Set BranchCache Distributed Cache Mode” y “Enable Automatic Hosted Cache Discovery by Service Connection Point”.
  • Ir a Computer Configuration\Policies\windows Settings\Security settings\windows Firewall with Advanced Security\windows firewall with advanced security\…inbound rules
  • Nueva regla – Predefinida – Branchcache- content retrieval (uses http).
    Filtrar la gpo para que solo se aplique a ordenadores cliente donde queremos que utilicen BranchCache
    2.Instalar la caraterística de BranchCache en los servidores hosted, para ello:
  • Comando powershell: get-windowsfeature BranchCache | install-WindowsFeature
  • Si tenéis varios servidores podéis: invoke-command –computername server1,server2,dc –scriptblock{y el comando que he puesto antes}

3. Configurar por ejemplo la carpeta de web server para las primeras pruebas:

  • publish-bcwebcontent c:\inetpub\wwwroot (o la ruta donde tengáis la web en cuestión).

4. Configurar el/los hosted cache server, en mi caso lo haré en server1 y server2:

  • enable-bchostedserver –registerscp
  • gpupdate /force
  • get-service peerdistsvc | restart-service

A partir de este momento ya se puede realizar una prueba, por ejemplo, bajando un archivo de http://dc/archivo.iso (por ejemplo). Para que las pruebas confirmen el funcionamiento, lo mejor sería utilizar un limitador de ancho de banda en el dc y comprobar que la primera descarga desde server1 es muy lenta y luego, desde server2, la misma descarga se realizar prácticamente de inmediato.

Una vez configurado todo esto, si queréis que una carpeta se cachee, solo tenéis que marcar la opción al respecto en las propiedades de esta.

martes, 6 de agosto de 2013

Ruta alternativa para la instalación de componentes en W8, WS2012 y WS2012 R2

Hola.

En su día ya traté por aquí, el hecho de que no todas los componentes vengan almacenados en el propio sistema operativo a la espera de ser activados; eso ocurre en W8, WS2012 y WS2012R2.

El ejemplo es claro, prácticamente lo primero que encontramos cuando queremos instalar algún rol es la necesidad de contar con .net framework y este, se descarga online, algo que normalmente, nuestros servidores no pueden realizar.

Para remediar esto de forma profesional en un entorno al menos mediano, lo suyo es crear una directiva que nos ayude, para ello, basta con seguir los siguientes:

1.Crear una directiva e ir a la ruta:

image

Computer configuration\administrative Templates\system\Specify settings fo optional component installation and component repair

2.Activar la opción y en “Alternate source file path” podemos:

2.1 Simplemente utilizar la ruta de un share, donde habremos guardado los archivos del iso; ejemplo: \\nas\share

2.2 Utilizar un share donde hemos guardado el archivo wim e indicarlo todo, ejemplo: wim:\\nas\share\install.wim:3.

En mi caso he usado la opción 1 ya que la 2 viene perfectamente detallada en la ayuda:

image

Además, también podéis personalizar la opción contando con las opciones “never attempt to download payload from windows update” o “contact Windows Update directly to download repair content…”, las cuales están perfectamente explicadas en la parte de la ayuda de la propia opción.

Saludos.

viernes, 28 de junio de 2013

Conocer el lenguaje del sistema operativo en un equipo vía powershell

Hola.

Con el siguiente script, tendréis en la variable $code el resultado de la consulta del tipo de lenguaje del sistema operativo.

$solenguaje = Get-WmiObject Win32_OperatingSystem

$code= switch($solenguaje.oslanguage){

default {“Unknown”);

3082 {“Spanish”};

1033 {“English”}

}

Esta información se basa en estos códigos de lenguaje:

http://www.science.co.il/language/Locale-Codes.asp

Saludos.

miércoles, 26 de junio de 2013

Comportamiento y scripts de inicio de imagen con Sysprep

Hola.

Dos rutas para muchos desconocidas y para otros ultra mega super utilizadas, existentes en sistemas operativos Microsoft, han sido creadas con la intención de albergar los archivos con el script a acometer durante el primer arranque tras despertar de un sysprep.

La primera de las dos, es la ruta %WINDIR%\Panther\unattend\ donde albergaríamos el archivo unattend.xml creado con la herramienta Windows System Image Manager, disponible gratuitamente y que forma parte de las herramientas WAIK ( http://www.microsoft.com/en-us/download/details.aspx?id=5753).

Al albergar en esta ruta el archivo nombrado, el equipo al despertar, irá contestando cada una de las típicas preguntas de inicio de Windows sin que el usuario tenga que interactuar y pudiendo así, asegurarnos que todo nuestro parque obtiene la misma configuración.

La segunda de las dos rutas es %WINDIR%\Setup\Scripts\ donde alojando un archivo con nombre setupcomplete.cmd, provocamos que el sistema, durante el primer inicio que realice, ejecutará cada una de las acciones allí almacenadas, como por ejemplo el test de Aero para tener una experiencia gráfica completa o la llamada a un script .vbs donde suele ser habitual cambiar el nombre dele quipo para que nuestro parque cuente con un patrón de nombres similar y típico también es, encontrar un  “joindomain” para introducir el equipo en dominio en el primer arranque.

Ejemplo:

Setupcomplete.cmd

cscript %windir%\system32\oobe\prestage\RenameAndJoinDomain.vbs

REM Aero test
winsat.exe formal

REM aquí podríamos forzar también bitlocker.

manage-bde -on c: -skiphardwaretest –recoverypassword

REM es importante borrar el unattend.xml porque puede contener información importante como nuestra clave de Windows

del /f /q %WINDIR%\Panther\unattend\unattend.xml

shutdown /r /f /t 5

Para que nuestro despertar sea correcto, previamente, al finalizar la instalación del equipo modelo y tras instalar todos los componentes que queremos en nuestra maqueta corporativa y  por ejemplo también, drivers que no incluya el sistema por defecto y que van a ser dispositivos que podría encontrar nuestro equipo al despertar, tenemos que “dormir” el sistema. Para ello, podemos crear un script como por ejemplo el siguiente:

Sysprep.cmd

copy /y .\unattend.xml %WINDIR%\Panther\unattend\unattend.xml
copy /y  .\setupcomplete.cmd %WINDIR%\Setup\Scripts\SetupComplete.cmd

%WINDIR%\system32\sysprep\sysprep.exe /oobe /generalize /shutdown 

Sysprep : http://technet.microsoft.com/es-es/library/cc721940(v=ws.10).aspx

Tras la realización de estos pasos, podéis clonar el disco tal y como muchos me habéis dicho que soléis hacer pero con la imagen sin sysprep, lo cual no es nada aconsejable por cierto y diría que totalmente inviable si hablamos de equipos en dominio.

En una posterior entrada, hablaré de como convertir esta imagen en un archivo .wim y como desplegar manipular ese archivo posteriormente hasta el punto del despliegue.

Saludos.

Introducir a un usuario en grupo de administradores locales

Hola.

Puestos a publicar scripts, os publico uno rápido que tengo hecho y aunque es mejorable :). Es válido perfectamente en una empresa donde se pasa por un filtro el que un usuario sea administrador de su equipo o no:

$strDomain = "dominio"
$strComputer = Read-Host "Ordenador"
$strUser = Read-host "Usuario"

$computer = [ADSI]("WinNT://" + $strComputer + ",computer")
$group = $computer.psbase.children.find("Administradores")
$group.Name

function ListAdministrators

{$members = $group.psbase.invoke("Members") | %{$_.GetType().InvokeMember("Name",'GetProperty',$null,$_,$null)}
$members}

$group.Add("WinNT://" + $strDomain + "/" + $strUser)
ListAdministrators

 

La penúltima línea, la podéis modificar y crear un script con :

$group.Remove("WinNT://" + $strDomain + "/" + $strUser)

Para que el script pase a borrar el usuario del grupo.

Advierto que es muy mejorable, por ejemplo el hecho de que busque la cadena “Administradores”, ya que si el s.o. está en inglés ya la cadena es “Administrators”, pero bueno, siempre se puede hacer un if y esa clase de cosas.

martes, 25 de junio de 2013

Script completo para preparar equipo y lanzar Bitlocker.

Hola.

Hago público el script del que os he hablado estos días.

Este Script, está hecho para que encuentre los portátiles como los encuentre, vaya mandando el comando correspondiente e irá preparando el equipo hasta lanzar el comando que cifra la unidad C:. No hace falta decir que se puede llevar al logonscript del dominio o como es mi caso, lanzarlo de forma continuada en los próximos logon vía SCCM.

Cabe destacar, que para mi, es importante que se apliquen los cambios en la gpo del dominio para que se almacene la clave de bitlocker en directorio activo.

Por partes:

#Comprobamos que la partición de boot está creada por debajo del tamaño Default ya que también se suele crear de 100mb.

    if( $Partitionstatus.size -gt 314572800) { 
        VENTANAPARTREINICIO
        bdehdcfg -target default -restart -quiet
    } 

#comprobamos que hay conectividad con alguno de los DCs antes de lanzar el cifrado ya que las directivas nos obligan a guardar la clave de bitlocker (de todas formas, no habiendo conectividad no funcionaría porque la directiva así lo ordena).

Function CONEXIONREDCIFRADODISCO
{
    $Ping1DC = Test-Connection "!DC1" -Count 1 -Quiet
    $Ping2DC = Test-Connection "!DC2" -Count 1 -Quiet
    if (($Ping1DC -eq $true) -or ($Ping2DC -eq $true)) {
        VENTANANOREINICIO
        manage-bde -on c: -skiphardwaretest -recoverypassword
    }

}

#Comprobamos que el equipo forma parte del dominio, que bitlocker no cifra ya el disco, que la partición es menor y que el equipo es un portátil.

If (($compconfig.domain -eq "!dominio.local") -and ($bitlockstatus -ne "1") -and ($Partitionstatus.size -le 314572800) -and ($tipoequipo -eq "2")) {

 

#----------------------------------------------------------------------------------
#Script para preparar equipos portátiles y lanzar bitlocker en unidad c:
#
# Realizado por Miguel Hernández
#
#Para personalizar este script ha de buscar el signo ! .
#----------------------------------------------------------------------------------

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$tpm = Get-WmiObject -class Win32_Tpm -namespace "root\CIMV2\Security\MicrosoftTpm"
$BitLockDrive = get-wmiobject -namespace root\CIMv2\Security\MicrosoftVolumeEncryption -class Win32_EncryptableVolume -filter "driveletter='c:'"
$Partitionstatus= Get-WmiObject Win32_DiskPartition -filter "bootpartition='True'"
$CompConfig = Get-WmiObject -Class Win32_ComputerSystem

##obtenemos el tipo de equipo = 1 {"Desktop"},2 {"Laptop"},3 {"Workstation"},4 {"EntServer"},5 {"SmallOfficeOrHomeServer"},6 {"AppliancePC"},7 {"PerformanceServer"},8 {"Maximum"},default {"NoConocido"}
$tipoequipo = $CompConfig.PCSystemType

#Obtenemos la información de si bitlocker ya cifra la unidad
$bitlockstatus = $BitLockDrive.protectionstatus

#-------------------------------------------------------------------------------
#Funciones
#-------------------------------------------------------------------------------

function VENTANAPARTREINICIO
{

#Ventana Form donde se comunica el reinicio

$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "IT Department."
$objForm.Size = New-Object System.Drawing.Size(300,220)
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(80,150)
$OKButton.Size = New-Object System.Drawing.Size(120,25)
$OKButton.Text = "Accept"
$OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()})
$objForm.Controls.Add($OKButton)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,10)
$objLabel0.Size = New-Object System.Drawing.Size(280,30)
$objLabel0.Text = "Como parte del proceso de cifrado se va a preparar la unidad de disco de este equipo."
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,45)
$objLabel1.Size = New-Object System.Drawing.Size(280,30)
$objLabel1.Text = "Por favor, cierre todo los programas abiertos ya que al finalizar este proceso el ordenador se reiniciará."
$objForm.Controls.Add($objLabel1)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,85)
$objLabel0.Size = New-Object System.Drawing.Size(280,30)
$objLabel0.Text = "As part of Encrypting process it will be prepared the computer's hard drive."
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,115)
$objLabel1.Size = New-Object System.Drawing.Size(280,30)
$objLabel1.Text = "Please close all your opened programs because the computer will be restarted."
$objForm.Controls.Add($objLabel1)

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

}

function VENTANAREINICIO
{
#Ventana Form donde se comunica el reinicio

$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "IT Department."
$objForm.Size = New-Object System.Drawing.Size(300,220)
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(80,150)
$OKButton.Size = New-Object System.Drawing.Size(120,25)
$OKButton.Text = "Accept"
$OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()})
$objForm.Controls.Add($OKButton)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,10)
$objLabel0.Size = New-Object System.Drawing.Size(280,30)
$objLabel0.Text = "Se va a proceder a la activación del cifrado de su disco."
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,40)
$objLabel1.Size = New-Object System.Drawing.Size(280,30)
$objLabel1.Text = "Tras reiniciar, si su equipo es HP tendrá que pulsar la tecla F1 y si es TOSHIBA la tecla F10."
$objForm.Controls.Add($objLabel1)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,75)
$objLabel0.Size = New-Object System.Drawing.Size(280,20)
$objLabel0.Text = "It will proceed to activate the hard drive encryption."
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,95)
$objLabel1.Size = New-Object System.Drawing.Size(280,40)
$objLabel1.Text = "After restarting your computer if it an HP you will need to press the F1 Key however if it is a TOSHIBA press the F10 key."
$objForm.Controls.Add($objLabel1)

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

}

function VENTANANOREINICIO
{
#Ventana Form donde se comunica el proceso

$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "IT Department."
$objForm.Size = New-Object System.Drawing.Size(300,220)
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(80,150)
$OKButton.Size = New-Object System.Drawing.Size(120,25)
$OKButton.Text = "Accept"
$OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()})
$objForm.Controls.Add($OKButton)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,10)
$objLabel0.Size = New-Object System.Drawing.Size(280,20)
$objLabel0.Text = "Se va a lanzar el proceso de cifrado de su disco."
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,30)
$objLabel1.Size = New-Object System.Drawing.Size(280,40)
$objLabel1.Text = "Usted podrá trabajar con normalidad, aunque apreciará cambios en el espacio libre de su unidad de disco."
$objForm.Controls.Add($objLabel1)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,85)
$objLabel0.Size = New-Object System.Drawing.Size(280,20)
$objLabel0.Text = "It will proceed to activate the hard drive encryption."
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,105)
$objLabel1.Size = New-Object System.Drawing.Size(280,30)
$objLabel1.Text = "You can work normally although during this process the hard drive free space will changes."
$objForm.Controls.Add($objLabel1)

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

}

#Prepara el disco para bitlocker
function PREPDISCO 
{

    if( $Partitionstatus.size -gt 314572800) {
        VENTANAPARTREINICIO
        bdehdcfg -target default -restart -quiet
    } 
}

#Comprobamos que estamos en red.
Function CONEXIONREDCIFRADODISCO
{
    $Ping1DC = Test-Connection "!DC1" -Count 1 -Quiet
    $Ping2DC = Test-Connection "!DC2" -Count 1 -Quiet
    if (($Ping1DC -eq $true) -or ($Ping2DC -eq $true)) {
        VENTANANOREINICIO
        manage-bde -on c: -skiphardwaretest -recoverypassword
    }

}

#-------------------------------------------------------------------------------
#Ejecución script general
#-------------------------------------------------------------------------------

PREPDISCO

#Entrará en el if si el disco no está cifrado, la unidad de disco está preparada, es un portátil y está en dominio
If (($compconfig.domain -eq "!dominio.local") -and ($bitlockstatus -ne "1") -and ($Partitionstatus.size -le 314572800) -and ($tipoequipo -eq "2")) {
    if (($tpm.isEnabled_InitialValue -eq $true) -and ($tpm.isActivated_InitialValue -eq $true) -and ($tpm.IsOwned_InitialValue -eq $true)){
        #TPM está listo para habilitar bitlocker    
        CONEXIONREDCIFRADODISCO
    }
    elseif (($tpm.isEnabled_InitialValue -eq $true) -and ($tpm.isActivated_InitialValue -eq $true) -and ($tpm.IsOwned_InitialValue -eq $false)){
        #Se obtendrá propiedad de tpm"
        $valor=1
        manage-bde -tpm -takeownership %date%%random%%random%
        CONEXIONREDCIFRADODISCO
    }
    elseif (($tpm.isEnabled_InitialValue -eq $false) -and ($tpm.isActivated_InitialValue -eq $false) -and ($tpm.IsOwned_InitialValue -eq $false)){
        #TPM Se pondrá en ON y se forzará reinicio
        VENTANAREINICIO
        manage-bde -tpm -t
        shutdown -r -t 60 
    }
    elseif (($tpm.isEnabled_InitialValue -eq $false) -and ($tpm.isActivated_InitialValue -eq $false) -and ($tpm.IsOwned_InitialValue -eq $true)){
        #TPM Se pondrá en ON y se forzará reinicio
        VENTANAREINICIO
        manage-bde -tpm -t
        shutdown -r -t 60
    }
    elseif (($tpm.isEnabled_InitialValue -eq $true) -and ($tpm.isActivated_InitialValue -eq $false) -and ($tpm.IsOwned_InitialValue -eq $false)){
           #TPM está encendido peri no activado, se activará y forzará reinicio
        VENTANAREINICIO
        manage-bde -tpm -t
        shutdown -r -t 60
    }
}

lunes, 24 de junio de 2013

Aplicar script solo a un tipo de equipo / servidor

Hola.

Muchas veces, uno de los condicionantes a la hora de aplicar un script, es aplicarlo solo a equipos y no a servidores e incluso a portátiles y no a puestos de trabajo.

Si os encontráis en esta situación, incluso como medida de protección ante scripts que vayáis a aplicar a una directiva aplicada a, por ejemplo, la ou donde debería haber un tipo de equipos, incluso una directiva aplicada a una consulta wmi que aplique solo a ciertos equipos, mejor aseguraros en el propio script que este, solo se aplicará si encontramos el tipo de equipo deseado, por ejemplo así:

  • $CompConfig = Get-WmiObject -Class Win32_ComputerSystem
  • $tipoequipo = $CompConfig.PCSystemType

$tipoequipo puede ser:

  • 1 {"Desktop"},2 {"Laptop"},3 {"Workstation"},4 {"EntServer"},5 {"SmallOfficeOrHomeServer"},6 {"AppliancePC"},7 {"PerformanceServer"},8 {"Maximum"},default {"NoConocido"}

Si queréis el nombre, podéis añadir esto:

Switch ($tipoequipo) {
   1 {"Desktop"}
   2 {"Mobile / Laptop"}
   3 {"Workstation"}
   4 {"Enterprise Server"}
   5 {"Small Office and Home Office Server"}
   6 {"Appliance PC"}
   7 {"Performance Server"}
   8 {"Maximum"}
default {"Not a known Product Type"}
}

 

En cuanto a equipos de dominio podemos también extraer información:

$TipoOrdenador = Get-WmiObject Win32_ComputerSystem
$Rol = $TipoOrdenador.DomainRole

 

Switch ($Rol) {
   0 {"Standalone Workstation"}
   1 {"Member Workstation"}
   2 {"Standalone Server"}
   3 {"Member Server"}
   4 {"Backup Domain Controller"}
   5 {"Primary Domain Controller"}
   default {"Not a known Domain Role"}
}

 

Tras esto, el condicionante podría ser:

If (($tipoequipo -eq "Desktop") -and ($Roldeservidor -eq "Member Workstation")) then {

}

Saludos.

viernes, 21 de junio de 2013

Comprobación de requisitos y preparación de disco previo a la activación de bitlocker vía cmd y powershell

Hola.

Como requisito del proceso de cifrado del disco, es imprescindible que nuestro boot esté en una partición diferente a la partición que almacena nuestro o nuestros sistemas operativos.

Si disponéis de esta partición, podéis ver que en el administrador de discos, aparece sin letra y con un tamaño que ronda los 100 a 300mb.

Si no disponéis de esta partición y queréis activar bitlocker via scripting, por supuesto debéis crearla y el comando para que el sistema haga un shrink, traslade archivos de boot y modifique el bcdedit, es el siguiente:

  • bdehdcfg -target default -restart –quiet   #pongo default por hacerlo fácil, esto nos dará una partición de 314572800bytes que redondeando son  300mb.

A mi me aparece la necesidad de comprobar vía scripting que esta partición existe y he utilizado los siguientes comandos:

$Partitionstatus= Get-WmiObject Win32_DiskPartition -filter "bootpartition='True'"

if( $Partitionstatus.size -gt 314572800) {
    VENTANAPARTREINICIO  #función mía que lanza una ventan con aviso de reinicio
    bdehdcfg -target default -restart -quiet
}

saludos.

Posibles estados del chip TPM y gestión de bitlocker vía Cmd y Powershell

 

En este artículo, voy a intentar plasmar las posibles situaciones en las que podemos encontrar y posicionar el chip TPM, con el fin de activar Bitlocker en los equipos de nuestro parque.

Lo primero que debemos conocer es que el comando Manage-bde es el que nos permitirá ir cambiando el estado del chip, los comandos son:

  • manage-bde –tpm –t  #activa tpm
  • manage-bde –tpm –takeownership contraseña   #Para tomar propiedad del chip si no somos propietarios.
  • manage-bde –on c: –skiphardwaretest –recoverypassword  #Para lanzar bitlocker en la unidad c:

Lo segundo que debemos conocer es que como inevitablemente el scripting va a formar parte imprescindible del proceso, hay ciertos comandos y consultas wmi que nos harán conducir el proceso.

Primero y antes de nada, la consulta wmi y la clase que extraerá la información es:

$tpm = Get-WmiObject -class Win32_Tpm -namespace "root\CIMV2\Security\MicrosoftTpm"

De la información extraida en la variable $tpm, nos importa esto:

$tpm.isEnabled_InitialValue = True or False   #¿Está habilitado?.

$tpm.isActivated.InitialValue = True or False  #¿Está activado?.

$tpm.isOwned_InitialValued = True or False  #¿Somos el propietario?.

 

Y esto nos puede dar las siguientes condiciones y debemos entonces actuar como se describe:

(($tpm.isEnabled_InitialValue -eq $true) -and ($tpm.isActivated_InitialValue -eq $true) -and ($tpm.IsOwned_InitialValue -eq $true))  #entonces solo queda activar con “manage-bde –on c:….”

(($tpm.isEnabled_InitialValue -eq $true) -and ($tpm.isActivated_InitialValue -eq $true) -and ($tpm.IsOwned_InitialValue -eq $false))  #Debemos hacernos propietarios y activar 1. manage-bde –tpm –takeownership contraseña y 2. manage-bde –on c:…

 

#Requieren activación de tpm “ manage-bde –tpm –t” el resto de condiciones:

(($tpm.isEnabled_InitialValue -eq $false) -and ($tpm.isActivated_InitialValue -eq $false) -and ($tpm.IsOwned_InitialValue -eq $false))

(($tpm.isEnabled_InitialValue -eq $false) -and ($tpm.isActivated_InitialValue -eq $false) -and ($tpm.IsOwned_InitialValue -eq $false))

Y

(($tpm.isEnabled_InitialValue -eq $true) -and ($tpm.isActivated_InitialValue -eq $false) -and ($tpm.IsOwned_InitialValue -eq $false))

 

Saludos.

Interactuar con usuario en tarea programada

Hola.

Uno de los problemas comunes, al programar tareas programadas via gpo a todos o parte de los equipos del parque, es que queremos interactuar con el usuario y esto choca con el usuario que debemos poner en la tarea con privilegios para que la tarea sea lanzada.

Pues bien, para que las ventanas y/o scripts salten en la sesión del usuario, debemos hacer que la tarea se ejecute con el usuario localhost\usuarios

Para ello cuando estamos en el menú “General” – debemos elegir el usuario que os he comentado y podéis ver aquí:

image

 

Saludos.

Provocar ventana en tarea programada

Hola.

La forma de hacer que aparezca al usuario una ventana con una información concreta, disparada por una tarea programada es la siguiente:

 

1. Menú Acciones en tarea programada.

2. Crear una nueva acción con las opciones: Iniciar un programa – Powershell en “Programa o script” y en “Agregar argumentos (opcionar"), utilizar el siguiente argumento:

-WindowStyle hidden -Command "& {[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Your_Desired_Message',’texto a aparecer’)}"

 

image

Saludos.

jueves, 20 de junio de 2013

Encontrar cadena de texto en powershell

Hola.

Estoy metido de lleno en un script para lanzar bitocker y me surge la necesidad de saber si el disco está cifrado para crear un if en el script.

Pues bien, la forma más fiable de todas las posibles es encontrar la cadena 0% en la información que devuelve manage-bde, para ello he utilizando:

 

$status=manage-bde c: -status
$id = $status -match "0%" | Out-String

if ($id -like '* 0%*') {
    entonces…
}

 

Saludos.

Cambiar la propiedad de del chip TPM con contraseña aleatoria

Hola.

Pongámonos en situación. Tenemos un equipo con bitlocker activado, en el que para volver a instalar windows y activar Bitlocker, hemos roto la partición y vuelvo a crear otra nueva.

La instalación la haremos sin problema, pero la activación de bitlocker ya no es tan fácil ya que el chip está en modo ON y la contraseña de acceso no la tenemos.

Ante una situación como la descrita y otras muchas donde no somos propietarios o hemos borrado el contenido y password del chip a través de la bios, la solución es la misma. Tenemos que hacernos propietarios de ese chip y para ello, el comando es el siguiente:

  • manage-bde –tpm –takeownership PASSWORD

Para mí y para muchos, ya que he podido comprobar que los foros están repletos de dudas y pocas o ninguna solución, el problema que aprecio es que la password, en un script está en texto plano e incluso, si tienes un parque medianamente extenso, va a ser la misma en todos los equipos.

Es importante subrayar que esta password, no necesitamos conocerla, ya que podemos solucionar cualquier incidencia con la clave de bitlocker que habremos almacenado en archivos de texto o mejor aun, en directorio activo gracias a una gpo correctamente configurada.

Pues bien,  tras las pruebas realizadas :), el comando que os he mostrado anteriormente se puede sustituir por:

  • manage-bde –tpm –takeownership %random%

Esto tiene un problema y es que el random puede ir des 0 a una cantidad de 4 crifras y como manage-bde te obliga a que la contraseña sea de 8 cifras, tampoco nos valdría con un %random%%random%

Pues bien, tras las pruebas realizadas (2), he optado por:

  • manage-bde –tpm –takeownership %time%%random%%random%.

¿Ingenioso eh? :), así tenemos una contraseña fuerte a prueba de auditores quisquillosos.

jueves, 13 de junio de 2013

DNS block list en Windows Server

Hola.

Un olvidado a la hora de aumentar la seguridad de nuestra red es el servicio de blocklist de nuestro DNS, este servicio es administrable en su totalidad e incorpora una lista de direcciones, que para no ahondar mucho más en él, podemos decir que no se resolverán aunque tengamos una entrada host , alias, etc. creada.

El ejemplo más claro lo vemos cuando queremos publicar un servicio proxy pac vía dns y creamos la entrada, que debería resolver wpad.dominio.local por ejemplo.

Captura donde podéis ver que no podemos hacer ping a la dirección:

image

Gestión de la Blocklist

Comandos comunes en la gestión de este servicio son:

  • dnscmd servidor /info /globalqueryblocklist    - Nos enseña la lista de direcciones bloqueadas.
  • dnscmd Servidor /config /globalqueryblocklist nombre nombre nombre …   - Añade una o varias direcciones
  • dnscmd servidor /config /enableglobalqueryblocklist 0|1  - 0 Deshabilida  1 Habilita Blocklist
  • dnscmd /config /globalqueryblocklist  - Vacia la lista de direcciones.

Por defecto tenemos en la lista wpad y Isatap:

image

Y tras el reseteo de la lista:

image Saludos.

lunes, 3 de junio de 2013

Nuevas funcionalidades en Hyper-V dentro de Windows Server 2012 R2

 

Hola.

Hoy se han presentado bastantes novedades de lo que va a ser el nuevo rol de Hyper-V dentro de Windows Server 2012 R2 y que junto a System Center 2012 R2, también se ha dicho que en Junio será pública una Release Candidate.

Nuevas funcionalidades:

1. Replica extendida. El servidor que recibe la réplica, podrá ser a su vez un emisor hacia otro servidor de backup = Server A replica a server B y a su vez, replica a server C. También podremos controlar el intervarlo de envío de los logs al servidor de réplica.

2. Máquinas virtuales de nueva generación. Este es un concepto que a todos nos resulta nuevo, pero a falta de una exhaustiva investigación Sonrisa, son máquinas virtuales sin relación con el hardware, no dispositivos legados, no bios, todo virtual y sin dependencias.

3.Remote Desktop Services integrado en el VM Bus, lo que le va a hacer, independiente del adaptador de red.

4.Redimensionamiento Online de VHDX. Creo que la descripción lo explica todo.

5.USB como pass-trough Hoy mismo lo he echado en falta Sonrisa.

6.Compatibilidad total con Azure ya que, según Microsoft, en Azure contaremos con la misma versión de host de la que ofrece el sistema operativo que adquiriremos.

7.Online VM Export. Podremos exportar máquinas virtuales sin interrupción.

8.Live migration más rápido. Se comprimirá los datos antes de ser migrados lo que acelerará la migración en vivo. A esto se suma que se podrá combinar con las ventajas que aporta SMB direct y las nuevas versiones de SMB.

9.Activación automática de VMS. Veremos como funciona pero sabiendo que las VMS ya se puede decir que se licencian gracias a la compra del host, lo que he leido está relacionado con la activación única del host (esto es una teoría personal a falta de analizar al 100% esta funcionalidad).

10. Qos para el almacenamiento. Podremos controlar y gestionar los I/o y peso de una VM en relación a la ocupación del almacenamiento. Lo que se suma al ya antiguo Sonrisa control del peso en cuanto al uso del procesador y control de la memoria que ofrecía Dynamic Memory.

Saludos.

Limpiar Proxy pac cacheado en equipos

 

Hola.

Las últimas semanas he estado trabajando mucho en relación a la publicación de proxy pac que está detrás de la opción “Detectar automáticamente la configuración” a la hora de que el equipo, encuentre la salida correcta por internet.

En los próximos días colgaré bastante información bajo la etiqueta Proxypac, la cual espero que os sea útil si tenéis que realizar pruebas y su posterior puesta en producción.

Por el momento quería dejar publicados los pasos necesarios para limpiar todo rastro de la caché del archivo proxy pac. Esta información es útil ya que como el S.O. cachea este archivo, comprobar cada cambio se convierte en una verdadera pesadilla:

Limpiar caché manualmente:

1. Borrar  por completo el historial del navegador .

2. Abrir un CMD como Administrador.

3. Ejecutar el comando: Del \wpad*.dat /s  (cuidado, borrará cualquier archivo proxy pac que tengáis en el disco.

4. Ejecutar el archiconocido: ipconfig /flushdns

5. Ejecutar: nbtstat –r

6. Abrir navegador.

También deciros que por mi experiencia, Firefox parece que al menos a mí, no me cachea el proxy pac, por lo que en producción va a resultar un tanto pesado, pero para hacer troubleshooting es ideal.

Si quisierais desactivar el cacheado del proxy en todo o parte del parque, os dejo un KB de Microsoft donde podéis ver como se hace, pero, de todas formas, yo limpiaría manualmente la caché en los equipos donde aunque hayáis aplicado esta política o modificación de registro, queráis estar completamente seguros que está cogiendo el proxy pac publicado.

http://support.microsoft.com/kb/271361/es

 

Saludos.

Instalar características de ws2012 offline eligiendo fuente de datos

 

Hola.

Cuando instaláis una  característica (Feature) o Rol en Windows Server 2012 o Windows 8, os podéis encontrar que sin conexión a internet o contando con una conexión filtrada a través de un proxy, no la activación de estas, no pueda realizarse.

Para solucionar este problema, debéis indicar una fuente de datos correcta ya que Internet, como tal, no es una posibilidad.

Por tanto:

1. Debéis descomprimir el Iso de Ws2012 y/o W8 o copiar el contenido del dvd en una carpeta.

2. Utilizar este comando para la activación de:

dism.exe /online /enable-feature /featurename:Feature /Source:Unidad:\sources\sxs /LimitAccess /all

Ejemplo .Net Framework:

dism.exe /online /enable-feature /featurename:NetFX3 /Source:e:\isos\sources\sxs /LimitAccess /all

Esta es una consulta más o menos común en los foros, pero atentos, pocas instrucciones dadas en estos, añaden la variable /all la cual habilita la activación de dependencias y por tanto, el comando falla fácilmente.

Saludos

viernes, 31 de mayo de 2013

Lista de actualizaciones y hotfix publicados para Hyper-V en WS2012

 

Hola.

En Technet han actualizado la tabla con la lista de actualizaciones y hotfix sacados hasta la fecha para Hyper-V en Windows Server 2012

Aquí lo tenéis:

http://social.technet.microsoft.com/wiki/contents/articles/15576.hyper-v-update-list-for-windows-server-2012.aspx

En este web también podéis encontrar algo similar en relación a actualizaciones y hotfix para el rol de Failover Clúster:

http://support.microsoft.com/kb/2784261

Saludos.

miércoles, 29 de mayo de 2013

Sacar tipo index de una imagen .wim

 

Hola.

Hacía tiempo que no me liaba con esto, pero como tampoco es que esta información sea fácil de encontrar por internet, os detallo el comando necesario para ver cual es la versión de sistema operativo que comprende el index X de una imagen .wim.

dism /get-wiminfo /WimFile:G:\w2012wims\install.wim /index:Número

image

Voy a ver si me lio con el script para que todo vaya del tirón en un despliegue con vhds. Espero subirlo por aquí pronto.

viernes, 5 de abril de 2013

Hyper-V: Top Free programs

Hola.

Os dejo un enlace de un compañero MVP donde relaciona las principales herramientas que solemos usar con Hyper-V. Veréis que siempre se descubre algo ;).

http://social.technet.microsoft.com/wiki/contents/articles/2325.hyper-v-top-free-programs.aspx

miércoles, 27 de marzo de 2013

Script: inventario donde se relaciona usuario con equipo.

 

Un problema común y fácilmente solucionable en todas los dominios, es el de asociar equipos con usuario.

Para tener un inventario y registro de usuarios que han pasado por cada uno de los equipos, hice un script bastante simple, el cual deja en una carpeta oculta en la red un registro con cierta información, como es: Usuario,dominio, nombre de equipo, fecha e ip. en un archivo de texto separado por comas.

$Date = Get-Date -format MM-dd-yyyy
$Time =     "{0:h:mm:ss tt zzz}" -f (get-date) #finalmente no se guarda para que funcione la búsqueda de duplicados.

$computer=get-content env:computername
$user= [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$Netip = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -computername localhost

add-content \\servidor\share$\Repositorio\infoequipos.txt -value ($user + "," + $computer + "," + $date + "," + $netip.ipaddress)

Saludos.

martes, 26 de marzo de 2013

Script que permite limpiar o subir fotografía a AD.

 

Hola.

Os cuelgo a continuación un Script que he terminado y que permite al usuario subir o limpiar su foto del directorio activo, para que luego se alimente, ya sabéis, Exchange, Lync, etc.

Diréis, ¿Por qué no lo haces en C# y lo compilas?, pues porque lo he ido haciendo en mis ratos libres y como muchas otras cosas, nació para algo diferente. Pero me gusta porque el usuario lo puede lanzar con unas simples instrucciones (botón derecho, ejecutar con poweshell) y al contrario de algunas aplicaciones, no tiene por qué, tener derechos de administrador local para instalarse nada. Sonrisa

Como es común en estas cosas, solo tenéis que localizar y adaptar esta línea de aquí:

$root = [ADSI]'GC://dc=dominio,dc=local' #Inyecta el dominio con el que trabajar

Se que es mejorable,  lo se Guiño.

También tiene varias funciones que os pueden servir de utilidad.

#------------------------------------------------------
#Script encargado de guardar o limpiar fotografía en AD del campo Thumbnailphoto

#Autor: Miguel Hernández

#------------------------------------------------------

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

#-------------------------------------------------------------------------------
#Funciones
#-------------------------------------------------------------------------------

#Toma usuario y lo devuelve con valor $X0
function tomausuario
{

    $objForm0 = New-Object System.Windows.Forms.Form
    $objForm0.Text = "Fotografía en Directorio Activo"
    $objForm0.Size = New-Object System.Drawing.Size(300,120)
    $objForm0.StartPosition = "CenterScreen"

    $objForm0.KeyPreview = $True
    $objForm0.Add_KeyDown({if ($_.KeyCode -eq "Enter")
        {$x0=$objTextBox0.Text;$objForm0.Close()}})    #toma el valor X0
    $objForm0.Add_KeyDown({if ($_.KeyCode -eq "Escape")
        {$objForm0.Close()}})

    $objLabel0 = New-Object System.Windows.Forms.Label
    $objLabel0.Location = New-Object System.Drawing.Size(10,10)
    $objLabel0.Size = New-Object System.Drawing.Size(280,20)
    $objLabel0.Text = "Usuario:"
    $objForm0.Controls.Add($objLabel0)

    $objTextBox0 = New-Object System.Windows.Forms.TextBox
    $objTextBox0.Location = New-Object System.Drawing.Size(10,30)
    $objTextBox0.Size = New-Object System.Drawing.Size(260,20)
    $objForm0.Controls.Add($objTextBox0)

    $OKButton0 = New-Object System.Windows.Forms.Button
    $OKButton0.Location = New-Object System.Drawing.Size(110,60)
    $OKButton0.Size = New-Object System.Drawing.Size(75,23)
    $OKButton0.Text = "OK"
    $OKButton0.Add_Click({$x=$objTextBox0.Text;$objForm0.Close()})
    $objForm0.Controls.Add($OKButton0)

    $objForm.Topmost = $True

    $objForm0.Add_Shown({$objForm0.Activate()})
    [void] $objForm0.ShowDialog()

return $x0

}

#----------------------------------------------------------
#Función resultado
#----------------------------------------------------------

#Abre form con el valor $valor escrito.

function resultado
{

    $objForm0 = New-Object System.Windows.Forms.Form
    $objForm0.Text = "Resultado"
    $objForm0.Size = New-Object System.Drawing.Size(400,90)
    $objForm0.StartPosition = "CenterScreen"

    $objLabel0 = New-Object System.Windows.Forms.Label
    $objLabel0.Location = New-Object System.Drawing.Size(10,20)
    $objLabel0.Size = New-Object System.Drawing.Size(380,20)
    $objLabel0.Text = $valor
    $objForm0.Controls.Add($objLabel0)

       $objForm.Topmost = $True

    $objForm0.Add_Shown({$objForm0.Activate()})
    [void] $objForm0.ShowDialog()
}

#-------------------------------------------------------------
#Función donde se abre ventana donde elegir fotografía
#-------------------------------------------------------------

function Select-FileDialog
    {
        param([string]$Title,[string]$Directory,[string]$Filter="All Files (*.*)|*.*")
        [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
        $objForm = New-Object System.Windows.Forms.OpenFileDialog
        $objForm.InitialDirectory = $Directory
        $objForm.Filter = $Filter
        $objForm.Title = $Title
        $objForm.ShowHelp = $true
        $Show = $objForm.ShowDialog()

        If ($Show -eq "OK")
        {
            Return $objForm.FileName
        }
        Else
        {
            $valor = "Operación cancelada por el usuario."
            resultado $valor
        }
    }

#------------------------------------------------------
#Empieza el script
#------------------------------------------------------

#Ventana Form donde se pregunta la acción a realizar

$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Fotografía en Directorio Activo"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,130)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()})
$objForm.Controls.Add($OKButton)

$objLabel0 = New-Object System.Windows.Forms.Label
$objLabel0.Location = New-Object System.Drawing.Size(10,10)
$objLabel0.Size = New-Object System.Drawing.Size(280,20)
$objLabel0.Text = "1. Limpiar fotografía actual"
$objForm.Controls.Add($objLabel0)

$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,30)
$objLabel1.Size = New-Object System.Drawing.Size(280,20)
$objLabel1.Text = "2. Cambiar fotografía"
$objForm.Controls.Add($objLabel1)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,130)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancelar"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,70)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Seleccionar acción:"
$objForm.Controls.Add($objLabel)

$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,90)
$objTextBox.Size = New-Object System.Drawing.Size(260,20)
$objForm.Controls.Add($objTextBox)

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

#Devuelve el valor $X con 1 o 2 = 1: Limpiar fotografía / 2: Cambiar fotografía

$SAMName = tomausuario  #Pregunta el usuario

    $root = [ADSI]'GC://dc=dominio,dc=local'  #Inyecta el dominio con el que trabajar
    $searcher = new-object System.DirectoryServices.DirectorySearcher($root)
    $searcher.filter = "(&(objectClass=user)(sAMAccountName=$SAMName))"
    $user = $searcher.findall()
    $userdn = $user[0].path
    $userdn = $userdn.trim("GC")
    $userdn = "LDAP" + $userdn
     
      
IF ($x -EQ "1") {

    try
    {
        $user = [ADSI]($userdn)
        $user.Properties["thumbnailPhoto"].Clear()
        $user.CommitChanges()
        $valor = "La fotografía ha sido borrada del servidor"
        resultado $valor
    }
    catch
    {
        $valor = "La fotografía no ha podido ser borrada del servidor"
        resultado $valor
    }
       
}

IF ($x -EQ "2") {
  
    try
    {
        $photo = Select-FileDialog -Title "Selecciona una fotografía (ext.jpg o .png)" -Directory "%userprofile%" -Filter "JPG Images (*.jpg)|*.jpg|PNG Images (*.png)|*.png"
        [byte[]]$file = Get-Content $photo -Encoding Byte
        $user = [ADSI]($userdn)
       
        # Limpiar foto anterior
        $user.Properties["thumbnailPhoto"].Clear()

        # Guardar fotografía
        $user.Properties["thumbnailPhoto"].Add($file)
        $user.CommitChanges()
        $valor = "La fotografía ha sido guardada del servidor"
        resultado $valor
    }
    catch
    {
        $valor = "La fotografía no ha sido guardada en el servidor"
        resultado $valor
    }      
}

martes, 12 de marzo de 2013

Los 8 imprescindibles de Windows 8.

 

Hola.

Seguro que si tenéis múltiples conexiones con la blogosfera, ya conocéis los que os vengo a decir Sonrisa.

 

El amigo @samuelltr a través de @estipro, se ha currado una serie de 8 webcast sobre Windows 8, en la que participarán 8 IT pros que a pesar de la “juventud” del sistema operativo, cuenta con mucho conocimiento sobre el mismo.

Aquí tenéis toda la información y registro:

http://technet.microsoft.com/es-es/dn186239.aspx

Yo por mi parte, me encargaré del webcast sobre “recovery” que se realizará el 16 de Abril a las 18:00 gmt +1.

 

¡Saludos!.

jueves, 7 de marzo de 2013

Quitar aplicaciones de la interface Metro de una imagen / plantilla

 

Hola.

El comando para quitar aplicaciones que no queremos, en lo que va a ser nuestra imagen/plantilla corporativa, es el ya conocido dism.exe con las variables /image /remove-provisionedappxpackage y a continuación el parámetro correspondiente.

http://support.microsoft.com/kb/2769827

Saludos.