Web Deploy – config Transformation

Una de las utilidades que contamos los desarrolladores web en Visual Studio 2010 y que por mi experiencia veo que no se utiliza mucho. Es la transformación de ficheros de configuración.

A quien no le ha pasado que ha realizado un despliegue al entorno de producción y se ha dejado el modo debug activado o la cadena de conexión a la de test. Pues Visual Studio nos permite poder evitar esto de una manera muy fácil y además automática, para que no nos tengamos que preocupar de si lo hemos configurado todo correctamente para el despliegue.

Ficheros de Transformación

Una de las situaciones que habitualmente nos encontramos en los proyectos, es que tenemos que tener diferentes ficheros de configuración para cada uno de los entornos de los que contamos.

No es lo mismo hacer un despliegue para el entorno de Desarrollo que para Pre-Test o Producción. Por eso ahora disponemos de la posibilidad de modificar el fichero de configuración dependiendo de donde queramos publicar nuestra aplicación web.

Lo primero que tenemos que hacer es crear una configuración de compilación que la podemos definir por ejemplo para cada entorno en el que trabajaremos con las diferentes configuraciones.

Podemos crear una configuración nueva o copiar de otra existente.

Una vez que tengamos las configuraciones creadas, hacemos clic con el botón derecho en el fichero de configuración y añadimos los nuevos ficheros de transformación.

Tendemos que tener tantos ficheros de transformación como diferentes configuraciones necesitemos en nuestros despliegues.

¿Qué son los ficheros de Transformación?

Los ficheros de transformación, son ficheros XML que utilizan los atributos XML para especificar que se tienen que modificar o eliminar del fichero web.config.

Por ejemplo el fichero de transformación de la publicación en Release elimina el famoso atributo Debug=true.

 

1 <?xml version="1.0"?>
3 <system.web>
4 <compilation xdt:Transform="RemoveAttributes(debug)" />
5 </system.web>
6 </configuration>

 

XML-Document-Transform

Este espacio de nombres tiene dos propiedades Principales:

  • Locator:Se seleccionan los elementos que coinciden con la expresión XPath combinada.
    • Locator=”Match(key)” – Selecciona los elementos que concidan con el atributo key.
  • Transform:Especifica la transformación de elemento o elementos seleccionados con la propiedad locator.
    • Replace: Sustituye el elemento o primer elemento seleccionado por el informado.
    • Insert: Inserta un nuevo elemento como podría ser una nueva cadena de conexión, al final de la colección.
    • InsertBefore: Inserta un nuevo elemento justo antes del elemento seleccionado.
    • InsertAfter: Inserta un nuevo elemento justo después del elemento seleccionado.
    • Remove: Elimina el elemento o primer elemento seleccionado.
    • RemoveAll: Elimina todos los elementos seleccionados.
    • RemoveAttributes: elimina el atributo especificado de los elementos seleccionados.
    • SetAttributes: Modifica los atributos especificados de los elementos seleccionados.

Los ejemplos más utilizados serían:

  1.  
    1. Modificar el valor de una propiedad personalizada de la configuración por su clave.

 

1 <add key="UrlEscritura" value="http://test/ Solicitudes/ServicioEscritura.svc" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>

 

  1.  
    1. Modificar una cadena de conexión por su nombre: perfecto si atacamos a diferentes bases de datos en cada entorno.

 

1 <connectionStrings>
2 <add name="SqlCon" connectionString="Data Source=server;Initial Catalog=test;" providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
3 </connectionStrings>

 

  1.  
    1. Eliminar el famoso atributo de modo Debug cuando compliamos en Release:

 

1 <system.web>
2 <compilation xdt:Transform="RemoveAttributes(debug)" />
3 </system.web>

 

Conclusión

Si nos preocupamos un poco en tener diferentes configuraciones de compilación para nuestros entornos, además de facilitarnos los despliegues y su configuración de forma automática.

También nos evita los típicos errores por descuido que tantos problemas nos suelen dar en los despliegues.

Cross-Posting: http://mrubino.net 

 

 

Push con SingalR

Últimamente se está oyendo hablar mucho de SignalR en los en tornos de ASP.Net y no es para menos.

Los programadores web estamos acostumbrados a hacer peticiones al servidor “Pull” para poder consultar cualquier cosa y en más de una ocasión hemos tenido que tirar de un timer en el cliente para que cada X-tiempo consulte un recurso del servidor e ir informando al usuario del progreso de una tarea o de los datos que se tienen que actualizar constantemente.

Para evitar esto podríamos utilizar a día de hoy varias opciones como la API de html5 WebSocket que está en fase borrador y ha tenido algún problema de seguridad, podemos utilizar el servidor Openfire con el protocolo XMPP o servidor Node.js con la librería Nowjs . Pero la ventaja que proporciona SignalR frente los otros es que esta especialmente diseñado para aprovechar las características de las aplicaciones ASP.NET MVC tanto el lado del servidor como la parte cliente.

Como empezar

Para empezar tenemos que instalar la librería que tenemos disponible desde Nuget.

Tienes que tener en cuenta que tiene dependencias con la librería JQuery .

El Servidor

En el servidor solo necesitamos una clase que implemente Hub y si queremos hacer una devolución al cliente solo tenemos que añadir una expresión dinámica a Clients que se resolverá en tiempo de ejecución.

 

 
1 public class NotificationHub : Hub
2 {
3 public void Notificar(string valor)
4 {
5 Clients.AddValor("Informamos al cliente");
6 }
7 }

 

El cliente

Recordar la dependencia con JQuery y además hay que poner una referencia a “/Signalr/Hubs” que es donde se crearan los scripts dinámicamente para las llamadas al servidor.

 

 

1 <script type="text/javascript">// <![CDATA[
2 src</span>="/Scripts/jquery-1.7.1.js" type="text/javascript">
3 // ]]></script>
4 <script type="text/javascript">// <![CDATA[
5 src</span>="/Scripts/jquery.signalR.js" type="text/javascript">
6 // ]]></script>
7 <script type="text/javascript">// <![CDATA[
8 src</span>="/Signalr/Hubs" type="text/javascript">
9 // ]]></script>

 

 

1 $.connection.hub.start();
2 var hub = $.connection.notificationHub;
3 hub.AddValor = function (valor) {
4 alert(valor);
5 };

 

1. Abrimos la conexión con el servidor.
2. Inicializamos nuestro hub donde haremos las llamadas.
3. Definimos la función de devolución para actuar cuando el servidor nos informe.

Ya esta !!!! Es súper sencillo !!!!

EJEMPLO

Haré un pequeño ejemplo para que se vea toda su potencia en acción. Imaginaros un control de encuesta donde sea el servidor el que te informe que sus datos se han actualizado y solo permita votar una vez al usuario, toda la lógica estará en el servidor y no en la UI, de esta manera no mezclamos responsabilidades.
Utilizaré la librería jqplot.js para mostrar la gráfica de la encuesta en tiempo real.

Servidor

Primero crearé la parte del servidor donde estará la lógica de los votos.

  

01 public class NotificationHub : Hub
02 {
03 public void Notificar( string valor)
04 {
05 if (valor != null && Encuesta.Instance != null
06 && Encuesta.Datos.ContainsKey(valor))
07 {
08 var clientId = Context.ClientId;
09 if (Encuesta.Usuarios.Any(u => u == clientId))
10 {
11 // El usuario ya ha votado no hay que actuar
12 // ni informar de actualizaciones
13 }
14 else
15 {
16 Encuesta.Usuarios.Add(clientId);
17 Encuesta.Datos[valor]++;
18 var resultado = Encuesta.Datos.Keys.Select(
19 key => new List</pre>
20 ()
21 <pre>
22 {
23 key, Encuesta.Datos[key]
24 }).ToList();
25
26 // Informamos al cliente
27 Clients.AddValor(resultado);
28 }
29 }
30 }
31 }

 

Esta clase controla si el usuario ya ha votado y si no lo añade a la lista para no permitir votar la próxima vez que llame el mismo cliente y como se puede observar, tenemos acceso al identificador del cliente para controlar quien es el que hace la llamada, pero además podemos acceder al dentity para hacer un seguimiento más exhaustivo del usuario y sus credenciales.

Luego si el voto es de un elemento correcto le incrementa el número de votos y retorna a todos los clientes conectados los nuevos datos de la encuesta actualizada.

El cliente llamara a Notificar(valor) para informar del voto y estará en espera que el servidor actualice los datos con AddValor(resultado).

Cliente

Tendremos una vista con varios radio buttons para seleccionar las opciones de la encuesta y un botón que lanzara la llamada al servidor con la selección del usuario.

 

 

01 $(function () {
02 inicializarEncuesta();
03 $("#btnSendNotificacion").click(function () {
04 var voto = $('input:radio:checked').val();
05 hub.notificar(voto);
06 });
07 $.connection.hub.start();
08 var hub = $.connection.notificationHub;
09 hub.AddValor = function (valor) {
10 $.jqplot('chart1', [valor], chartOption()).replot();
11 };
12 });

 

Si el servidor devuelve nuevos datos “AddValor” entonces repintaremos el gráfico con la nueva información.

De esta manera todos los usuarios conectados a la encuesta reciben las actualizaciones en tiempo real.

Conclusión

SignalR es un Framework potente y fácil de utilizar que nos permite mantener conexiones abiertas con el servidor de ASP.NET.
Con este tipo de librerías podemos empezar a realizar aplicaciones realmente colaborativas y en tiempo real, donde se definen mejor las responsabilidades gracias a las llamadas Push y nos ayuda a no agregar lógica de negocios en nuestras UI.

 

Cross-Posting: http://mrubino.net 

 

 

Deserializar JSon a tipo anónimo .Net

En ciertas ocasiones podemos necesitar deserializar un objeto pasado desde un cliente en formato JSon a un tipo .net anónimo. Por ejemplo si utilizas MongoDB con el driver NORM y pretendes filtrar u ordenar de una manera dinámica, es difícil pasar estos objetos a la query para poder generar un filtro dinámico.

Para hacernos una idea esta sería una consulta paginada y con un filtro sencillo con NORM:

1 //NoRM anonymous objects:
2 return GetRepository().GetCollection("Personas")
3 .Find(
4 new { Nombre = Q.IsNotNull() }, //Where
5 new { Fecha = OrderBy.Descending }, //OrderBy
6 10, // Nº elementos de la secuencia "Skip"
7 0 // Primer elemento de la secuencia "Take"
8 );

 

Esta consulta nos devolvería las 10 primeras personas con Nombre que no sea null.

Tanto al utilizar los tipos anónimos como en las consultas LinQ se tiene que especificar la propiedad por la que se quiere filtrar u ordenar y eso nos limita a la hora de intentar hacer estas consultas de forma dinámica.

Parara hacer una prueba crearemos un tipo específico para utilizar en las consultas desde javaScript.

Lo ideal sería:

1 public class QueryRequest
2 {
3 public int Pagina { get; set; }
4 public int Registros { get; set; }
5 public object Orden { get; set; }
6 public object Filtro { get; set; }
7 }

 

Con este tipo nos pasarían como parámetros lel número de página, la cantidad de registros y además un object para filtrar y otro object para ordenar.

Pero esto no funciona porque NORM no lo reconoce como tipo anónimo y si lo intentamos pasar como string tampoco funciona.

Ahora solo nos queda intentar deserializar directamente nosotros el objeto JSON en un tipo anónimo y para eso utilizaremos el tipo dynamic que tenemos disponible desde c# 4.

Para eso solo tenemos que deserializar un texto con datos en formato JSon utilizandoJavaScriptSerializerque te permite utilizar un tipo T.

1 var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
2 var ObjetoAnonimo = jss.Deserialize(strJson);

 

Con estas dos líneas lo tenemos solucionado y el nuevo tipo podría quedar de esta manera para facilitar la entrada de los datos como string y la salida como objeto dinámico.

01 public class QueryRequest
02 {
03 public int Pagina { get; set; }
04 public int Registros { get; set; }
05
06 // input string - output dynamic
07 private string orden;
08 public dynamic Orden { get { return DeserializarJSon(orden); } set { orden = value; } }
09
10 // input string - output dynamic
11 private string filtro;
12 public dynamic Filtro { get { return DeserializarJSon(filtro); } set { filtro = value; } }
13
14 private dynamic DeserializarJSon(string strJson)
15 {
16 var jss = new JavaScriptSerializer();
17 dynamic resultado;
18 try
19 {
20 resultado = jss.Deserialize(strJson);
21 }
22 catch (Exception)
23 {
24 resultado = new { };
25 }
26 return resultado;
27 }
28
29 }

 

Ahora nuestro objeto es capaz de devolver un tipo anónimo al consultar la propiedad Filtro y Orden.

01 public IEnumerable FindFiltradoDinamico( QueryRequest datos )
02 {
03 //NoRM anonymous objects:
04 return GetRepository().GetCollection("Personas")
05 .Find(
06 datos.Filtro as object,
07 datos.Orden as object,
08 datos.Registros,
09 datos.Pagina * datos.Registros
10 );
11
12 }

 

Ahora si tenemos las consultas preparadas para aceptar parámetros dinámicos.

01 public ActionResult Index()
02 {
03 var datos = new QueryRequest()
04 {
05 Pagina = 0,
06 Registros = 10,
07 Filtro = " { Edad : { '$gt': 15 } } ", //mayor de 15 años
08 Orden = "{ Nombre : -1}" // 1 Ascendente - -1 Descendente
09 };
10
11 var f2 = repositoryPersona.FindFiltradoDinamico(datos);
12
13 return View();
14 }

 

 

Cross-Posting: http://mrubino.net

 

 

 

Vistas & View Engines en ASP.NET MVC

Partiendo de que la intención de MVC es separar las responsabilidades de cada componente, me gustaría explicar cual es la responsabilidad de las vistas y como utilizarlas en ASP.NET MVC.

Lo que primero nos choca a los programadores que procedemos de los formularios web, es que han desaparecido los eventos y el famoso ciclo de vida, y eso se debe precisamente que ASP.NET MVC es mucho más natural en los protocolos HTTP y HTML en su tratamiento.

Mvc vs WebForms

Como se puede apreciar en la imagen los formularios web se basaban en los eventos para procesar una petición, entrar en el ciclo de vida del documento, tratar el evento, pintar los controles y devolver el resultado.

Sin embargo las peticiones en MVC son mucho mas simples y respetuosas con el protocolo HTTP. La petición la recibe el motor de rutas que mediante la URL decide cual es el controlador que la debe procesar, el Controlador puede consultar al modelo si es necesario y posteriormente devuelve un ActionResult que puede ser un fichero, datos en formato JSon, una vista, etc.

Vistas

Como ya he comentado la vista encapsula la lógica de presentación y NO tiene que contener lógica de la aplicación ni código de recuperación de datos.

Las vistas no son ficheros físicos ligados a una URL como en los formularios web. Cuando queríamos consultar un formulario teníamos que poner su ruta física www.miaplicacion/personas.aspx En MVC es el controlador el que decide que vista servir y eso facilita que las url sean descriptivas y que los buscadores puedan indexar mejor las páginas de nuestra aplicación “SEO Friendly“.

ViewBag:

Las vistas pueden recibir datos desde el controlador gracias al ViewBag que devuelve un diccionario de datos dinámicos. La gran diferencia con ViewData de las versiones anteriores de MVC, es que ViewBag aprovecha la opción de c#4 para generar tipos dinámicamente y evita tener que hacer conversiones en la vista para obtener el tipo adecuado de los datos.

En el Controlador: Definimos la propiedad que queremos pasar a la vista y el dato

1 ViewBag.Message = "Welcome to ASP.NET MVC!";

 

En la vista: desde la vista recuperamos el dato de una forma muy fácil.

1 <h2>@ViewBag.Message</h2>

 

ViewData vs ViewBag: la gran diferencia es que ya no tenemos la necesidad de hacer conversiones de los datos para poder tratarlos correctamente

1 @*Tipo Fecha con tipos dinámicos*@
2 <h1>@ViewBag.FechaVieBag.ToShortDateString()</h1>
3
4
5 @*Tipo Fecha con ViewData*@
6 <h1>@(((DateTime)ViewData["Fecha"]).ToShortDateString())</h1>
7

 

Tipos de Vistas de las que disponemos:

  •   View Page: Vista principal.
  • LayoutView: Pagina Maestra.
  • ViewContentPage: Vista que utiliza una página Maestra predefinida.
  • Partial View: Vista que se utiliza desde otra vista y no se puede llamar directamente. Como se utilizaban los user controls en los webForms. La vista parcial tiene acceso a su ViewData y al dela vista primaria, pero las actualizaciones de los datos de la vista parcial solo afectan a su viewData y no a la de la vista primaria.

View Engines

ASP.NET MVC utiliza view engines para generar las vistas y desde MVC3 disponemos de dos motores de vistas incluidos para utilizar directamente.

  • ASPX: Es el motor de vistas de ASP.NET con tipos personalizados “ViewPage, ViewMasterPage y ViewUserControl” que heredan de los tipos de páginas existentes .aspx, .ascx, .master.
  • Razor: Motor de vistas más cercano para los programadores de C# o VB
  • Otros:

Convenciones

Hay un par de convenciones que nos afectan al trabajar con las vistas y nos ahorran interminables ficheros de configuración.

  • Return View(): no tenemos que especificar explícitamente que vista estamos devolviendo, porque si no lo hacemos utilizará el nombre de la acción para encontrar la vista. Este ejemplo retorna la vista Create.
1 // GET: /Peliculas/Create
2 public ActionResult Create()
3 {
4 return View();
5 }

 

  • Estructura Vista – controlador: Los controladores se tendrán que llamar MyNombreController y las vistas estarán en una carpeta llamada MyNombre dentro de la carpeta Views. De esta manera el controlador encontrará la vista sin problemas.

En esta imagen las extensiones de los ficheros son .cshtml porque he utilizado el motor de vista Razor en C#, si utilizara VB seria .vbhtml y si utilizara el motor de vista ASPX sería (.aspx, .ascx, .Master)

Creo que con esto hemos visto todo lo que tiene que ver con las vistas en MVC 3

Cross-Posting: http://mrubino.net

 

 

[webCast] Auges MVC 3 + Html5 + CSS3

Os recuerdo que este lunes grabaremos el webCast sobre MVC 3 y Html5 con Visual Studio 2010 con la gente de Auges el grupo de usuarios de ASp.Net Spain.

Después de participar en el Barcelona Developer Conference tengo la oportunidad de repetir evento pero esta ves online y con la posibilidad de hacerla completa y sin las restricciones de tiempo que mormalmente nos encontramos en los eventos presenciales.

Podéis acceder al registro en https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032500294&Culture=es-ES

Ademas recordaros que el Martes desde SecondNug tenéis otro webCast de Lluis Franco MVP de Visual C# sobre Mejorar el rendimiento con programación paralela.

Espero Veros a Todos 😉

Cross-Posting: http://mrubino.net

 

Material BcnDevConf MVC + HTML

Esta semana se ha realizado el primer Barcelona Developer Conference 2011 y espero que no sea la última porque nos ha dejado a todos un gran sabor de boca y una innumerable lista de nuevos contactos.

Tenéis disponible el material y la presentación para que podáis jugar un poco con el ejemplo, ya que no tuvimos mucho tiempo para verlo todo.

Proyecto de Ejemplo : Folder

Para los que os supo a poco y tenga ganas de ver la charla completa seguro que no tendremos problemas de tiempo en el webCast que haremos el próximo lunes 28 en el grupo de usuarios de ASP.NET Spain

Nos vemos el Lunes

Cross-Posting:  http://mrubino.net

 

 

 

[Evento] BDNDevConf: MVC + JQuery + Html5

 

Me encuentro en el CommunityDay 2011 de Fuengirola y desconecto un segundo de tanto networking, charlas y el hack-a-ton, para recordar que esta semana tendremos el evento Barcelona Developers Conference ’11. Tres intensos días con 18 Master Sessions, 32 Sesiones, 2 Mesas redondas, 3 WorkShops entre otras cosas. Una oportunidad impresionante para coincidir todo tipo de profesionales del sector y ampliar nuestra red de contactos.

Ademas no desaprovechar la oportunidad para hacer un poco de autobombo y recordaros que el viernes 18 yo mismo daré una sesión sobre MVC, JQuery y HTML5.

Para más información podéis consultar la agenda en

http://bcndevcon.org/en/content/scheduling 

Espero que podáis venir al evento.

Cross-posting: http://mrubino.net/ 

 

 

Cargar scripts bajo demanda con JQuery

Quien no se ha encontrado alguna vez que se va añadiendo potencia y dinamismo a las páginas web con diferentes librerías y al final tenemos una página que carga un montón de ficheros que a veces no se utilizan porque el usuario no ha necesitado esa opción en ese momento en concreto. Y con la aparición hace tiempo de los MastersPages se ha aumentado esta práctica tanto si hablamos de webForms como con MVC. Pues gracias a JQuery podemos cargar las dependencias o ficheros .js que necesitemos solo cuando realmente se necesite esa funcionalidad de una forma dinámica y no tener que descargar todo al cargar la página. Solo tendremos que utilizar getScript para cargar un script remoto con una llamada asíncrona “AJAX” y además no tendremos problemas con cross-domain, porque utiliza JsonP para cargar el script entre dominios. Pero que mejor que un ejemplo para que quede claro el concepto.

Ejemplo:

Imaginaros que tenemos una aplicación con una búsqueda avanzada oculta que utiliza JQuery, un autocomplete y un watermark.

  • El botón para mostrar el formulario.

  • Se muestra el contenido del formulario al hacer click en el botón

  • El autocomplete está disponible


Lo normal sería cargar todos los scripts que necesitamos al cargar la página.

<script type=»text/javascript» src=»Scripts/jquery-1.4.1.min.js»></script> <script type=»text/javascript» src=»Scripts/jquery.watermark.min.js»></script><script type=»text/javascript» src=»Scripts/JScript.js»></script>


Pero sería mucho más optimo cargar las librerías del watermark y el autocomplete solo cuando se muestra el formulario de búsqueda avanzada. ¿ NO ?

Pues para cargar los script bajo demanda sería:

$(‘#btnBusqueda’).click(function () { $.getScript(«Scripts/jquery-autocomplete.js», function (data, estado) { if (estado == ‘success’) { $(«#tags»).autocomplete({ source: availableTags }); } else{ alert(«Error al cargar la librería autocomplete»); } }); $.getScript(«Scripts/jquery.watermark.min.js», function (data, estado) { if (estado == ‘success’) { $(‘#tags’).watermark(‘Buscar…’); } else{ alert(«Error al cargar la librería watermark»); } }); $(‘.busquedaAvanzada’).show(); });


Como se puede comprobar solo se cargan las librerías si el usuario hace click en el botón para ver el formulario de búsqueda, entonces se carga el script y se utiliza una función anónima la cual utiliza dos parámetors con el contenido del script y el estado de la solicitud.

Posibles estados:

  • “timeout”
  • “error”
  • “notmodified”
  • “success”
  • “parsererror”

Con este sencillo ejemplo podemos ver cómo podemos cargar scripts bajo demanda.

Instalar Windows 8 sin USB/DVD de inicio

Esta semana ha habido un gran revuelo con el BUILD y todo el mundo se ha vuelto loco intentando ser el primero en instalar windows 8 y poder probar la versión Preview Development.

Yo he tenido bastantes problemas para hacer la instalación desde un USB/DVD de arranque como explica Scott Hanselman en su blog sobre todo porque no quería comprar un USB de 16 GB solo para poder probar win8. La única opción que me quedaba era instalar la ISO en una máquina virtual como VirtualBox, pero tener un disco virtual de arranque es mucho más rápido y utilizas mejor los recursos del sistema, solo tienes que seleccionar el sistema operativo que quieres utilizar al encender el ordenador.

Después de muchas pruebas mi compañero Alberto Diaz me paso un link para poder hacer la instalación desde PowerShell que funciona de maravilla y sin necesidad de tener el famoso USB de 16 GB para realizar la instalación.

Como esta solución me ha parecido muy interesante recompilaré para la correcta instalación teniendo en cuenta que el origen de esta información la he sacado de SharpFellows .  

  1. Necesitamos la ISO de Win8 Developer Preview para instalar.
  2. Utilizar una aplicación como Virtual Clone Drive para utilizar directamente la ISO.
  3. Los Scripts de Instalación de naeemkhedarun que está en GitHub.
  4. Utilizar los Scripts que tienen tres parámetros ejecutar –>cmd –> PowerShell
    1. El path donde se creará el disco duro virtual «VHD»
    2. El tamaño de la imagen.
    3. La letra de la unidad del disco «Que no esté en Uso»
// Donde tengais los ficheros
C:projectsCreateWindows8VHD> Import-Module .Create-Windows8VHD.ps1
C:projectsCreateWindows8VHD> Create-Windows8VHD 
        "C:vhdwindows8preview.vhd" "30000" "X" 

      5.     Finalmente poner el nuevo disco como unidad de arranque.

//En mi máquina e instalación
C:WindowsSystem32bcdboot.exe X:Windows

Una cosa que te puede pasar la primera vez que utilizas PowerShell es que te da un error de permisos de ejecución de los scripts. Esto se soluciona con el mismo PowerShell.

Set-ExecutionPolicy RemoteSigned

Todo listo 😉      

Cross-Posting: http://mrubino.net 

 

[Tip] Intellisense entre ficheros .Js

Dedicado a mi colega Pablo Nuñez que últimamente le veo muy desesperado con el uso de JavaScript. Pablo nunca pierdas la esperanza!!! Este truco es muy sencillo y nos sirve para poder tener la referencia de un fichero script desde otro fichero script y solo tenemos que insertar el path del fichero que queremos tener la referencia con tres barras estilo comentario.

Pero eso no es todo, también podemos personalizar la información que queremos mostrar como en el resto de nuestro código de la aplicación.

 

Espero que este truco sea de utilidad 😉  

Cross-Posting: http://mrubino.net/