jueves, 23 de agosto de 2012

Interfaz de usuario de Windows 8

Síntomas

Instalas Windows 8, al arrancar te encuentras con una pantalla que parece un Windows Phone.
¿Qué haces a continuación? ¿Donde está botón de inicio? ¿el panel de control? ¿Cómo lo apagas?

Solución:

Para ver el escritorio normal busca un cuadro con margaritas entre todos esos que cambian de color y hablan de fútbol.
Cuando hagas clic en las margaritas llegaras al escritorio.
Pero no encontraras el botón de inicio, porque no lo hay, ni sin duda lo habrá.
Una alternativa al botón de inicio es desplazar el ratón a las esquina superior o inferior  derecha
Se despliega una barra en el lateral derecho, allí tienes la lupa, le das clic y tienes una lista de programas e incluso el panel de control.
Otra opción interesante en la barra que has desplegado es la de configuración (la rueda tipo tiempos modernos abajo). Allí tienes un botón iniciar/apagar que sirve para apagar o REiniciar.
Para cerrar sesión tienes que volver a la ventana de los cuadrados cambiantes (se llama Metro) y pulsar en tu nombre arriba a la derecha.
Pero desde el escritorio ¿cómo vuelves al dichoso Metro?
Hay algo maravilloso en Windows 8, la tecla de Windows  te lleva a Metro sacándote de cualquier embrollo donde te hayas metido sin encontrar la flecha de salida.
¡Es como la tecla escape pero con dibujos!

También sigue funcionando esta tecla con la R para ejecutar un programa. Es una lástima que no sirva también para desinstalar Windows 8 y volver al 7.

Comentario:

Microsoft ha vuelto a cometer los errores del Vista y del Office 2007: confiar en diseñadores y creativos del marketing que piensan que un ordenador es un producto para consumir (metro) no para crear (escritorio), y que a un teclado le sobran 103 teclas porque les molesta que otros escribamos con todos los dedos.

Las personas normales somos reacias al cambio, nos gusta que la llave o interruptor para arrancar el coche esté en el lado derecho del volante. Aceptamos los cambios cuando nos aportan algún beneficio.
En mi Nissan, no me molesta presionar el pedal de freno al mismo tiempo porque la llave inteligente me evita rebuscar en los bolsillos (ante guardaba la llave nada mas abrir la puerta del coche y luego no la encontraba).

Pero ¿qué aporta Metro? ¿El mismo interfaz en todos mis dispositivos?
¡Pero si yo cambié los teléfonos móviles de mi empresa desde Windows Phone a Android cuando salió Windows Phone 7.0 precisamente con ese interfaz Metro y sus contenidos cambiantes!
Si fuera solo una pantalla de bienvenida pasaría, pero al quitar el botón de inicio pierdes mucho tiempo cada vez que quieres hacer algo normal.
Lo peor es que cuando salio la preview algunos programadores sacaron utilidades para recuperar ese botón de inicio, pero desde Microsoft alguien ordenó que bloquearan esta posibilidad. Sostenella  y no enmendalla

Desde el punto de vista de empresa no anticipo nada bueno a Windows 8:
  1. Costes de formación usuario final. ¿os acordaís del botón de office 2007 y los usuarios queriendo imprimir?.
  2. La pantalla inicial que ofrece juegos, musica, videos, noticias de futbol, cualquier cosa menos productividad. (y eso que estoy probando la versión enterprise).
El caso es que por lo que he leído y experimentado en Windows 8 hay mucho trabajo de core que agiliza el sistema en el arranque y en el uso. Es una lastima que todo ese trabajo se desaproveche y espero que Microsoft corrija antes de que sea tarde como ya hizo con el Windows 7 y otros muchos productos antes.

Yo he usado Windows en todas las versiones tanto de escritorio ( 1, 2, 2.1, 386,3,0, 3,1,  3.11, 95, 98, me, XP,  Vista, Windows 7) y como de servidor (OS/2 con IBM, NT 3.1, NT 3.5, NT 3.51, NT4, 2000, 2003, 2003R2, 2008, 2008R2,...y se de que hablo.
Porque al fin y al cabo a mí me gusta Microsoft,..., aunque en Visual Studio 2012 haya puesto los menús en mayúsculas, ¡otro creativo suelto!.






Se interrumpe la instalación del Rollup 4 para Exchange 2010 SP2

Síntomas:

Cuando aparece la barra de progreso de instalación del RU4 para XCHG2012 SP2 indica que está intentado detener los servicios, inmediatamente después informa que está deshaciendo las acciones y te informa que no se ha instalado.

Solución:

Guarda el archivo msp del RU en una carpeta.
Abre un ventana de símbolo de sistema en modo administrador 
(ya sabes botón derecho en el menú de inicio, ejecutar como administrador)
Ves a la carpeta y ejecuta.

domingo, 19 de agosto de 2012

Script PowerShell para apagar infraestructura vmWare

Enunciado

Quieres que en caso de corte de suministro eléctrico prolongado las maquinas virtuales de tu infraestructura vmWare se apaguen ordenadamente por grupos y dejando para el final las maquinas mas críticas (los servidores de dominio).

Entorno

En mi caso dispongo de un SAI EATON que puede notifica a un software Intelligent Power Protector que puede lanzar un batch.

Solución

Me baso en el post http://www.virtu-al.net/2010/01/06/powercli-shutdown-your-virtual-infrastructure/ y algunos de los comentarios que allí hacen.
Coloco las maquinas que deben apagarse en varias carpetas o grupos según su importancia.
La idea es lanzar el siguiente script PowerShell desde un batch (powershell script.ps1)
if (!(get-pssnapin -name VMware.VimAutomation.Core -erroraction silentlycontinue)) {
     add-pssnapin VMware.VimAutomation.Core
 }
Set-PowerCLIConfiguration -DisplayDeprecationWarnings $false -Confirm:$false 

function ApagaMaquinasCarpeta 
#Ordena el apagado de las $maquinas en un grupo (host, carpeta, cluster,...etc) y espera un $tiempo dado 
{
 write $Carpeta
 $Maquinas=Get-Folder -Name $Carpeta 
 Foreach ($VM in ($Maquinas |Get-VM  )){
      Shutdown del invitado
     $VM | Shutdown-VMGuest -Confirm:$false
 }
 #Bucle esperando que apague
 $Inicio= (Get-Date).TimeofDay
 do {
   sleep 1.0
  $Lapso=(Get-Date).TimeofDay - $Inicio
     $Quedan = $Tiempo - ($Lapso.TotalSeconds)
  write  $quedan
  $numvms = ($Maquinas |  Get-VM | Where { $_.PowerState -eq "poweredOn"} ).count
  write "Esperando que se apaguen $numvms VMs o que transcurran $Quedan segundos"
  } until ((@($Maquinas |  Get-VM | Where { $_.PowerState -eq "poweredOn"} ).count -eq 0) -or ($Lapso).TotalSeconds -ge $Tiempo)
 write "Maquinas apagadas o plazo consumido ($Lapso)"
}
 clear 
$VCenter= "vcenter.empresa.org"
 
Connect-VIServer $VCenter
$Hosts= Get-VMHost
$Tiempo=1
$Carpeta= "Apagado Directo"
ApagaMaquinasCarpeta 
$Tiempo=20
$Carpeta= "Escritorios"
ApagaMaquinasCarpeta 
$Tiempo=300
$Carpeta= "Servidores"
ApagaMaquinasCarpeta 
$Tiempo=300
$Carpeta= "Ultimo apagado"
ApagaMaquinasCarpeta 
$ESXSRV = Get-VMHost
$ESXSRV | Foreach {Get-View $_.ID} | Foreach {$_.ShutdownHost_Task($TRUE)}
Disconnect-VIServer -server $VCenter -Confirm:$false
write "Fin"
#Apago la estación IPP
Stop-Computer

Comentarios

Eaton suministra un modulo para instalar en la infraestructura, pero me gusta mas esta solución porque puedo verla, probarla y guardar un archivo de seguimiento (redireccionando powershell).

Alguien se preguntará el por qué no uso parámetros de función en lugar de variables globales: no funcionaban, tenia prisa y trabajar con mandatos del tipo shutdown me pone muy nervioso.
En primer lugar porque un error te tira todas las maquinas, pero también porque la actualización ESXi 5.0 me había dejado sin módulos de shutdown, en el agosto mas caluroso desde hace años y podían producirse cortes de suministro por el elevado consumo de aire acondicionado.

viernes, 13 de julio de 2012

Descargar un informe desde Report Server en PDF

Enunciado 

Usando Visual Basic.NET, descarga un informe desde Report Server que puede ser utilizado para mandarlo por correo o generar una descarga por web.

Solución

Es tan simple como esto:
Private Function solicitaInformeSSRS(idRespuesta As Integer) As Byte()
        Dim informe As New ServerReport
        With informe
            .ReportServerUrl = New Uri(My.Settings.urlServerReport)
            .ReportPath = My.Settings.SSRSEncuestaPromocion
            .ReportServerCredentials = New MyReportServerCredentials
            .SetParameters(New ReportParameter("idRespuesta", idRespuesta))
            .Refresh()
            Return .Render("PDF")
        End With
End Function
Hay que utilizar la clase  MyReportServerCredentials que puedes encontare en mi post Autentificación Reporting Services

Usos:

Una vez descargado el array de byte, puedes utilizarlo para adjuntarlo en un email como un adjunto:

 msj.Attachments.Add(New Attachment(New System.IO.MemoryStream(informe),"informe.pdf")) 
O entregarlo en el stream de salida de una página (descarga del PDF):
Response.Clear()
Response.ContentType = "Application/PDF"
Response.AddHeader("content-disposition", String.Format("attachment; filename={0}.PDF", "archivo.PDF"))
Response.BinaryWrite(bytes)

Comentario:

Usar informes del servidor resulta mas simple, y no digamos ya si existen subinformes, ver Subinformes RDLC en Report cargado dinámicamente.

miércoles, 11 de julio de 2012

Lanzar eventos desde un control de usuario ASP.NET

Enunciado

Una forma muy cómoda de comunicar un control de usuario (.ascx) con la página u otro control de usuario que le contiene es definir un evento, lanzarlo y recogerlo.

Por ejemplo:
Un control de usuario realiza un búsqueda y la visualiza en un dataGrid.
Cuando el usuario elige un comando en una fila del datagrid el control de usuario lanza un evento informando con un texto y un identificador.

Solución:

Un pequeño truco, en el data grid usamos un comando con nombre y argumento.

   
        
           
         
         
   

En el código del control de usuario definiremos el evento y lo lanzaremos en dos casos:
  1. Con el evento RowCommand del datagrid
  2. Al hacer en click en cancelar (un botón)

Public Event eleccion As System.EventHandler

Private Sub gvActiv_RowCommand(
                        sender As Object, 
                        e As GridViewCommandEventArgs
                        ) Handles gvActiv.RowCommand
        RaiseEvent eleccion(Me, New ArgumentoObjetoElegido(e))
End Sub

Protected Sub LBCancelar_Click(
                        sender As Object,
                        e As EventArgs) Handles LBCancelar.Click
        RaiseEvent eleccion(Me, New ArgumentoObjetoElegido)
End Sub
Observar que como segundo argumento al lanzar el evento (RaiseEvent) hemos usado la clase ArgumentoObjetoElegido que hereda de EventArgs.
Esta clase puede crearse con y sin los argumentos. En caso de usar argumentos estos son del tipo GridViewCommandEventArgs.
Public Class ArgumentoObjetoElegido
    Inherits EventArgs
    Public Property Identificador As Integer = 0
    Public Property Descripcion As String = "(Nada seleccionado)"

    Public Sub New(Argumentosfila As GridViewCommandEventArgs)
        Identificador = CInt(Argumentosfila.CommandArgument)
        Descripcion = Argumentosfila.CommandName
    End Sub
    Public Sub New()
        'sin argumentos, valores iniciales arriba
    End Sub
End Class
Finalmente hay que recoger el evento en la página principal:
Private Sub EligeActiv_eleccion(sender As Object, e As ArgumentoObjetoElegido) Handles EligeActiv.eleccion
        If e.Identificador = 0 Then
            'Codigo para procesar cancelación
            If controlador.ActividadEnCurso.identificador = 0 Then
                controlador.ControlMenos()
            Else
                EstableceVista(VistaActividad)
            End If
        Else
            'codigo para procesar una elección el grid
            controlador.ActividadEnCurso.identificador = e.Identificador
            controlador.ActividadEnCurso.Descripcion = e.Descripcion
            EstableceVista(VistaActividad)
        End If
    End Sub

lunes, 9 de julio de 2012

WSUS: problema al conectarse a la base de datos el servicio de red

Sintomas

El servidor de actualizaciones (WSUS) no arranca. aparecen varios errores en el registros de eventos, el más destacado e indicativo es:

Tipo de suceso: Errores
Origen del suceso: MSSQL$MICROSOFT##SSEE
Categoría del suceso: (4)
Id. suceso: 18456
Fecha: 09/07/2012
Hora: 14:05:32
Usuario: NT AUTHORITY\Servicio de red
Equipo: W2K3R2
Descripción:
Login failed for user 'NT AUTHORITY\Servicio de red'. [CLIENT: ]

Solución:

Necesitarás las herramientas de administración de SQL Server.
Arranca el SQL Server Configuration Manager
Habillita las canalizaciones con nombre en configuración de red de SQL Server.../Protocolos de Microsoft##SSEE

De paso copiate al portapapeles el nombre de la canalización
\\.\pipe\MSSQL$MICROSOFT##SSEE\sql\query
Que encontraras en las propiedades de las canalizaciones con nombre

Ahora con SQL Server Managemente Studio
Conectate al motor de la base de datos
\\.\pipe\MSSQL$MICROSOFT##SSEE\sql\query
Si me has hecho caso, te bastarácon pegarlo.

Abre las propiedades de la base de datos SUSDB y activale la opción de multiusuario (estará en usuario único)

Comentario:

Encontré la pista en http://steili.com/2012/06/19/wsus-3-0-sp2-will-not-run-after-installing-update-2720211/ aunque en su caso no había funcionado. El habla de que el problema estaba en una instalación fallida de la KB2720211, pero en mi caso tengo que reconocer que se llenó el disco. Y eso que es una VM y tengo suficiente espacio. Pero es un crimen.



viernes, 6 de julio de 2012

Autocompletar un cuadro de texto en jQuery Mobile

Enunciado:

Tenemos la clásica búsqueda con un cuadro de texto al que normalmente desplegaríamos un lista de sugerencias a medida que escriben. En una aplicación de escritorio ASP.NET usariamos el componente autocomplete de AJAX.NET o de jQuery UI. Pero ¿En una aplicación móvil?

Solución:

Usar jQuery y el componente jQM Autocomplete de Andy Matthews.
Si haces clic en el vínculo llegaras a una demo y te enamoraras como lo hice yo.

Desarrollo de la solución

Necesitaras un servicio JSON que te entregue las sugerencias de palabras. Si desarrollas en ASP.NET puedes consultar mi post Desarrollo de un servicio json sobre ASP.NET para consumo desde Jquery
En mi caso además estaba buscando nombres de empresa en una base de datos por lo que dispongo del identificador único de registro.
Por eso devuelvo un array de objetos con dos propiedades de texto "label" y "value" .
Esta es la respuesta JSON:

[{"label":"INCOAZUL","value":"353"},{"label":"AZULIBER","value":"18"},{"label":"AZULEJERA ALCORENSE","value":"62"},{"label":"MAYOLICA AZULEJOS, S.L.","value":"60"},{"label":"AZULEJOS ALCOR","value":"61",{"label":"AZULINDUS & MARTI, S.A.","value":"13"},{"label":"NOMAZUL, S.A.","value":"85"}}] Este un ejemplo código de página:

    Que completaríamos con esté código JavaScript
           $(document).ready( function (e) {
             $("#busqueda").autocomplete({
                 method: 'GET',
                 target: $('#sugerencias'),
                 source: "/MAC.svc/NomIdEmpresa",
                 link: 'ficha?id=',
                 minLength: 3
             });
         });
     
    
    Por supuesto en los encabezados debes incluir las referencias a las librerias y estilos jQuery, jQuery Mobile y jQM autocomplete.
    Observarás que en la parte java especifico un enlace ficha?id= que se completará al final con el campo value que me devuelve el JSON. Asi cuando clicken en INFOAZUL navegaremos hacia ficha?id=353.
    Sin embargo, esta no es la solución optima, lo mejor sería cambiar a una página móvil ya cargada y actualizarla con los datos leidos con un llamada a un servicio JSON datosEmpresa(idEmpresa). 
    Es mi próximo objetivo, así que....continuará en próximas entregas