<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>El Blog de Albert Mata &#187; Batch</title>
	<atom:link href="http://www.albertmata.net/category/batch/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.albertmata.net</link>
	<description>// anotaciones de análisis y programación en mi día a día como consultor de software</description>
	<lastBuildDate>Mon, 03 Aug 2009 19:22:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Ambrosio o cómo crear un servicio de Windows obediente en .NET.</title>
		<link>http://www.albertmata.net/2008/07/ambrosio-o-como-crear-un-servicio-de-windows-obediente-en-net/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ambrosio-o-como-crear-un-servicio-de-windows-obediente-en-net</link>
		<comments>http://www.albertmata.net/2008/07/ambrosio-o-como-crear-un-servicio-de-windows-obediente-en-net/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 16:42:50 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[installutil]]></category>
		<category><![CDATA[servicio windows]]></category>
		<category><![CDATA[timer]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=61</guid>
		<description><![CDATA[Últimamente he estado programando un servicio de Windows para que el sistema realice de manera periódica y en segundo plano unas determinadas tareas. En mi caso concreto se trata de replicar unas determinadas tablas desde una base de datos Oracle hacia otra MySQL con una determinada periodicidad en función de cada tabla (unos datos son [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-62" title="servicio" src="http://www.albertmata.net/public/uploads/2008/07/servicio.jpg" alt="" width="339" height="199" />Últimamente he estado programando un servicio de <strong>Windows </strong>para que el sistema realice de manera periódica y en segundo plano unas determinadas tareas. En mi caso concreto se trata de replicar unas determinadas tablas desde una base de datos <strong>Oracle </strong>hacia otra <strong>MySQL </strong>con una determinada periodicidad en función de cada tabla (unos datos son más críticos y necesitan actualizarse cada hora, otros menos variables los actualizamos una vez al día durante las horas valle de actividad). El caso es que con <strong>VisualBasic.NET</strong> me ha resultado bastante sencillo crearlo y después instalarlo, así que paso a explicar un ejemplo de cómo hacer un sencillo servicio de Windows.<br />
<span style="color: #333399;"><span style="text-decoration: underline;"><strong><br />
Paso 1. Creamos el proyecto.</strong></span></span></p>
<p>Para empezar simplemente iniciamos <strong>VisualStudio.NET</strong> (en mi caso 2005) y seleccionamos la opción para crear un nuevo proyecto. Ahí seleccionamos <strong>Servicio de Windows</strong>, le damos un nombre agradable (a poder ser más que <strong>WindowsService1</strong>, por ejemplo <strong>ServicioAlertas</strong>) y aceptamos. Nos aparecerá directamente la clase <strong>Service1.vb</strong> que también podemos renombrar a algo más intuitivo como <strong>clsAlert.vb</strong>.</p>
<p><span style="color: #333399;"><span style="text-decoration: underline;"><strong>Paso 2. Agregamos un instalador.</strong></span></span></p>
<p>En la vista diseño de la clase que se nos ha creado hacemos clic con el botón derecho del ratón y seleccionamos la opción <strong>Agregar instalador</strong>. Con esto se nos creará la clase <strong>ProjectInstaller.vb</strong> que contiene dos controles: <strong>ServiceInstaller1</strong> y <strong>ServiceProcessInstaller1</strong>. En mi caso renombro estos dos controles simplemente para eliminarles el 1 final (maniático que es uno). Del código de <strong>ProjectInstaller.vb</strong> nos olvidaremos por completo, pero vamos a hacer algún ajuste en las propiedades de estos dos controles.</p>
<p><span style="color: #333399;"><span style="text-decoration: underline;"><strong>Paso 3. Configuramos el instalador.</strong></span></span></p>
<p>En el control <strong>ServiceInstaller</strong> modificamos las propiedades <strong>DisplayName </strong>y <strong>ServiceName </strong>para dejarlas ambas en <strong>ServicioAlertas</strong>. Modificamos también la propiedad <strong>StartType </strong>para dejarla en <strong>Automatic</strong>. Esto último sirve para que después cuando instalemos el servicio, éste quede puesto para que arranque automáticamente al iniciarse el sistema operativo. Si no se desea este comportamiento, ajustar esta propiedad según convenga. Es decir:</p>
<div class="code">DisplayName&#58;&#160;ServicioAlertas<br />
ServiceName&#58;&#160;ServicioAlertas<br />
StartType&#58;&#160;&#160;&#160;Automatic</div>
<p>En el control <strong>ServiceProcessInstaller </strong>modificamos la propiedad <strong>Account </strong>para dejarla en <strong>LocalSystem</strong>. Esto indica qué tipo de cuenta se utilizará para ejecutar el servicio. Podemos dejarla en <strong>User</strong>, pero después al instalar el servicio pedirá cuenta de usuario y contraseña, así que yo recomiendo pasarla a <strong>LocalSystem</strong>. Así pues:</p>
<div class="code">Account&#58;&#160;&#160;&#160;&#160;&#160;LocalSystem</div>
<p>Con la clase <strong>ProjectInstaller.vb</strong> hemos terminado ya por completo, ahora nos centraremos en <strong>clsAlert.vb</strong>.</p>
<p><span style="color: #333399;"><span style="text-decoration: underline;"><strong>Paso 4. Programamos el servicio.</strong></span></span></p>
<p>Accedemos al código de la clase <strong>clsAlert.vb</strong> y observamos que por defecto ya se nos han generado dos métodos: <strong>OnStart </strong>y <strong>OnStop</strong>. Está claro para lo que sirven, ¿no? Eso es, para configurar qué hacer y cómo para arrancar y detener el servicio. Personalmente no utilizo el <strong>OnStop </strong>para nada, así que no hablaré de él, pero por supuesto el que esté interesado puede buscar más información en la propia ayuda del <strong>IDE </strong>o en internet. Me voy a centrar en el <strong>OnStart </strong>y voy a ponerle un temporizador para que cada 5 segundos me escriba en un log la hora actual. Sí, lo sé, es un servicio de alertas mediocre, pero servirá como ejemplo de código sencillo con el que programar un servicio y hacer uso, además, de un temporizador (cosa terriblemente útil en ocasiones).</p>
<p>Muestro el código íntegro que dejo pues en la clase <strong>clsAlert.vb</strong>:</p>
<div class="code">&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Author&#58;&#160;&#160;&#160;&#160;&#160;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#39;&#160;Date&#58;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;20080723<br />
&#39;&#160;Description&#58;&#160;Class&#160;to&#160;show&#160;how&#160;to&#160;create&#160;a&#160;Windows&#160;service&#160;and&#160;how<br />
&#39;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;to&#160;work&#160;with&#160;a&#160;timer&#46;&#160;<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
Public&#160;Class&#160;clsAlert</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Attributes&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;DBTimer&#160;As&#160;System&#46;Timers&#46;Timer</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Starts&#160;service&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Protected&#160;Overrides&#160;Sub&#160;OnStart&#40;ByVal&#160;args&#40;&#41;&#160;As&#160;String&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Creating&#160;timer&#160;with&#160;interval&#160;&#61;&#160;5000&#160;milisec&#160;&#61;&#160;5&#160;seconds&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DBTimer&#160;&#61;&#160;New&#160;System&#46;Timers&#46;Timer&#40;5000&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DBTimer&#46;Enabled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AddHandler&#160;DBTimer&#46;Elapsed&#44;&#160;AddressOf&#160;Me&#46;ShowAlert<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Stops&#160;service&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Protected&#160;Overrides&#160;Sub&#160;OnStop&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Void&#44;&#160;as&#160;I&#39;m&#160;not&#160;using&#160;this&#160;method&#46;<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Main&#160;process&#160;executed&#160;every&#160;time&#160;DBTimer&#160;gives&#160;a&#160;signal&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;ShowAlert&#40;ByVal&#160;source&#160;As&#160;Object&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;ByVal&#160;e&#160;As&#160;System&#46;Timers&#46;ElapsedEventArgs&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DBTimer&#46;Enabled&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;LogFile&#160;As&#160;New&#160;System&#46;IO&#46;StreamWriter&#40;&#34;C&#58;&#92;log&#46;txt&#34;&#44;&#160;True&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LogFile&#46;WriteLine&#40;&#34;Alerta&#160;www&#46;albertmata&#46;net&#160;&#45;&#160;&#34;&#160;&#38;&#160;Date&#46;Now&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LogFile&#46;Close&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DBTimer&#46;Enabled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>End&#160;Class</p></div>
<p>Con esto tenemos terminado nuestro servicio de <strong>Windows</strong>. Ahora sólo nos falta instalarlo.</p>
<p><span style="color: #333399;"><span style="text-decoration: underline;"><strong>Paso 5. Generamos el ejecutable.</strong></span></span></p>
<p>Generamos el ejecutable de nuestro servicio (<strong>Generar </strong>o <strong>Volver a generar</strong>). A partir de aquí no necesitamos más el <strong>IDE</strong>, de modo que podemos cerrarlo. A partir de ahora sólo necesitamos el <strong>.exe</strong> que se nos acaba de generar y un par de archivos <strong>.bat </strong>que vamos a crear a continuación (podríamos no generarlos y escribir las instrucciones directamente en línea de comandos, pero a mí me resulta más cómodo hacerlo en archivos <strong>batch</strong>). El archivo <strong>.exe</strong> (que encontramos en la carpeta <strong>bin/Release</strong> de nuestro proyecto <strong>ServicioAlertas</strong>) lo copiaremos en una ruta más corta (<strong>C:\</strong>). Y los dos archivos <strong>.bat</strong> que necesitamos son los siguientes:</p>
<p><strong>Instalador.bat</strong></p>
<div class="code">C&#58;&#92;WINDOWS&#92;Microsoft&#46;NET&#92;Framework&#92;v2&#46;0&#46;50727&#92;InstallUtil&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#34;C&#58;&#92;ServicioAlertas&#46;exe&#34;<br />
pause</div>
<p><strong>Desinstalador.bat</strong></p>
<div class="code">C&#58;&#92;WINDOWS&#92;Microsoft&#46;NET&#92;Framework&#92;v2&#46;0&#46;50727&#92;InstallUtil&#160;&#47;U<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#34;C&#58;&#92;ServicioAlertas&#46;exe&#34;<br />
pause</div>
<p>En ambos las dos primeras líneas deben ser una única línea continuada (el ancho del blog no lo permite) y la ruta de la aplicación <strong>InstallUtil </strong>puede variar ligeramente en función de la versión del <strong>Framework </strong>que estemos utilizando. Basta con verificarlo con el <strong>Explorador de Windows </strong>y modificarla según convenga.</p>
<p>Para lo que sirven está claro: uno instala el servicio y el otro lo desinstala.</p>
<p><span style="color: #333399;"><span style="text-decoration: underline;"><strong>Paso 6. Instalamos el servicio.</strong></span></span></p>
<p>Simplemente ejecutamos el archivo <strong>Instalador.bat</strong> y se nos abrirá una ventana de línea de comando con el proceso de la instalación terminando exitosamente. Ahora nos vamos a <strong>Panel de control - Herramientas administrativas - Servicios</strong> y encontraremos nuestro servicio <strong>ServicioAlertas</strong>. Lo iniciamos y observaremos al cabo de pocos segundos que en la ruta <strong>C:\</strong> se nos ha creado un archivo <strong>log.txt</strong>. Si dejamos el servicio un rato funcionando y después lo detenemos veremos que este archivo ha quedado más o menos así:</p>
<div class="code">Alerta&#160;www&#46;albertmata&#46;net&#160;&#45;&#160;23&#47;07&#47;2008&#160;21&#58;12&#58;18<br />
Alerta&#160;www&#46;albertmata&#46;net&#160;&#45;&#160;23&#47;07&#47;2008&#160;21&#58;12&#58;23<br />
Alerta&#160;www&#46;albertmata&#46;net&#160;&#45;&#160;23&#47;07&#47;2008&#160;21&#58;12&#58;28<br />
Alerta&#160;www&#46;albertmata&#46;net&#160;&#45;&#160;23&#47;07&#47;2008&#160;21&#58;12&#58;33<br />
Alerta&#160;www&#46;albertmata&#46;net&#160;&#45;&#160;23&#47;07&#47;2008&#160;21&#58;12&#58;38</div>
<p><span style="color: #333399;"><span style="text-decoration: underline;"><strong>Paso 7. Desinstalamos el servicio.</strong></span></span></p>
<p>Si en algún momento queremos desinstalar el servicio (si es tan poco útil como <strong>ServicioAlertas </strong>seguro que querremos) solo debemos ejecutar <strong>Desinstalador.bat</strong> y el servicio quedará desinstalado (tendremos que refrescar la lista de servicios para ver que efectivamente así es).</p>
<p>Con esto queda visto el tema de los servicios de <strong>Windows</strong>. En internet se puede encontrar mucha otra información al respecto (<a href="http://www.codeguru.com/vb/gen/vb_system/services/article.php/c4825/" target="_blank">p.ej. ésta en CodeGuru</a>) en la que nos alertan de no utilizar <strong>MsgBox</strong> y similares en un servicio porque suelen dar problemillas. <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/07/ambrosio-o-como-crear-un-servicio-de-windows-obediente-en-net/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Formato no disponible en Snapshot de Access.</title>
		<link>http://www.albertmata.net/2008/06/formato-no-disponible-en-snapshot-de-access/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=formato-no-disponible-en-snapshot-de-access</link>
		<comments>http://www.albertmata.net/2008/06/formato-no-disponible-en-snapshot-de-access/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 07:10:14 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Access]]></category>
		<category><![CDATA[Batch]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[snapshot]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=32</guid>
		<description><![CDATA[Hace un tiempo, cuando me dedicaba fundamentalmente a programar aplicaciones en Access, me encontré con un problema que irremediablemente todos mis clientes sufrían tarde o temprano. Es un problema que se refiere a las versiones XP y 2003 (ignoro si alguna más) y que ocurre cuando se quiere generar un informe en formato Snapshot. Este [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-33" title="snapshot" src="http://www.albertmata.net/public/uploads/2008/06/snapshot.jpg" alt="" width="253" height="199" />Hace un tiempo, cuando me dedicaba fundamentalmente a programar aplicaciones en <strong>Access</strong>, me encontré con un problema que irremediablemente todos mis clientes sufrían tarde o temprano. Es un problema que se refiere a las versiones <strong>XP</strong> y <strong>2003</strong> (ignoro si alguna más) y que ocurre cuando se quiere generar un informe en formato <strong>Snapshot</strong>. Este formato es muy útil para exportar informes en archivos <strong>.snp</strong> que se pueden visualizar desde prácticamente cualquier ordenador (y si no existe un <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b73df33f-6d74-423d-8274-8b7e6313edfb&amp;displaylang=en" target="_blank">visualizador gratuito de <strong>Microsoft</strong></a>).</p>
<p>Bien, el problema increíblemente reside en que al instalar <strong>Microsoft Access</strong> en español, la instalación crea una clave en el registro de <strong>Windows</strong> (<strong>regedit.exe</strong>) con la descripción en castellano:</p>
<div class="code">snp,,1,Formato Snapshot (*.snp),0</div>
<p>Pero cuando el propio <strong>Access</strong> busca el valor para esa clave espera encontrarlo en inglés:</p>
<div class="code">snp,,1,Snapshot Format (*.snp),0</div>
<p>Y al no encontrarlo muestra un mensaje diciendo que el formato en cuestión no está disponible. O sea, una chapuza monumental de los señores de <strong>Microsoft</strong>, sí.</p>
<p>Para solucionar esto simplemente hay que cambiar la entrada correspondiente en el registro de <strong>Windows</strong> para cambiar el primer valor por el segundo. Ojito, todos sabemos que puede ser crítico cambiar cosas en dicho registro, así que cada cual sabrá lo que hace (pero este cambio es bastante inofensivo, eso sí <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ). En cualquier caso la entrada a modificar es la siguiente para <strong>Access XP</strong>:</p>
<div class="code">HKEY_LOCAL_MACHINE\_<br />
&#160;&#160;&#160;&#160;&#160;SOFTWARE\Microsoft\Office\10.0\Access\Report Formats</div>
<p>Y esta otra para <strong>Access 2003</strong>:</p>
<div class="code">HKEY_LOCAL_MACHINE\_<br />
&#160;&#160;&#160;&#160;&#160;SOFTWARE\Microsoft\Office\11.0\Access\Report Formats</div>
<p>Y la entrada concreta a la que hay que cambiarle el valor es <strong>Snapshot Format</strong>.</p>
<p>A mis clientes solía enviarles un archivo <strong>.bat</strong> para facilitarles la modificación, que consistía simplemente en la instrucción:</p>
<div class="code">REG ADD &#34;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\<br />
Office\11.0\Access\Report Formats&#34; /v &#34;Snapshot Format&#34; /d &#34;snp,<br />
,1,Snapshot Format(*.snp),0&#34; /f</div>
<p>Todo junto en la misma línea y sin espacios en los saltos de línea, ¿ok? Ah, y en donde pone <strong>11.0</strong> cambiarlo por <strong>10.0</strong> cuando la versión de <strong>Access</strong> sea la <strong>XP</strong>.</p>
<p>Por último añadir que en mi caso el uso del formato <strong>Snapshot</strong> era como paso intermedio para la creación de archivos <strong>PDF</strong> directamente desde <strong>Access</strong> sin necesidad de tener instalada ninguna impresora <strong>PDF</strong>, utilizando para ello la magnífica herramienta de <strong><a href="http://www.lebans.com" target="_blank">Lebans</a></strong>.</p>
<p><strong>Actualización:</strong> Iván aporta amablemente en los comentarios de esta misma entrada que en su caso para que pasara a funcionarle tuvo que cambiar el valor en castellano por este otro:</p>
<div class="code">Formats\snp,,1,Snapshot Format (*.snp),0</div>
<p>Es decir, añadiéndole el <strong>Formats\</strong> delante. Así que si estáis intentando resolver este problema y con las indicaciones del post no se os resuelve, no dejéis de probar también esta alternativa.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/06/formato-no-disponible-en-snapshot-de-access/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Copias de seguridad en MySQL con mysqldump.</title>
		<link>http://www.albertmata.net/2008/06/copias-de-seguridad-en-mysql-con-mysqldump/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=copias-de-seguridad-en-mysql-con-mysqldump</link>
		<comments>http://www.albertmata.net/2008/06/copias-de-seguridad-en-mysql-con-mysqldump/#comments</comments>
		<pubDate>Thu, 05 Jun 2008 18:54:34 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[copias de seguridad]]></category>
		<category><![CDATA[gnu-gpl]]></category>
		<category><![CDATA[mysqldump]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=30</guid>
		<description><![CDATA[En los pocos días de vida que tiene este blog es posible que haya mencionado ya que en el proyecto en el que estoy trabajando actualmente estamos utilizando una base de datos MySQL. Sí, lo sé, unas cuantas veces llevo ya... pero es que realmente va muy bien, estamos muy contentos con sus prestaciones hasta [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-31" title="mysqldump" src="http://www.albertmata.net/public/uploads/2008/06/mysqldump.jpg" alt="" width="233" height="118" />En los pocos días de vida que tiene este blog es posible que haya mencionado ya que en el proyecto en el que estoy trabajando actualmente estamos utilizando una base de datos <strong>MySQL</strong>. Sí, lo sé, unas cuantas veces llevo ya... pero es que realmente va muy bien, estamos muy contentos con sus prestaciones hasta la fecha. Se está mostrando rápida y muy fiable... y todo ello con una licencia <strong>GPL</strong>, no lo olvidemos.</p>
<p>Bueno, el caso es que como es evidente, cuando trabajamos con cualquier sistema tenemos que tener muy bien previsto un método decente de copias de seguridad. En el caso de <strong>MySQL</strong> tenemos varias alternativas, pero la que a mí más me ha convencido ha sido la herramienta <strong>mysqldump</strong>. Es realmente sencilla de utilizar y tremendamente funcional. Su funcionamiento exacto con las decenas de opciones que admite se puede encontrar en el propio <a href="http://dev.mysql.com/doc/refman/5.0/en/mysqldump.html" target="_blank">manual de referencia de MySQL</a>. No requiere instalación alguna, simple y llanamente que dispongamos del archivo <strong>mysqldump.exe</strong> que conseguiremos sin problemas en la página oficial de <strong>MySQL</strong> y que si hemos instalado el servidor <strong>MySQL</strong> probablemente tendremos ya en nuestro equipo.</p>
<p>La herramienta <strong>mysqldump</strong> nos genera archivos con extensión <strong>.sql</strong> que incluyen -según hayamos configurado- las instrucciones necesarias para restaurar una base de datos entera -o todas las que tengamos en el servidor <strong>MySQL</strong>-, desde su creación hasta la adición de los datos pasando por la creación de las tablas. Realmente completito. Para una restauración sólo habría que hacer algo así en una línea de comandos (<strong>localhost</strong> o servidor según corresponda):</p>
<div class="code">mysql -u root -p -h localhost &lt; C:\archivo_backup.sql</div>
<p>No obstante lo que quiero explicar hoy es cómo he automatizado estas copias de seguridad que hago con <strong>mysqldump</strong> a través de un archivo <strong>batch</strong>. Expongo código y después lo comento.</p>
<div class="code">&#64;echo&#160;off</p>
<p>set&#160;path&#95;mysqldump&#61;&#34;C&#58;&#92;Program&#160;Files&#92;MySQL&#92;MySQL&#160;Server&#160;5&#46;0&#92;bin&#34;<br />
set&#160;path&#95;backups&#61;&#34;&#92;&#92;99&#46;24&#46;13&#46;29&#92;BBDD&#92;Backups&#34;<br />
set&#160;user&#61;root<br />
set&#160;password&#61;mi&#95;password<br />
set&#160;host&#61;99&#46;24&#46;13&#46;26</p>
<p>if&#160;&#37;time&#58;&#126;0&#44;2&#37;&#160;GEQ&#160;10&#160;goto&#160;&#58;DespuesDeLas10</p>
<p>&#58;AntesDeLas10<br />
&#37;path&#95;mysqldump&#37;&#92;mysqldump&#160;&#45;&#45;user&#61;&#37;user&#37;&#160;&#45;&#45;password&#61;&#37;password&#37;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#45;h&#160;&#37;host&#37;&#160;&#45;&#45;databases&#160;db&#95;offers&#160;&#45;&#45;single&#45;transaction&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#62;&#160;&#37;path&#95;backups&#37;&#92;backup&#95;&#37;date&#58;&#126;6&#44;4&#37;&#37;date&#58;&#126;3&#44;2&#37;&#37;date&#58;&#126;0&#44;2&#37;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#95;0&#37;time&#58;&#126;1&#44;1&#37;&#37;time&#58;&#126;3&#44;2&#37;&#46;sql<br />
goto&#160;&#58;Salir</p>
<p>&#58;DespuesDeLas10<br />
&#37;path&#95;mysqldump&#37;&#92;mysqldump&#160;&#45;&#45;user&#61;&#37;user&#37;&#160;&#45;&#45;password&#61;&#37;password&#37;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#45;h&#160;&#37;host&#37;&#160;&#45;&#45;databases&#160;db&#95;offers&#160;&#45;&#45;single&#45;transaction&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#62;&#160;&#37;path&#95;backups&#37;&#92;backup&#95;&#37;date&#58;&#126;6&#44;4&#37;&#37;date&#58;&#126;3&#44;2&#37;&#37;date&#58;&#126;0&#44;2&#37;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#95;&#37;time&#58;&#126;0&#44;2&#37;&#37;time&#58;&#126;3&#44;2&#37;&#46;sql<br />
&#58;Salir</p></div>
<p>Antes que nada, comentar que las líneas que comienzan por <strong>%path</strong>... aparecen aquí cortadas por temas de espacio (en píxeles, no en bytes <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) en el blog, pero en realidad deben formar una sola línea que termina con <strong>.sql</strong>. Debe haber un espacio entre <strong>%password%</strong> y <strong>-h</strong> y después otro entre <strong>transaction</strong> y <strong>&gt; %path_</strong>, pero en cambio la última linea va sin espacio (<strong>%date:~0,2%_0%time</strong> va todo seguido, ¿ok?).</p>
<p>Paso a explicarlo. Las primeras cinco líneas después del archiconocido <strong>@echo off</strong> son asignaciones de valores a las variables que después utilizaremos. Es la parte de configuración del archivo <strong>batch</strong>.</p>
<p>1) <strong>path_mysqldump</strong> contiene la ruta del directorio donde se encuentra el archivo <strong>mysqldump.exe</strong>.</p>
<p>2) <strong>path_backups</strong> contiene la ruta del directorio donde se almacenará la copia de seguridad, en este ejemplo he puesto una carpeta en un servidor.</p>
<p>3) <strong>user</strong> es el usuario con el que se ejecutará <strong>mysqldump</strong>. Parece una perogrullada, pero hay que tener en cuenta que debe disponer de permisos suficientes, aunque no es necesario que sea el usuario <strong>root</strong> (de hecho mucho mejor si no lo es, ya que así no quedará en un archivo <strong>batch</strong> visualizable el password del usuario <strong>root</strong>).</p>
<p>4) <strong>password</strong> es... sí, eso.</p>
<p>5) <strong>host</strong> es la máquina donde se encuentra el servidor <strong>MySQL</strong> que queremos backupear. Si es nuestro propio ordenador escribiremos <strong>localhost</strong>. A destacar que el servidor <strong>MySQL</strong> debe estar corriendo en el momento de lanzar el <strong>mysqldump</strong>.</p>
<p>Lo que sigue es ya la ejecución. En mi caso las copias de seguridad las quiero en formato <strong>backup_YYYYMMDD_HHMM</strong> con la fecha y la hora de esta manera, ya que así una simple ordenación alfabética de los archivos lleva a cabo también una ordenación por fechas. Para lograr eso hay que jugar con los <strong>date:~6,4</strong> y similares y además hay que programar dos ramas en función de que sean antes o después de las 10 de la mañana, ya que hasta entonces necesito concatenar un <strong>0</strong> y un <strong>time:~1,1</strong> para la hora con dos dígitos y a partir de las 10 me vale con <strong>time:~0,2</strong>. Podemos prescindir de hacer estas dos alternativas si vamos a lanzar siempre el batch a la misma hora y será más tardía que esas 10am de la <em>madrugada</em>. En cualquier caso para discernir entre si seguir un camino u otro utilizamos el...</p>
<div class="code">if %time:~0,2% GEQ 10 goto <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> espuesDeLas10</div>
<p>...donde <strong>GEQ</strong> equivale a lo que en lenguaje de programación normal y corriente diríamos <strong>&gt;=</strong>.</p>
<p>Por último comentar que con esto obtenemos un archivo <strong>.bat</strong> que podemos ejecutar manualmente o programar para que se ejecute periódicamente a nuestro antojo. Por ejemplo con una simple tarea programada de <strong>Windows</strong> si no nos queremos complicar demasiado la vida.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/06/copias-de-seguridad-en-mysql-con-mysqldump/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Copias de seguridad con ROBOCOPY.</title>
		<link>http://www.albertmata.net/2008/05/copias-de-seguridad-con-robocopy/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=copias-de-seguridad-con-robocopy</link>
		<comments>http://www.albertmata.net/2008/05/copias-de-seguridad-con-robocopy/#comments</comments>
		<pubDate>Fri, 23 May 2008 11:00:27 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[copias de seguridad]]></category>
		<category><![CDATA[robocopy]]></category>
		<category><![CDATA[windows xp]]></category>
		<category><![CDATA[xcopy]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=10</guid>
		<description><![CDATA[Imagino que a todos los que nos dedicamos a esto nos ocurre que constantemente estamos creando nuevos archivos, nuevas versiones del mismo código, nuevos ficheros que sustituyen al anterior... y vamos haciendo copias de seguridad aquí y allá. Al menos a mí me pasa. Y me pasa también que termino teniendo versiones distintas de una [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-11" title="batch" src="http://www.albertmata.net/public/uploads/2008/05/batch.jpg" alt="" width="271" height="222" />Imagino que a todos los que nos dedicamos a esto nos ocurre que constantemente estamos creando nuevos archivos, nuevas versiones del mismo código, nuevos ficheros que sustituyen al anterior... y vamos haciendo copias de seguridad aquí y allá. Al menos a mí me pasa. Y me pasa también que termino teniendo versiones distintas de una misma cosa en el ordenador portátil y en el de sobremesa, en el pendrive, en el disco duro externo, en el servidor de la empresa... ¡no fuera caso que se perdiera el trabajo!</p>
<p>Pues hace unos días me pregunté si no habría alguna manera fácil y rápida de mantener todo eso un poco más sincronizado. Y sí, claro, la hay. De buenas a primeras seguro que hay <a href="http://www.softonic.com/windows/copias-de-seguridad" target="_blank">un montón de aplicaciones en Softonic que nos permiten hacer copias de seguridad</a> incrementales de manera superprofesional. Pero yo buscaba algo más simple, algo más rápido. Y encontré Robocopy.</p>
<p>Robocopy es una herramienta para copiado de archivos y directorios que nos viene incorporada con Windows Vista (¡algo bueno tenía que tener Vista!). Hace cosas parecidas a las que se podrían hacer con Xcopy, pero si en una linea de comando escribimos:</p>
<div class="code">xcopy /?</div>
<p>El propio sistema nos informa que Xcopy es obsoleto y que utilicemos Robocopy en su lugar. Probemos ahora a escribir:</p>
<div class="code">robocopy /?</div>
<p>Recibimos una explicación de todos los posibles argumentos que podemos utilizar con Robocopy, algo que con alguna información extra añadida <a href="http://en.wikipedia.org/wiki/Robocopy" target="_blank">también podemos encontrar en la Wikipedia</a>. Sin embargo para un uso simple, rápido y funcional de Robocopy nos basta con crear un archivo .bat tal que así:</p>
<div class="code">@echo off<br />
robocopy C:\Proyectos \\99.34.63.19\AM_Proyectos /E /B<br />
robocopy C:\VBnet \\99.34.63.19\AM_VBnet /E /B<br />
robocopy C:\2006 F:\2006 /E /B<br />
robocopy C:\2007 F:\2007 /E /B<br />
robocopy C:\2008 F:\2008 /E /B</div>
<p>Después basta con ejecutar el .bat y directamente se nos crea una copia incremental de los cinco directorios de la unidad C que hemos especificado en las cinco rutas destino que hemos indicado. Así, los dos primeros se copiarán en sus respectivas carpetas en el servidor, mientras que los otros tres irán a parar a mi pendrive USB. Los parámetros /E y /B nos permiten precisamente hacer eso.</p>
<p>Insisto en que es una copia incremental. Esto significa que la primera vez que se ejecuta se demora unos minutos en función de la cantidad de información a respaldar, pero las siguientes sólo copiará los ficheros modificados, con lo que en principio es bastante rápido. No borra de destino los elementos que ya no forman parte de los directorios de origen, pero es algo que también se puede configurar con el parámetro /PURGE si se desea.</p>
<div class="subtitle">Nota.</div>
<p>Aunque Robocopy viene con Windows Vista, se puede también añadir a sistemas Windows anteriores mediante las <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9D467A69-57FF-4AE7-96EE-B18C4790CFFD&amp;displaylang=en" target="_blank">Windows Server 2003 Resource Kit Tools</a> que funcionan como su propio nombre indica para Windows Server 2003 y también para Windows XP.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/05/copias-de-seguridad-con-robocopy/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
