Error en la instalación de SQL SERVER en Windows Server 2012. “Error en la espera del controlador de recuperación del Motor de base de datos…”

Al instalar SQL 2014 en un Windows Server 2012 R2, es posible que nos encontremos con el siguiente error:
“error en la espera del controlador de recuperación del motor de base de datos”

Se trata de un problema de autenticación con la cuenta de instalación por defecto que se asigna a los servicios del motor de base de datos.

Podemos solucionarlo escogiendo el usuario:
“servicio de red”

Lo mismo ocurre con el usuario del servicio Agente SQL server (debemos asignar el mismo usuario para que se ejecute con normalidad)

Habilitar TRUSTEDHOSTS para Hyper-V

Existe un problema a la hora de configurar una consola de administración remota de Hyper-V en una máquina cliente que no pertenece a ningún dominio. En ocasiones la máquina cliente no está preparada para ejecutar comandos remotos hacia otros servidores por lo que tendremos que configurarla para tal labor.

Para ello vamos a utilizar el comando WINRM en una ventana cmd con permisos de administrador.

Si no somos clientes de un Dominio o usamos https, WINRM requerirá que configuremos un parámetro adicional “TrustedHosts”, donde deberemos indicar las IPs de los equipos a los cuales deseamos conectarnos para la ejecución de comandos. Para modificar este parámetro debemos ejecutar el comando:

“winrm set winrm/config/client @{TrustedHosts=”*”}” (al poner un “*” estaremos permitiendo la comunicación con cualquier equipo remoto que ofrezca servicios WS-Management).

Resolver el error de SQL SERVER: Proveedor OLE DB “Microsoft.ACE.OLEDB.12.0″ para el servidor vinculado “(null)”

Queremos vincular una base de datos acces a SQL SERVER y al configurar el link nos da un error y el servidor no nos deja utilizar el proveedor OLE DB.

SELECT * FROM OPENROWSET(‘Microsoft.ACE.OLEDB.12.0′,’C:\Datos\datos.MDB';’Admin';, ‘SELECT * FROM datos’)

Solo tenemos que lanzar los siguientes comandos y por arte de magia nuestro amigo gestor de bases de datos nos deja hacer la vinculación sin problemas:

EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'AllowInProcess', 1
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'DynamicParameters', 1
GO

Enlace Relacionado

PRE-Requisitos en instalaciones con ClickOnce

Para distribuir un desarrollo con dependencias comunes, tipo .NET Framework, Crystal Reports, SQL SERVER Express, etc…, no necesitamos crearnos una instalación compleja con InstallShield. Podemos hacer uso de ClickOnce, que nos permite publicar y mantener las actualizaciones de forma muy sencilla.

ClickOnce001

En mi caso tenía una pequeña solución escrita en C# que utilizaba Crystal Report y SQL Server LocalBD. En las propiedades del propio proyecto C# disponemos de la opción de publicación con ClickOnce. Hasta ahí todo perfecto, pero a la hora de configurar los PRE-Requesititos de mi solución no encontraba en el menú la opción de Crystal. Yo tenía un windows 7 y actualice a windows 8 y después a windows 8.1. ClickOnce utiliza una carpeta de sistema para los re-requisitos, entiendo que será todos los componentes instalados para el desarrollo y algunos que trae por defecto windows. El caso es que todos esos datos están en “C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\Bootstrapper\Packages” menos el de Crystal que estaba en “C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages”. Solución evidente, copiamos la carpeta “Crystal Reports for .NET Framework 4.0” de …\v7.0A\.. a …\v8.1A\… y ya podremos seleccionar Crystal como pre-requisito.

ClickOnce002

Pero se nos plantea otro problema. Hay pre-requisitos que dependen de otros y sin embargo se lanzabn antes que los que necesitan. Así que descubrí que se pueden editar unos ficheros incluidos dentro de cada carpeta de pre-requisito llamado Product.xml. En ese fichero podemos decirle el requisito previo a instalar. Por ejemplo, Crystal Report le tuve que decir que instalase previamente .NET 4.

<RelatedProducts>
<DependsOnProduct Code=”.NETFramework,Version=v4.0″ />
<DependsOnProduct Code=”Microsoft.Net.Framework.2.0″ />
<DependsOnProduct Code=”Microsoft.Data.Access.Components.2.8″ />
</RelatedProducts>

 

Crear y consumir Eventos en C#

Aunque parece un tema fácil y de novatos, los que venimos acostumbrados a muchos años de VB y VB.net, no lo tenemos tan claro. Tras revisar documentación por la RED te encuentras multitud de hilos en los que te explican, cada uno de su forma y manera, como crear un evento y consumirlo desde otra clase.  La mayoría de ellos lo hacen de forma intachable siguiendo las “normas Microsoft”, pero yo, cogiendo de aquí y de allí, os lo voy a explicar de forma sencilla y menos liosa.

En la clase que publica el evento hay que crear un delegado y un evento del tipo del delegado creado. Cada vez que se quiera hacer la invocación al evento basta con hacer la llamada al evento pasándole los argumentos creados en el delegado.

//Creamos el delegado
public delegate void EstadoProcesoDelegate(string Estado);

//Creamos el evento para llamamos al delegados
public event EstadoProcesoDelegate EstadoProceso;

//invocamos al evento
EstadoProceso("Cadena de texto a pasar");

En la clase en la que queremos consumir los eventos simplemente tendremos que crear una instancia de dicha clase y asignar a cada evento que hayamos creado en la clase un método con la misma estructura que el delegado creado.


cClaseConEventos oEvento = new cClaseConEventos();      
//Le asignamos al evento de la clase un metodo con la misma estructura que el delegado      
oEvento.ContadorProceso += oTraspaso_ContadorProceso;

//Creamos un método donde utilizaremos el valor que nos devuelve el evento cada vez 
//que se invoque en la clase en la que lo lanzamos
void oTraspaso_EstadoProceso(string Estado)
{            
     lblProcesoMSJ.Text = Estado;
     lblProcesoMSJ.Refresh();
     this.Refresh();
}

Como eliminar un área de trabajo del TFS

En multitud de ocasiones al operar con el TFS nos encontramos con algunos usuarios que haciendo pruebas han dejado colgados cambios pendientes sobre algunos proyectos. Estos usuarios se crearon áreas de trabajo que ya no existen.

Primero listamos todas las áreas de trabajo existentes para tener los datos necesarios y ver cual es la que hay que borrar:

tf workspaces /owner:* /collection:http://TFServer/tfs/DefaultCollection /login:Usuario,Contraseña

Una vez tengamos claro el área de trabajo que queremos eliminar utilizamos el siguiente código:

tf workspace /delete NombreArea;Usuario /s:http://TFServer/tfs/DefaultCollection /login:Usuario,Contraseña

Hay que tener en cuenta que todo el area de trabajo que se borre eliminará cualquier cambio pendiente que esta tuviera.

Método de extensión para clonar clase C#

En ocasiones necesitamos hacer una copia de una instancia, pero no queremos que nos arrastre los punteros a terceras, ya que queremos modificarlas sin que se vean alterados los valores del origen de la copia. La solución me la dio mi compañero Sergio Montes.

En principio montamos el método de extensión.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;

namespace DeepClone
{
    public static class ExtensionMethods
    {
        public static T CloneCompleto<T>(this T origen)
        {
            using (var memStream = new MemoryStream())
            {
                var formateadorBinario = new BinaryFormatter();
                formateadorBinario.Serialize(memStream, origen);
                memStream.Seek(0, SeekOrigin.Begin);
                return (T)formateadorBinario.Deserialize(memStream);
            }
        }
    }
}

El método es sencillo de comprender, simplemente se serializa en memoria y se desserializa en una clase nueva, por lo que el resultado es una copia exacta sin enlaces de punteros.
Gracias a los tipos genéricos, T, podremos llamar a este método desde cualquier clase. El siguiente paso es añadir la propiedad [Serializable] en la clase que queremos clonar.

    [Serializable]
    public class Prueba
    {
        public int Codigo { get; set; }
        public int Serie { get; set; }
        public double Base { get; set; }
        public double ImporteIVA { get; set; }
        public List<Prueba> ListaClasesHijos { get; set; }

        public Prueba Clone()
        {
            return this.CloneCompleto<Prueba>();
        }

    }

Como veis en el ejemplo simple tenemos una clase que se clona a sí misma.

Como Reiniciar en modo seguro a prueba de fallos con windows 8.1.

En ocasiones necesitamos reiniciar nuestra máquina en modo seguro para poder borrar alguna dll que en modo normal está bloqueada por el sistema. Pero cual es nuestra sorpresa cuando en Windows 8.1. al pulsar F8 no nos activa el menú de inicio para poder arrancar en nuestro esperado modo de fallos.

Buscando por internet descubrí un comando para habilitar este menú. Como siempre microsoft “haciendonos la vida más fácil”. Abre una consola con permisos de administrador y escribe lo siguiente:

bcdedit /set bootmenupolicy Legacy

Sentencia COALESCE, sustituye CASE para valores nulos.

Día a día se aprenden nuevas sentencias, funciones y atajos que nos facilitan la escritura de nuestro código. La sentencia que hoy he aprendido es COALESCE. Normalmente cuando he querido elegir entre valores de algunas columnas para desechar valores nulos he optado por utilizar la sentencia CASE de esta forma

CASE

WHEN (expression1 IS NOT NULL) THEN expression1

WHEN (expression2 IS NOT NULL) THEN expression2

ELSE expressionN

END

Pero resulta que existe la expresión COALESCE que eleije la primera aparición que no sea nula de de todas las que le ponemos

COALESCE(expression1,…n)

Puertos con C#. Envio y Recepción de Datos.

Aprenderemos a abrir el puerto, enviar datos y recibirlos. La recepción de datos puede ser de forma síncrona o asíncrona. Yo voy a enfocar todo el artículo a la forma de recepción síncrona, ya que necesito leer la trama y dejar de leer cuando este todo recepcionado, así que tendremos que ir analizando cada byte que recibimos.

En primer lugar abrimos el puerto:

    public void AbrirPuertoSerie(string Puerto,int Velocidad)
        {

            try
            {

                if (_PuertoSerie.IsOpen)
                    _PuertoSerie.Close();
                _PuertoSerie.PortName = Puerto;
                _PuertoSerie.BaudRate = Velocidad;

                _PuertoSerie.Parity = System.IO.Ports.Parity.None;
                _PuertoSerie.DataBits = 8;
                _PuertoSerie.StopBits = System.IO.Ports.StopBits.One;
                _PuertoSerie.Handshake = System.IO.Ports.Handshake.None;

                _PuertoSerie.RtsEnable = false;
                _PuertoSerie.DtrEnable = true;

                //_PuertoSerie.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
                //_PuertoSerie.ErrorReceived += new SerialErrorReceivedEventHandler(com_ErrorReceived);

                _PuertoSerie.Open();

            }
            catch (ArgumentOutOfRangeException Ex)
            {
                _Errores.add("AbrirPuertoSerie. " + Ex.Message);
            }
            catch (InvalidOperationException Ex)
            {
                _Errores.add("AbrirPuertoSerie. " + Ex.Message);
            }
            catch (ArgumentException Ex)
            {
                _Errores.add("AbrirPuertoSerie. " + Ex.Message);
            }
            catch (IOException Ex)
            {
                _Errores.add("AbrirPuertoSerie. " + Ex.Message);
            }
            catch (Exception ex)
            {
                _Errores.add("AbrirPuertoSerie. " + ex.Message);
            }

        }

Una vez abierto ya podremos hacer el envío de los datos.

Los datos, la trama, la construiremos con un List<byte> que es lo más cómodo de utilizar y el envío se produce sin errores. He tenido muchos problemas al enviar los datos como char, inexplicable.
Sigue leyendo