<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tag 'Curiosidades'</title><link>http://msmvps.com/search/SearchResults.aspx?q=app:weblogs&amp;tag=Curiosidades&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tag 'Curiosidades'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Sobre el error &amp;quot;La operaci&amp;#243;n solicitada requiere elevaci&amp;#243;n&amp;quot; que puede devolver Runas.exe en Windows Vista/7</title><link>http://msmvps.com/blogs/dmartin/archive/2009/10/03/sobre-runas-exe-en-windows-7.aspx</link><pubDate>Sat, 03 Oct 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1724594</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;En un foro que frecuento un usuario ten&amp;iacute;a el siguiente problema: Al intentar ejecutar como administrador un programa en Windows 7 usando el comando Runas.exe, le aparec&amp;iacute;a el siguiente mensaje de error:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;740: La operaci&amp;oacute;n solicitada requiere elevaci&amp;oacute;n.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ciertamente el usuario estaba proporcionando el nombre de usuario y la contrase&amp;ntilde;a de un usuario con privilegios administrativos as&amp;iacute; que... &amp;iquest;d&amp;oacute;nde estar&amp;iacute;a el problema?&lt;/p&gt;
&lt;p&gt;En primer lugar, vamos a analizar con calma lo que quiere decir el mensaje de error. El mensaje de error &amp;quot;La operaci&amp;oacute;n solicitada requiere elevaci&amp;oacute;n&amp;quot; est&amp;aacute; recogido en el fichero de cabecera Ntstatus.h del SDK de Windows Vista y posteriores. Concretamente est&amp;aacute; definido con el nombre de macro ERROR_ELEVATION_REQUIRED.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;iquest;Cu&amp;aacute;ndo se devuelve ese c&amp;oacute;digo de error durante el funcionamiento de Windows?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;En Windows los procesos se crean usando la API CreateProcess. Uno de los pasos que se siguen antes de crear un proceso en Windows Vista y posteriores es comprobar si el proceso en cuesti&amp;oacute;n necesita elevar sus privilegios o no. A la hora de determinar este aspecto, entran en juego, entre otros,&amp;nbsp;dos par&amp;aacute;metros: El nivel de ejecuci&amp;oacute;n (&lt;em&gt;runlevel&lt;/em&gt;) impuesto por el manifiesto de la propia aplicaci&amp;oacute;n, y el token del usuario que est&amp;aacute; lanzando ese programa. Existen tres posibles niveles de ejecuci&amp;oacute;n para una aplicaci&amp;oacute;n:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;asInvoker&lt;/em&gt;: El nivel de ejecuci&amp;oacute;n es el mismo que el del proceso padre.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;highestAvailable&lt;/em&gt;: El nivel de ejecuci&amp;oacute;n es el de mayores privilegios posibles, considerando el tipo de cuenta desde la&amp;nbsp;cual&amp;nbsp;se ejecuta el proceso.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;requireAdministrator&lt;/em&gt;: El nivel de ejecuci&amp;oacute;n es administrativo, independientemente de las dem&amp;aacute;s circunstancias.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esta tabla recoge de forma b&amp;aacute;sica las posibilidades:&lt;/p&gt;
&lt;table style="width:100%;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;&lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;Nivel de ejecuci&amp;oacute;n de la aplicaci&amp;oacute;n&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;&lt;em&gt;Token&lt;/em&gt; del usuario&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;Requiere elevaci&amp;oacute;n o no&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;AsInvoker&lt;/td&gt;
&lt;td&gt;Cualquiera&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;highestAvailable&lt;/td&gt;
&lt;td&gt;Administrador &amp;quot;elevado&amp;quot;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;highestAvailable&lt;/td&gt;
&lt;td&gt;Administrador &amp;quot;est&amp;aacute;ndar&amp;quot;&lt;/td&gt;
&lt;td&gt;S&amp;iacute;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;highestAvailable&lt;/td&gt;
&lt;td&gt;Otro caso&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;requireAdministrator&lt;/td&gt;
&lt;td&gt;Administrador &amp;quot;elevado&amp;quot;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="width:239px;"&gt;requireAdministrator&lt;/td&gt;
&lt;td&gt;Otro caso&lt;/td&gt;
&lt;td&gt;S&amp;iacute;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Por administrador &amp;quot;elevado&amp;quot; me refiero a aquella cuenta con privilegios administrativos pero que, o bien ya ha elevado expl&amp;iacute;citamente sus privilegios (a trav&amp;eacute;s de un cuadro de UAC), o bien no tiene activada la caracter&amp;iacute;stica Modo de aprobaci&amp;oacute;n del administrador (&lt;em&gt;Admin Approval Mode&lt;/em&gt;). Esta caracter&amp;iacute;stica se puede desactivar desde Directiva de grupo, pero yo personalmente lo desaconsejo.&amp;nbsp;Un ejemplo de este tipo de cuentas es la cuenta &amp;quot;Administrador&amp;quot;, creada durante la instalaci&amp;oacute;n del sistema operativo. Recuerde que el resto de cuentas con privilegios administrativos poseen dos &lt;em&gt;tokens&lt;/em&gt;: uno limitado, con el que &amp;quot;act&amp;uacute;an&amp;quot; por defecto, y otro &amp;quot;administrativo&amp;quot;, que pueden aplicar si el usuario as&amp;iacute; lo indica a trav&amp;eacute;s de un cuadro de UAC.&lt;/p&gt;
&lt;p&gt;Una vez que CreateProcess falla (devuelve un valor distinto de 1) y el &amp;uacute;ltimo error se establece como ERROR_ELEVATION_REQUIRED (columna &amp;quot;Requiere elevaci&amp;oacute;n&amp;nbsp;o no&amp;quot; de la tabla anterior), es asunto del proceso padre el tratar convenientemente este error. Si no lo hace, se registrar&amp;aacute; en Visor de sucesos, apartado dedicado a UAC, un evento informando de que el proceso padre no trat&amp;oacute; apropiadamente el error&amp;nbsp;&lt;span lang="EN"&gt;ERROR_ELEVATION_REQUIRED.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;&lt;strong&gt;&amp;iquest;Qu&amp;eacute; ocurre cuando se lanza una aplicaci&amp;oacute;n desde la l&amp;iacute;nea de comandos?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;Imaginemos que el usuario intenta ejecutar el desfragmentador de disco de Windows 7 usando para ello una sintaxis de Runas.exe como esta:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;&lt;strong&gt;runas /u:UsuarioAdministrador dfrgui.exe&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;&lt;/span&gt;&lt;span lang="EN"&gt;B&amp;aacute;sicamente la l&amp;iacute;nea de comandos detecta que no se trata de un comando interno, sino que se trata del programa Runas.exe, y por tanto&amp;nbsp;se dispone a ejecutarlo usando CreateProcess. Como Runas.exe no es un programa que est&amp;aacute; marcado para requerir elevaci&amp;oacute;n de privilegios, CreateProcess retorna &amp;eacute;xito.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;Una vez que el planificador del sistema operativo&amp;nbsp;cede el control al proceso Runas.exe reci&amp;eacute;n creado, este se dispone a analizar su l&amp;iacute;nea de comandos. Se encuentra con una petici&amp;oacute;n de ejecutar Dfrgui.exe como si fuera el usuario administrador pasado como par&amp;aacute;metro. Sin embargo, Runas.exe&amp;nbsp;es poco&amp;nbsp;m&amp;aacute;s que un &amp;quot;envoltorio&amp;quot; de la API &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/ms682431(VS.85).aspx"&gt;CreateProcessWithLogonW&lt;/a&gt;, que a su vez es poco m&amp;aacute;s que un envoltorio de la API CreateProcess, pero pasando otro perfil de usuario distinto como par&amp;aacute;metro.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;Durante su ejecuci&amp;oacute;n, CreateProcess determina que Dfrgui.exe requiere privilegios administrativos (puesto que as&amp;iacute; se lo indica su manifiesto), y por ello devuelve falso y establace el &amp;uacute;ltimo error como ERROR_ELEVATION_REQUIRED. Como Runas.exe es una herramienta que no est&amp;aacute; dise&amp;ntilde;ada para tratar apropiadamente ese error, simplemente lo devuelve por pantalla de la forma &amp;quot;740: La operaci&amp;oacute;n solicitada requiere elevaci&amp;oacute;n&amp;quot;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;Una vez desvelado el misterio, resta por comentar un aspecto que a estas alturas quiz&amp;aacute; ya se haya planteado:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;&lt;strong&gt;&amp;iquest;C&amp;oacute;mo es posible que ejecutando Dfrgui.exe desde la l&amp;iacute;nea de comandos -sin usar Runas.exe- s&amp;iacute; que aparezca un cuadro de UAC?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN"&gt;El secreto est&amp;aacute; en que la l&amp;iacute;nea de comandos, antes de llamar a CreateProcess, informa al sistema de que va a tratar los posibles ERROR_ELEVATION_REQUIRED que puedan surgir. Esto lo consigue estableciendo unos atributos no documentados a la estructura &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/ms686329(VS.85).aspx"&gt;STARTUPINFOEX&lt;/a&gt;, que se pasa como par&amp;aacute;metro a la familia de API CreateProcess. Esto hace que no se registre el correspondiente error en el apartado UAC del Visor de sucesos. Seguidamente, la l&amp;iacute;nea de comandos, sabiendo que se trata de un programa que debe elevar sus privilegios, lo intenta ejecutar mediante la API &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/bb762154(VS.85).aspx"&gt;ShellExecuteEx&lt;/a&gt;. &lt;strong&gt;Esta API s&amp;iacute; muestra el correspondiente cuadro de UAC, as&amp;iacute; que es la v&amp;iacute;a apropiada para ejecutar una aplicaci&amp;oacute;n que requiera privilegios administrativos.&lt;/strong&gt;&lt;/span&gt;
&lt;p&gt;En resumen, me gustar&amp;iacute;a resaltar estos puntos&amp;nbsp;del tema del art&amp;iacute;culo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;En Windows Vista y Windows 7 la &amp;uacute;nica forma de ejecutar algo con privilegios administrativos es mediante un cuadro de UAC. No vale con poner el nombre de usuario y la contrase&amp;ntilde;a de un administrador en la l&amp;iacute;nea de comandos.&lt;/li&gt;
&lt;li&gt;Todo lo que se ejecute mediante la API CreateProcess, o alguna derivada de ella,&amp;nbsp;&lt;strong&gt;no har&amp;aacute; que aparezca un cuadro de UAC&lt;/strong&gt;. Un ejemplo de ello es la utilidad Runas.exe.&lt;/li&gt;
&lt;li&gt;Runas.exe, en Windows Vista/7, sirve para ejecutar una aplicaci&amp;oacute;n como si fuera otro usuario, &lt;strong&gt;pero no sirve para ejecutarla con mayores privilegios.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Si quiere que se ejecute una aplicaci&amp;oacute;n que requiere privilegios administrativos, &lt;strong&gt;use la API ShellExecuteEx&lt;/strong&gt;, o alguna de sus derivadas. Esta API s&amp;iacute; permite la aparici&amp;oacute;n de un cuadro de UAC para que el usuario eleve sus privilegios.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;</description></item><item><title>&amp;#191;Cu&amp;#225;ndo crea Windows un punto de restauraci&amp;#243;n autom&amp;#225;tico?</title><link>http://msmvps.com/blogs/dmartin/archive/2009/09/17/191-cu-225-ndo-crea-Windows-un-punto-de-restauraci-243-n-autom-225-tico.aspx</link><pubDate>Thu, 17 Sep 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1723151</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;Una de las dudas que m&amp;aacute;s surgen entre los usuarios de Restaurar sistema es cada cu&amp;aacute;nto tiempo se crear&amp;aacute; un punto de restauraci&amp;oacute;n autom&amp;aacute;tico. Este art&amp;iacute;culo pretende dar una respuesta precisa a esta cuesti&amp;oacute;n para as&amp;iacute; esclarecer aquellos casos en los que el sistema no haya creado un punto de restauraci&amp;oacute;n desde hace tiempo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows XP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;En Windows XP cada hora una tarea interna del Programador de tareas se encarga de analizar si el sistema est&amp;aacute; inactivo, es decir, si no est&amp;aacute; haciendo uso de la CPU ni del subsistema de E/S. Si se diera el caso, se realizan dos posibles comprobaciones para determinar si se debe crear un punto de restauraci&amp;oacute;n autom&amp;aacute;tico:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si han pasado m&amp;aacute;s de 24 horas desde el &amp;uacute;ltimo punto de restauraci&amp;oacute;n, se crea uno autom&amp;aacute;ticamente. Este par&amp;aacute;metro (24 horas) es editable desde el Registro del sistema operativo, concretamente en la clave HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\SystemRestore, valor &lt;em&gt;RPGlobalInterval&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Si la sesi&amp;oacute;n actual de trabajo con el PC&amp;nbsp;est&amp;aacute; durando m&amp;aacute;s de X horas y el &amp;uacute;ltimo punto de restauraci&amp;oacute;n es m&amp;aacute;s antiguo, se crea un punto de restauraci&amp;oacute;n autom&amp;aacute;tico. Por defecto, esta configuraci&amp;oacute;n &lt;strong&gt;no est&amp;aacute; establecida&lt;/strong&gt;, pero puede hacerlo desde el Registro en la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore, valor &lt;em&gt;RPSessionInterval&lt;/em&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La comprobaci&amp;oacute;n de inactividad se realiza por defecto cada hora pero podr&amp;iacute;a variar dependiendo de los valores de ciertas pol&amp;iacute;ticas de energ&amp;iacute;a de su equipo. Eche un vistazo a los valores &lt;strong&gt;IdleTimeoutDc, IdleTimeoutAc&lt;/strong&gt; de esta p&amp;aacute;gina de MSDN:&lt;strong&gt; &lt;/strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa373239(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/aa373239(VS.85).aspx&lt;/a&gt;. Aprovechando la inactividad, Restaurar sistema realiza otras tareas, tales&amp;nbsp;como eliminar aquellos puntos de restauraci&amp;oacute;n cuyo tiempo de vida ya haya expirado, y de paso comprimir el almac&amp;eacute;n usando compresi&amp;oacute;n NTFS. Estas tareas se realizan solo si el equipo est&amp;aacute; conectado a la corriente el&amp;eacute;ctrica, para evitar que se agote la bater&amp;iacute;a en el caso de port&amp;aacute;tiles.&lt;/p&gt;
&lt;p&gt;Si quiere profundizar en el funcionamiento de la herramienta Restaurar sistema de Windows XP, eche un vistazo a esta serie de art&amp;iacute;culos de mi antiguo &lt;em&gt;blog&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rinconwindows.blogspot.com/2007/02/cmo-funciona-restaurar-sistema-parte-i.html"&gt;http://rinconwindows.blogspot.com/2007/02/cmo-funciona-restaurar-sistema-parte-i.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rinconwindows.blogspot.com/2007/03/cmo-funciona-restaurar-sistema-parte-ii.html"&gt;http://rinconwindows.blogspot.com/2007/03/cmo-funciona-restaurar-sistema-parte-ii.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows Vista/7&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;En Windows Vista/7 el nuevo Programador de tareas muestra informaci&amp;oacute;n detallada acerca de la tarea programada que crea un punto de restauraci&amp;oacute;n autom&amp;aacute;tico. Abra Programador de tareas, apartado \Microsoft\Windows\SystemRestore. La tarea &lt;em&gt;SR&lt;/em&gt; tiene como desencadenantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El inicio del sistema.&lt;/li&gt;
&lt;li&gt;Diariamente a las 12 AM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En esos instantes se ejecutar&amp;aacute; el comando %windir%\system32\rundll32.exe /d srrstr.dll,ExecuteScheduledSPPCreation.&lt;/p&gt;
&lt;p&gt;El modificador /d de Rundll32.exe ya lo trat&amp;eacute;&amp;nbsp;ligeramente &lt;a target="_blank" href="http://rinconwindows.blogspot.com/2007/10/sobre-el-mensaje-de-error-ha-ocurrido.html"&gt;en mi antiguo &lt;em&gt;blog&lt;/em&gt;&lt;/a&gt;: Se trata de un modificador que le dice a Rundll32.exe &amp;quot;ejecuta este comando y no captures las posibles excepciones que ocurran&amp;quot;. La funci&amp;oacute;n &lt;em&gt;ExecuteScheduledSPPCreation&lt;/em&gt; es la encargada de verificar si el punto de restauraci&amp;oacute;n m&amp;aacute;s antiguo tiene m&amp;aacute;s de 12 horas (la mitad que en el caso de XP) y, si as&amp;iacute; fuese, crear&amp;aacute; uno nuevo.&lt;/p&gt;
&lt;p&gt;Hay que tener en cuenta otras condiciones adicionales que puede observar en la pesta&amp;ntilde;a &lt;em&gt;Condiciones&lt;/em&gt;: El sistema debe estar inactivo durante al menos 10 minutos y adem&amp;aacute;s, en el caso de port&amp;aacute;tiles, debe estar conectado a la red el&amp;eacute;ctrica.&lt;/p&gt;
&lt;p&gt;Espero que este art&amp;iacute;culo haya aclarado sus dudas con respecto a la creaci&amp;oacute;n autom&amp;aacute;tica de puntos de restauraci&amp;oacute;n por parte de Windows. En resumen, si su sistema no genera periodicamente puntos de restauraci&amp;oacute;n puede deberse a:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El servicio Programador de tareas no est&amp;aacute; iniciado.&lt;/li&gt;
&lt;li&gt;El sistema no est&amp;aacute; inactivo durante los periodos de tiempo impuestos por Windows, seg&amp;uacute;n lo explicado anteriormente.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Sobre la nueva sintaxis del Panel de control en Windows Vista/Windows 7</title><link>http://msmvps.com/blogs/dmartin/archive/2009/09/11/sobre-la-nueva-sintaxis-del-panel-de-control-en-windows-vista-windows-7.aspx</link><pubDate>Fri, 11 Sep 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1722676</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;Quiz&amp;aacute; ya se haya dado cuenta de que en Windows Vista/Windows 7&amp;nbsp;algunos m&amp;oacute;dulos del Panel de control que anteriormente estaban implementados en la cl&amp;aacute;sica forma de un fichero .cpl ahora lo est&amp;aacute;n en la forma de un fichero ejecutable (.exe). El motivo de este cambio es que con la introducci&amp;oacute;n de Control de cuentas de usuario (UAC),&amp;nbsp;se da el caso de que algunos de estos m&amp;oacute;dulos requieren privilegios administrativos para ejecutarse. Ve&amp;aacute;moslo con un ejemplo:&lt;/p&gt;
&lt;p&gt;El ejecutable DPIScaling.exe del&amp;nbsp;directorio \Windows\System32&amp;nbsp;implementa la opci&amp;oacute;n del&amp;nbsp;Panel de control que permite cambiar&amp;nbsp;la&amp;nbsp;escala DPI del sistema. Este m&amp;oacute;dulo requiere privilegios administrativos&amp;nbsp;para ejecutarse, como as&amp;iacute; indica su fichero de manifiesto. Para verlo pr&amp;aacute;cticamente, descargue Strings desde&amp;nbsp;&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx"&gt;http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx&lt;/a&gt;&amp;nbsp;y abra una&amp;nbsp;ventana de l&amp;iacute;nea de comandos en el directorio donde la&amp;nbsp;ha extra&amp;iacute;do. Introduzca este comando y pulse INTRO:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;strings %SystemRoot%\System32\DPIScaling.exe&amp;nbsp;| findstr /i requireAdministrator&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;La salida del comando, &lt;code&gt;level=&amp;quot;requireAdministrator&amp;quot;&lt;/code&gt;, nos indica que el ejecutable en cuesti&amp;oacute;n requerir&amp;aacute; privilegios administrativos cuando lo invoquemos. Otros posibles valores para el atributo level son:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;asInvoker:&lt;/em&gt; El ejecutable no requerir&amp;aacute; privilegios administrativos.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;highestAvailable:&lt;/em&gt; El ejecutable se ejecutar&amp;aacute; con los m&amp;aacute;ximos privilegios que le permita la cuenta de&amp;nbsp;usuario&amp;nbsp;desde la que ha sido invocado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nombres can&amp;oacute;nicos en Windows Vista/Windows 7&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Esta reestructuraci&amp;oacute;n de buena parte de los elementos del Panel de control trajo consigo una de las novedades&amp;nbsp;que se introdujeron en&amp;nbsp;Windows Vista y que se han mantenido en&amp;nbsp;Windows 7: la posibilidad de abrir elementos del Panel de control usando un nombre can&amp;oacute;nico. Un nombre can&amp;oacute;nico es un nombre en ingl&amp;eacute;s, no traducible, que describe de manera cercana al usuario el cometido de ese elemento del Panel de control. Esto evita que el usuario tenga que aprender el nombre de ficheros .cpl, muchas veces cr&amp;iacute;pticos, y adem&amp;aacute;s permite separar el nombre del &amp;iacute;tem de su implementaci&amp;oacute;n, ya sea en un cl&amp;aacute;sico fichero .cpl o, ya sea en un fichero .dll o .exe.&lt;/p&gt;
&lt;p&gt;Por ejemplo, para abrir el panel Agregar o quitar programas de Windows Vista/Windows 7, se puede usar esta sintaxis:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%windir%\system32\control.exe /name Microsoft.ProgramsAndFeatures&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;iquest;De d&amp;oacute;nde proviene ese nombre can&amp;oacute;nico, Microsoft.ProgramsAndFeatures?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cuando el ejecutable Control.exe recibe el par&amp;aacute;metro /name seguido de un nombre can&amp;oacute;nico, se invoca a la funci&amp;oacute;n &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/bb775394(VS.85).aspx"&gt;IOpenControlPanel::Open&lt;/a&gt;, la cual&amp;nbsp;en primer lugar busca el elemento correspondiente del Panel de control al que se est&amp;aacute; haciendo referencia. Cabe destacar que el Panel de control es un directorio &lt;strong&gt;virtual&lt;/strong&gt; (no reside f&amp;iacute;sicamente en el disco, sino que est&amp;aacute; implementado por el &lt;em&gt;shell&lt;/em&gt;), situado en la clave de Registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace. El valor &lt;em&gt;(Predeterminado)&lt;/em&gt; de cada una de las subclaves de esa rama de Registro contiene el nombre con el que se mostrar&amp;aacute; en Panel de control (no el nombre can&amp;oacute;nico). Para encontrar la implementaci&amp;oacute;n de, digamos, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace\{0DF44EAA-FF21-4412-828E-260A8728E7F1} (&amp;iacute;tem de las propiedades de la barra de tareas y men&amp;uacute; Inicio), se accede a la clave de registro HKEY_CLASSES_ROOT\CLSID\{0DF44EAA-FF21-4412-828E-260A8728E7F1}, en la cual existe un valor de registro de nombre &lt;em&gt;System.ApplicationName&lt;/em&gt; y cuyo contenido es el nombre can&amp;oacute;nico: &lt;em&gt;Microsoft.TaskbarAndStartMenu&lt;/em&gt;. As&amp;iacute; pues, para abrir las propiedades de la barra de tareas y del men&amp;uacute; Inicio ya sabemos que&amp;nbsp;bastar&amp;iacute;a con ejecutar lo siguiente:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%windir%\system32\control.exe /name Microsoft.TaskbarAndStartMenu&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Para ver qu&amp;eacute; es lo que realmente se ejecuta, eche un vistazo a la clave HKEY_CLASSES_ROOT\CLSID\{0DF44EAA-FF21-4412-828E-260A8728E7F1}\Shell\Open\Command.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cada &amp;iacute;tem del Panel de control puede implementar varias p&amp;aacute;ginas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Podemos entender las p&amp;aacute;ginas como subsecciones espec&amp;iacute;ficas del &amp;iacute;tem del Panel de control. Para indicar una, debe usarse la sintaxis&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%windir%\system32\control.exe /name &lt;em&gt;Nombre_can&amp;oacute;nico&lt;/em&gt; /page &lt;em&gt;P&amp;aacute;gina&lt;/em&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ve&amp;aacute;moslo con un ejemplo:&lt;/p&gt;
&lt;p&gt;Con los conocimientos que hemos adquirido, nos resulta sencillo determinar que el &amp;iacute;tem Personalizar del Panel de control est&amp;aacute; implementado en la DLL Themecpl.dll. Es en esta DLL donde encontraremos informaci&amp;oacute;n acerca de las posibles p&amp;aacute;ginas de este &amp;iacute;tem, en la forma, como no, de fichero XML.&lt;/p&gt;
&lt;p&gt;Esta vez usaremos la aplicaci&amp;oacute;n gr&amp;aacute;fica Resource Hacker, que puede descargar gratuitamente desde &lt;a href="http://www.angusj.com/resourcehacker/"&gt;http://www.angusj.com/resourcehacker/&lt;/a&gt;. Al abrir el fichero Themecpl.dll en&amp;nbsp;esta aplicaci&amp;oacute;n,&amp;nbsp;nos encontramos con dos ficheros XML adicionales al t&amp;iacute;pico fichero de manifiesto (.manifest) que hab&amp;iacute;amos visto hasta ahora.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/7838.Tasks_5F00_CPL.PNG"&gt;&lt;img src="http://msmvps.com/resized-image.ashx/__size/550x494/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/7838.Tasks_5F00_CPL.PNG" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/7838.Tasks_5F00_CPL.PNG"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Este primer fichero XML especifica una serie de tareas que puede realizar el elemento del Panel de control &amp;quot;Personalizar&amp;quot;. Estas tareas (cambiar los colores, el fondo de pantalla, etc.) se muestran como enlaces de texto justo debajo del elemento del Panel de control (suponiendo que est&amp;eacute; configurado en la vista por categor&amp;iacute;as). Y lo que es m&amp;aacute;s importante, estas tareas son indizables por el sistema de b&amp;uacute;squeda de Windows Vista. Puede obtener m&amp;aacute;s informaci&amp;oacute;n en este art&amp;iacute;culo de MSDN: &lt;a href="http://msdn.microsoft.com/en-us/library/bb776840(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/bb776840(VS.85).aspx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/0027.Paginas_5F00_CPL.PNG"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/0027.Paginas_5F00_CPL.PNG"&gt;&lt;img src="http://msmvps.com/resized-image.ashx/__size/550x494/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/0027.Paginas_5F00_CPL.PNG" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Esta segunda imagen hace referencia&amp;nbsp;al segundo fichero XML, que&amp;nbsp;es el que contiene la informaci&amp;oacute;n acerca de cada una de las p&amp;aacute;ginas que implementa este &amp;iacute;tem del Panel de control. Entre las etiquetas &lt;em&gt;&amp;lt;pagedefinition&amp;gt;&amp;lt;/pagedefinition&amp;gt;&lt;/em&gt; nos encontramos con una etiqueta &lt;em&gt;&amp;lt;properties&amp;gt;,&lt;/em&gt; que hace referencia a cada una de las p&amp;aacute;ginas. El atributo &lt;em&gt;canonicalName&lt;/em&gt; nos ofrece su nombre can&amp;oacute;nico.&lt;/p&gt;
&lt;p&gt;Como vemos, el &amp;iacute;tem &amp;quot;Personalizar&amp;quot; del Panel de control admite como sintaxis:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%windir%\system32\control.exe /name Microsoft.Personalization /page pageColorization&lt;/code&gt; (para cambiar la configuraci&amp;oacute;n de color)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%windir%\system32\control.exe /name Microsoft.Personalization /page pageWallpaper&lt;/code&gt; (para cambiar el fondo de escritorio)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ejercicio&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ahora que ya sabe c&amp;oacute;mo escudri&amp;ntilde;ar en los &amp;iacute;tems del Panel de control con el fin de construir accesos directos lo m&amp;aacute;s directos posibles (valga la redundancia), le propongo como ejercicio que en un sistema Windows 7 averig&amp;uuml;e la sintaxis para un acceso directo al Monitor de confiabilidad, que como sabe en Windows 7 est&amp;aacute; algo escondido dentro del Centro de acciones (&lt;em&gt;Action Center&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Si se rinde, puede ver la soluci&amp;oacute;n&amp;nbsp;seleccionando texto a partir de aqu&amp;iacute;: &lt;span style="color:white;"&gt;control.exe Microsoft.ActionCenter /page pageReliabilityView&lt;/span&gt;&lt;/p&gt;</description></item><item><title>Descubrir valores de Registro no documentados usando Process Monitor</title><link>http://msmvps.com/blogs/dmartin/archive/2009/08/16/descubrir-valores-de-registro-no-documentados-usando-process-monitor.aspx</link><pubDate>Sun, 16 Aug 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1716254</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;A mucha gente le gusta&amp;nbsp;personalizar su sistema de escritorio al m&amp;aacute;ximo posible. Por ello, Microsoft acostumbra a incorporar en sus sistemas operativos bastantes men&amp;uacute;s y cuadros de di&amp;aacute;logo capaces de personalizar muchos de los detalles de funcionamiento de Windows. Sin embargo, hay ciertos detalles que no son modificables desde la interfaz gr&amp;aacute;fica, solamente desde el Registro; siempre&amp;nbsp;siguiendo los pasos de alg&amp;uacute;n art&amp;iacute;culo de la documentaci&amp;oacute;n oficial de Microsoft (KB, MSDN LIbrary, Technet Library, etc.). Tambi&amp;eacute;n hay detalles que no est&amp;aacute;n documentados pero que&amp;nbsp;pueden &amp;quot;descubrirse&amp;quot; utilizando herramientas de monitoreo del Registro, como Process Monitor, tal y como se explica en este art&amp;iacute;culo.&lt;/p&gt;
&lt;p&gt;En el caso que nos ocupa, el usuario quer&amp;iacute;a modificar el tiempo de aparici&amp;oacute;n de la vista en miniatura de una aplicaci&amp;oacute;n en la barra de tareas de Windows Vista. En Windows Vista, la funcionalidad Windows Aero permite ver, a golpe de rat&amp;oacute;n, el contenido de todas y cada una de las ventanas minimizadas en la barra de tareas. El usuario intentaba buscar una forma de acortar ese tiempo de aparici&amp;oacute;n de la vista en miniatura, pues le parec&amp;iacute;a excesivo. En Internet la alternativa que es m&amp;aacute;s popular es la de modificar el valor de Registro &lt;em&gt;MouseHoverTime&lt;/em&gt; de la clave de Registro HKEY_CURRENT_USER\Control Panel\Mouse. Sin embargo, este valor influye en el tiempo que tarda en reconocerse un posicionamiento del cursor del rat&amp;oacute;n, en cualquier parte de la interfaz gr&amp;aacute;fica de Windows. Era necesario buscar alg&amp;uacute;n valor de Registro m&amp;aacute;s espec&amp;iacute;fico, y para ello iba a recurrir a Process Monitor.&lt;/p&gt;
&lt;p&gt;Antes de nada hay que comentar que no ten&amp;iacute;a la garant&amp;iacute;a de que existiera un valor de Registro que controlara ese aspecto tan espec&amp;iacute;fico de la interfaz gr&amp;aacute;fica de Windows. De existir, suelen ser par&amp;aacute;metros que solo se tienen en cuenta en las versiones de depuraci&amp;oacute;n (&lt;em&gt;checked&lt;/em&gt;) del sistema operativo. De todas formas, abr&amp;iacute; Process Monitor y establec&amp;iacute; un filtro de aquellos eventos de Registro que contuvieran en su ruta la palabra&amp;nbsp;&amp;quot;Thumbnail&amp;quot;. Inici&amp;eacute; Explorer.exe y r&amp;aacute;pidamente me encontr&amp;eacute; con&amp;nbsp;tres eventos bastante interesantes:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/5140.ExplorerThumbnails.PNG"&gt;&lt;img src="http://msmvps.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/5140.ExplorerThumbnails.PNG" border="0" style="max-height:63px;max-width:1023px;" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El primer evento indica el momento en que Explorer.exe examina una directiva, &lt;em&gt;TaskbarNoThumbnail&lt;/em&gt;, configurable desde Directiva de grupo, encargada&amp;nbsp;de desactivar las vistas en miniatura de la barra de tareas. La lectura de este valor me hizo pensar que los dos valores siguientes podr&amp;iacute;an estar relacionados con lo que buscaba.&lt;/p&gt;
&lt;p&gt;Esos dos eventos siguientes hacen referencia a una b&amp;uacute;squeda de cierta rama en el Registro (&lt;em&gt;ExplorerThumbnails&lt;/em&gt;), tanto en la rama HKEY_CURRENT_USER como en la rama HKEY_LOCAL_MACHINE. El primer evento hace referencia al SID de mi usuario dentro de la rama HKEY_USERS (HKU) simplemente porque ejecut&amp;eacute; Process Monitor desde una cuenta limitada, proporcionando obviamente&amp;nbsp;el nombre de usuario y contrase&amp;ntilde;a del administrador.&lt;/p&gt;
&lt;p&gt;&amp;iquest;Qu&amp;eacute; ser&amp;iacute;a esa rama &lt;em&gt;ExplorerThumbnails&lt;/em&gt;? La verdad es que no encontr&amp;eacute; nada documentado en Internet, pero su nombre era lo suficientemente atractivo como para seguir indagando. Una de las cosas que suelo hacer en casos como este es crear la clave que busca en este caso Explorer.exe y ver qu&amp;eacute; valores o subclaves de Registro busca a continuaci&amp;oacute;n. Eso hice: Abr&amp;iacute; Editor del Registro y cre&amp;eacute; la clave de Registro &lt;em&gt;ExplorerThumbnails&lt;/em&gt;. Volv&amp;iacute; a capturar una traza con Process Monitor y el resultado ofreci&amp;oacute; otros tres valores tan interesantes como desconocidos:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://msmvps.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/dmartin/3733.Contenidos_5F00_ExplorerThumbnails.PNG" border="0" style="max-height:146px;max-width:1031px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Los valores &lt;em&gt;InitialThumbnail&lt;/em&gt;, &lt;em&gt;InitialTooltip&lt;/em&gt; y &lt;em&gt;AutoPopTooltip&lt;/em&gt; me hac&amp;iacute;an pensar que efectivamente estaban relacionados con lo que realmente buscaba: Modificar el tiempo de aparici&amp;oacute;n de la vista en miniatura. En este caso podr&amp;iacute;a haber experimentado introduciendo algunos valores aleatorios para esos valores de Registro y observar los resultados, aunque en este caso recurr&amp;iacute; a una lectura del c&amp;oacute;digo fuente de Explorer.&lt;/p&gt;
&lt;p&gt;Al parecer, el valor &lt;em&gt;InitialThumbnail&lt;/em&gt; tiene que ver con el tiempo en milisegundos que tarda en aparecer la vista en miniatura desde que se sit&amp;uacute;a el cursor del rat&amp;oacute;n en la aplicaci&amp;oacute;n minimizada en la barra de tareas; &lt;em&gt;InitialTooltip&lt;/em&gt; influye en el tiempo de aparici&amp;oacute;n del texto emergente que siempre aparece encima de la vista en miniatura, un tiempo despu&amp;eacute;s. Por &amp;uacute;ltimo, &lt;em&gt;AutoPopTooltip&lt;/em&gt; influye en el tiempo que tarda en desaparecer el texto emergente. Por defecto, si no se encuentran esos valores en el Registro, el sistema supone, respectivamente, 500, 1000 y 5000 milisegundos.&lt;/p&gt;
&lt;p&gt;Para concluir, codifiqu&amp;eacute; una aplicaci&amp;oacute;n gr&amp;aacute;fica que facilitara la modificaci&amp;oacute;n de estos valores en el&amp;nbsp;Registro: &lt;a href="http://winvista.mvps.org/Ficheros/TweakThumbnails.zip"&gt;http://winvista.mvps.org/Ficheros/TweakThumbnails.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ya conoce otro posible uso de Process Monitor: Intentar descubrir valores de Registro (o ficheros) no documentados pero que pueden permitirnos configurar aspectos m&amp;aacute;s o menos interesantes del sistema operativo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Como indico en el margen izquierdo de este &lt;em&gt;blog&lt;/em&gt;, toda la informaci&amp;oacute;n que no est&amp;aacute; documentada por Microsoft es muy susceptible de cambiar e incluso de desaparecer en versiones posteriores de Windows. Este es el caso particular de esta rama del Registro, pues no es tenida en cuenta en Windows 7. Adicionalmente, deber&amp;aacute; tomar las medidas oportunas si aplica este&lt;em&gt; tip&lt;/em&gt; en un entorno de producci&amp;oacute;n, pues de seguro se trata de un par&amp;aacute;metro que no est&amp;aacute; tan probado como el resto de personalizaciones conocidas en el sistema operativo.&lt;/p&gt;</description></item><item><title>&amp;#191;/Savecred, /Savedcred, /Savedcreds...? Es lo mismo</title><link>http://msmvps.com/blogs/dmartin/archive/2009/07/02/191-savecred-savedcred-savedcreds-es-lo-mismo.aspx</link><pubDate>Thu, 02 Jul 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1697592</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;Como quiz&amp;aacute; sepa, el comando Runas.exe de Windows XP y Windows Server 2003&amp;nbsp;sirve para ejecutar procesos en el contexto de otra cuenta de usuario. Los usuarios dom&amp;eacute;sticos normalmente lo usan para ejecutar un proceso como administrador desde una cuenta limitada. Echando un vistazo al listado de par&amp;aacute;metros de Runas.exe nos encontramos con uno que suele llamar la atenci&amp;oacute;n de bastante gente. Sirve para almacenar temporalmente en el administrador de credenciales (&lt;em&gt;Credential Manager&lt;/em&gt;) el usuario y contrase&amp;ntilde;a que va a ejecutar el programa. El atractivo de este par&amp;aacute;metro es que&amp;nbsp;no tendremos que introducir el nombre de usuario y contrase&amp;ntilde;a para ese programa durante la sesi&amp;oacute;n en curso. Sin embargo, no hay unanimidad con respecto al nombre del par&amp;aacute;metro (incluso la propia documentaci&amp;oacute;n del sistema operativo creo que presenta alguna inconsistencia al respecto): Unos lo llaman&lt;strong&gt; /savecred&lt;/strong&gt;, otros &lt;strong&gt;/savedcred&lt;/strong&gt;, otros&lt;strong&gt; /savedcreds&lt;/strong&gt;... Incluso en algunos sitios se indica que tienen sem&amp;aacute;ntica diferente. &lt;/p&gt;
&lt;p&gt;Nada m&amp;aacute;s lejos de la realidad. Runas.exe solo entiende el par&amp;aacute;metro &lt;strong&gt;/sa&lt;/strong&gt; (que contiene el m&amp;iacute;nimo n&amp;uacute;mero de letras que diferencian&lt;strong&gt; /savecred&lt;/strong&gt; de los&amp;nbsp;par&amp;aacute;metros&lt;strong&gt; /smartcard&lt;/strong&gt; y &lt;strong&gt;/showtrustlevels&lt;/strong&gt;); lo que venga despu&amp;eacute;s le es indiferente. Del mismo modo, en cuanto se encuentra con&lt;strong&gt; /p&lt;/strong&gt; supone el par&amp;aacute;metro &lt;strong&gt;/profile&lt;/strong&gt;; si se encuentra con&lt;strong&gt; /e&lt;/strong&gt; supone&lt;strong&gt; /env&lt;/strong&gt;, y as&amp;iacute; sucesivamente.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Por limitaciones del administrador de credenciales de XP Home Edition, el par&amp;aacute;metro&lt;strong&gt; /savecred&lt;/strong&gt; no es tenido en cuenta en esta versi&amp;oacute;n de Windows. Este art&amp;iacute;culo no es aplicable tampoco a Windows Vista, pues el comando Runas.exe en Windows Vista es bastante diferente del de XP y ser&amp;aacute; tema de un pr&amp;oacute;ximo art&amp;iacute;culo.&lt;/p&gt;</description></item><item><title>&amp;#191;Qu&amp;#233; hay detr&amp;#225;s del mensaje &amp;quot;Win 16 Subsystem no tiene suficientes recursos...&amp;quot;?</title><link>http://msmvps.com/blogs/dmartin/archive/2008/11/06/191-qu-233-hay-detr-225-s-del-mensaje-quot-win-16-subsystem-no-tiene-suficientes-recursos-quot.aspx</link><pubDate>Thu, 06 Nov 2008 06:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1653311</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;Si usa Windows XP es posible que en alguna ocasi&amp;oacute;n se haya encontrado con el siguiente mensaje de aviso:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Win 16 Subsystem no tiene suficientes recursos para que contin&amp;uacute;e ejecut&amp;aacute;ndose. Haga clic en Aceptar, cierre sus aplicaciones y reinicie su equipo.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;iquest;Qu&amp;eacute; quiere decir exactamente este mensaje? B&amp;aacute;sicamente, es la consecuencia de una desacertada&amp;nbsp;decisi&amp;oacute;n de dise&amp;ntilde;o que Microsoft tom&amp;oacute; hace d&amp;eacute;cadas y&amp;nbsp;que&amp;nbsp;provoc&amp;oacute; una serie de fallos&amp;nbsp;descubiertos&amp;nbsp;poco tiempo antes de la salida al mercado de Windows XP. Este art&amp;iacute;culo indagar&amp;aacute; un poco en este tema tan curioso.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Un poco de historia&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Windows incorpora desde sus comienzos una interfaz que permite a los programadores dise&amp;ntilde;ar elementos gr&amp;aacute;ficos para sus aplicaciones. Esta interfaz recibe el nombre de &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Graphics_Device_Interface"&gt;GDI&lt;/a&gt; (&lt;em&gt;Graphics Device Interface&lt;/em&gt;). Ya desde Windows 3.1, Microsoft supuso que GDI solamente podr&amp;iacute;a generar &lt;em&gt;handles&lt;/em&gt; de tama&amp;ntilde;o menor de 16 K. En aquellos tiempos, los &lt;em&gt;handles&lt;/em&gt;&amp;nbsp;se implementaban en el mont&amp;oacute;n (&lt;em&gt;heap&lt;/em&gt;) de GDI y estaban limitados a 14 de los 16 bits posibles. Es decir, los dos &amp;uacute;ltimos bits estaban reservados (el &amp;uacute;ltimo bit siempre era cero porque las direcciones de memoria ten&amp;iacute;an que ser pares). Con la llegada de los 32 bits, lleg&amp;oacute; GDI32 y con &amp;eacute;l los &lt;em&gt;handles&lt;/em&gt; pasaron a ocupar una palabra de longitud: La mitad inferior conten&amp;iacute;a el valor en s&amp;iacute; y la mitad superior una serie de bits para dar &lt;a target="_blank" href="http://support.microsoft.com/kb/94917/en-us"&gt;unicidad&lt;/a&gt; al &lt;em&gt;handle&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Como supongo que ya sabr&amp;aacute;, los sistemas operativos Windows de 32 bits incorporan un subsistema de 16 bits encargado de hacer funcionar aplicaciones antiguas de 16 bits. Este subsistema recibe el nombre de WoW (&lt;em&gt;Windows on Windows&lt;/em&gt;). Obviamente, dicho subsistema tiene que tener alguna manera de convertir un &lt;em&gt;handle&lt;/em&gt; GDI de&amp;nbsp;32 bits a uno de&amp;nbsp;16 bits y viceversa. Hasta la llegada de&amp;nbsp;Windows XP lo que se hab&amp;iacute;a venido haciendo es simplemente descartar la mitad superior, quedarse con la mitad inferior y desplazarla dos posiciones hacia la izquierda. Como los &lt;em&gt;handles&lt;/em&gt; eran menores de 16 K, el desplazamiento no supon&amp;iacute;a p&amp;eacute;rdida de informaci&amp;oacute;n y todo funcionaba a pedir de boca... hasta que lleg&amp;oacute; Windows XP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Con Windows XP empezaron los problemas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Con la llegada de Windows XP, surgi&amp;oacute; la necesidad de tener&amp;nbsp;&lt;em&gt;handles&lt;/em&gt; GDI de tama&amp;ntilde;o superior a 16 K. Por este motivo, el equipo de GDI decidi&amp;oacute; utilizar completamente los 16 bits de la parte inferior del &lt;em&gt;handle&lt;/em&gt; (recuerde que hasta entonces solo se usaban 14 bits). El problema, como puede empezar a vislumbrar, suced&amp;iacute;a cuando un &lt;em&gt;handle&lt;/em&gt; de tama&amp;ntilde;o &lt;em&gt;mayor de 16 K&lt;/em&gt; ten&amp;iacute;a que ser convertido por la m&amp;aacute;quina virtual de 16 bits. Al hacer el desplazamiento de los bits, ya s&amp;iacute; se perd&amp;iacute;a informaci&amp;oacute;n, y los efectos negativos no tardaron en aparecer.&lt;/p&gt;
&lt;p&gt;Este problema se descubri&amp;oacute; en una fase muy tard&amp;iacute;a de la &lt;em&gt;beta&lt;/em&gt; de XP, por lo que Microsoft no tuvo otra opci&amp;oacute;n que implementar r&amp;aacute;pidamente&amp;nbsp;una soluci&amp;oacute;n&amp;nbsp;temporal:&amp;nbsp;Concretamente decidi&amp;oacute; que, antes de convertir,&amp;nbsp;se&amp;nbsp;comprobara el tama&amp;ntilde;o del &lt;em&gt;handle&lt;/em&gt;; si &amp;eacute;ste fuese superior a 16 K, se mostrar&amp;iacute;a el mensaje de aviso del principio de este art&amp;iacute;culo y se finalizar&amp;iacute;a la ejecuci&amp;oacute;n de la m&amp;aacute;quina virtual de 16 bits. La soluci&amp;oacute;n adoptada en Windows Vista y Windows Server 2008, ya con tiempo suficiente para comprobarla exhaustivamente, consiste en una tabla de correspondencias entre &lt;em&gt;handles&lt;/em&gt; de 32 bits&amp;nbsp;y &lt;em&gt;handles&lt;/em&gt; de 16 bits.&lt;/p&gt;
&lt;p&gt;Es curioso ver que una soluci&amp;oacute;n&amp;nbsp;v&amp;aacute;lida durante un determinado contexto temporal&amp;nbsp;(desplazamiento de bits para convertir &lt;em&gt;handles&lt;/em&gt; de 32 bits a 16 bits, y viceversa) puede ser totalmente err&amp;oacute;nea en el momento que&amp;nbsp;se introduzca alg&amp;uacute;n tipo de &amp;quot;ampliaci&amp;oacute;n&amp;quot; con la que no se contaba en ese momento. La implementaci&amp;oacute;n desde un principio de la tabla de correspondencias habr&amp;iacute;a ahorrado un buen n&amp;uacute;mero de &lt;a target="_blank" href="http://www.google.com/search?hl=en&amp;amp;q=%22The+Win+16+Subsystem+has+insufficient+resources+to+continue+running%22"&gt;usuarios disgustados&lt;/a&gt; por la soluci&amp;oacute;n temporal.&lt;/p&gt;
&lt;p&gt;Ya como curiosidad final,&amp;nbsp;y esto ya es m&amp;aacute;s una opini&amp;oacute;n personal,&amp;nbsp;si se da cuenta,&amp;nbsp;la cadena de texto en espa&amp;ntilde;ol contiene la nomenclatura inglesa (&amp;quot;Win 16 Subsystem&amp;quot;), cuando el resto de cadenas de Wow32.dll que hacen referencia a este concepto&amp;nbsp;usan su acertada traducci&amp;oacute;n al espa&amp;ntilde;ol, &amp;quot;Subsistema Windows de 16 bits&amp;quot;. &amp;Eacute;sta podr&amp;iacute;a ser otra prueba m&amp;aacute;s de que la implementaci&amp;oacute;n de esta soluci&amp;oacute;n temporal lleg&amp;oacute; muy, pero que muy tarde en el ciclo de desarrollo de Windows XP.&lt;/p&gt;</description></item><item><title>Avoiding access to base tables using Foreign Key, and two suggestions...</title><link>http://msmvps.com/blogs/eladio_rincon/archive/2008/08/25/avoiding-access-to-base-tables-using-foreign-key-and-two-suggestions.aspx</link><pubDate>Mon, 25 Aug 2008 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1645743</guid><dc:creator>Eladio</dc:creator><description>&lt;p&gt;Just a note before going further: I am going to maintain my blog in Spanish and English:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The English version will be hosted at msmvps.com (&lt;a title="http://msmvps.com/blogs/eladio_rincon/Default.aspx" href="http://msmvps.com/blogs/eladio_rincon"&gt;http://msmvps.com/blogs/eladio_rincon&lt;/a&gt;) &lt;/li&gt; &lt;li&gt;The Spanish version will be hosted at Solid Quality Mentors blog -- El Rincón del DBA (&lt;a title="http://blogs.solidq.com/ES/ElRinconDelDBA" href="http://blogs.solidq.com/ES/ElRinconDelDBA"&gt;http://blogs.solidq.com/ES/ElRinconDelDBA)&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Frequently, as a trainer and consultant I have to face in our clients the benefits that customers can get implementing DRI in their systems. I usually get different arguments such us:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;If I don&amp;#39;t define Foreign Keys, it is easier to perform bulk operations.  &lt;li&gt;I prefer to validate the integrity in the Data tier instead of the database.  &lt;li&gt;All the access to the base table is done using a set of stored procedures that I manage.  &lt;li&gt;We prefer not implementing DRI because our data model changes very frequently, and it is complex to change the database logical design.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I could count many more cases apart of those four; from my experiencie, I think that generally the root cause is related to their ALM processes, and their best practices. Almost always, you can come up with a safer and better design solution; in fact, during the classes and the mentoring sessions, you convice them to go for the change, but days after, they come back to their daily work, and they do not have time to GO for the change.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Here is a good post from Conor Cunningham (&lt;a title="http://blogs.msdn.com/conor_cunningham_msft/archive/2008/08/07/foreign-keys-are-our-friends.aspx" href="http://blogs.msdn.com/conor_cunningham_msft/archive/2008/08/07/foreign-keys-are-our-friends.aspx"&gt;http://blogs.msdn.com/conor_cunningham_msft/archive/2008/08/07/foreign-keys-are-our-friends.aspx&lt;/a&gt;) showing a hidden benefits of using DRI that you may not know: &lt;strong&gt;Using DRI SQL Server Optimizer, may dedice not to access base tables&lt;/strong&gt; because SQL Server already knows -- due to the DRI -- that if a row exist child table, it must exists one in the parent table.&lt;/p&gt; &lt;p&gt;However, I would like to make some suggestions in this matter, that you may see useful. &lt;/p&gt; &lt;p&gt;Using a very similar script to Conors&amp;#39;:&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2"&gt;  &lt;tr&gt; &lt;td&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;use AdventureWorks2008;&lt;br /&gt;go &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" size="3"&gt;&lt;/font&gt;&lt;font color="#800000"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;drop table f1&lt;br /&gt;drop table t1&lt;br /&gt;go &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" size="3"&gt;&lt;font color="#800000"&gt;create table t1(id int, v char(1) default &amp;#39;a&amp;#39;&lt;br /&gt;&amp;nbsp; , constraint t1_pk primary key (id))&lt;br /&gt;go&lt;br /&gt;&lt;/font&gt;&lt;/p&gt;&lt;/font&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;create table f1(f_id int identity, t_id int not null, v char(1) default &amp;#39;a&amp;#39;&lt;br /&gt;&amp;nbsp; , constraint f1_pk primary key (f_id) &lt;br /&gt;&amp;nbsp; , constraint fk1 FOREIGN KEY (t_id) REFERENCES t1(id)) &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;go&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" size="3"&gt;&lt;br /&gt;&lt;font color="#800000"&gt;create nonclustered index nci_f1_t_id &lt;br /&gt;on f1 (t_id) &lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="cour" size="2"&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;declare @i int=0&lt;br /&gt;set nocount on&lt;br /&gt;while @i &amp;lt; 2000&lt;br /&gt;begin&lt;br /&gt;&amp;nbsp; insert into t1 (id) values (@i)&lt;br /&gt;&amp;nbsp; insert into f1 (t_id) values (@i)&lt;br /&gt;&amp;nbsp; insert into f1 (t_id) values (@i)&lt;br /&gt;&amp;nbsp; insert into f1 (t_id) values (@i)&lt;br /&gt;&amp;nbsp; set @i+= 1&lt;br /&gt;end&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Conor pointed in his post, those two queries does not need to access the base table -- as you can see in the execution plan:&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2"&gt;  &lt;tr&gt; &lt;td&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;/*&lt;br /&gt;&amp;nbsp; |--Index Scan(OBJECT:([AdventureWorks2008].[dbo].[f1].[nci_f1_t_id]))&lt;br /&gt;*/&lt;br /&gt;select f1.* &lt;br /&gt;from t1 inner join f1 &lt;br /&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;on t1.id = f1.t_id&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;/*&lt;br /&gt;&amp;nbsp; |--Index Scan(OBJECT:([AdventureWorks2008].[dbo].[f1].[nci_f1_t_id]))&lt;br /&gt;*/&lt;br /&gt;select f1.* from f1 where &lt;br /&gt;exists (select * from t1 where t1.id = f1.t_id)&lt;/font&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;And I&amp;#39;d like to &lt;strong&gt;suggest&lt;/strong&gt; to the SQL Server Team considering those two cases as well:&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2"&gt;  &lt;tr&gt; &lt;td&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;/*&lt;br /&gt;|--Nested Loops(Inner Join)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Clustered Index Seek(OBJECT:([AW].[dbo].[t1].[t1_pk]), SEEK:([AW].[dbo].[t1].[id]=(1)) ORDERED FORWARD)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Nested Loops(Inner Join, OUTER REFERENCES:([AW].[dbo].[f1].[f_id]))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Index Seek(OBJECT:([AW].[dbo].[f1].[nci_f1_t_id]), SEEK:([AW].[dbo].[f1].[t_id]=(1)) ORDERED FORWARD)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Clustered Index Seek(OBJECT:([AW].[dbo].[f1].[f1_pk]), SEEK:([AW].[dbo].[f1].[f_id]=[AW].[dbo].[f1].[f_id]) LOOKUP ORDERED FORWARD)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;*/&lt;br /&gt;select f1.* from &lt;br /&gt;t1 inner join f1 &lt;br /&gt;on t1.id = f1.t_id&lt;br /&gt;where f1.t_id = 1&lt;/font&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt; &lt;p&gt;&lt;font face="Lucida Console" color="#800000" size="3"&gt;/*&lt;br /&gt;&amp;nbsp; |--Merge Join(Inner Join, MERGE:([AW].[dbo].[t1].[id])=([AW].[dbo].[f1].[t_id]), RESIDUAL:([AW].[dbo].[f1].[t_id]=[AW].[dbo].[t1].[id]))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Clustered Index Scan(OBJECT:([AW].[dbo].[t1].[t1_pk]), ORDERED FORWARD)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Index Scan(OBJECT:([AW].[dbo].[f1].[nci_f1_t_id]), ORDERED FORWARD)&lt;br /&gt;*/&lt;br /&gt;select t1.id, f1.* &lt;br /&gt;from t1 inner join f1 &lt;br /&gt;on t1.id = f1.t_id&lt;/font&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The first query, implements a typical OLTP query looking for all the detail rows for a given parent. In this example, SQL Server already knows that for each row in the child table (f1), at least exists one row in the header (t1). The only difference with the first query from Connor&amp;#39;s post is the predicate, that I think fires the behaviour. In my humble opinion, the filter is highly selective, and then sets the t1 table in best position to be seek&amp;quot;ed&amp;quot;.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The second query, seems to be a bit awkward, because SQL Server already knows that t1.id = f1.t_id. Why accessing t1 table, if the matching values are already in f1.t_id?&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;If you think that those last &amp;quot;logical suggestions&amp;quot; to avoid accesing parent tables should be considered by SQL Server, please, go to &lt;strong&gt;Conect &lt;/strong&gt;and cast your &lt;strong&gt;vote &lt;/strong&gt;(&lt;a title="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=363429" href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=363429"&gt;https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=363429&lt;/a&gt;).&lt;/p&gt;</description></item><item><title>Cerrar Explorer sin cerrar la sesi&amp;#243;n</title><link>http://msmvps.com/blogs/dmartin/archive/2008/08/11/cerrar-explorer-sin-cerrar-la-sesi-243-n.aspx</link><pubDate>Mon, 11 Aug 2008 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1644234</guid><dc:creator>dmartin</dc:creator><description>&lt;p&gt;Completando la informaci&amp;oacute;n del art&amp;iacute;culo anterior sobre Explorer, dejo por aqu&amp;iacute; un &amp;quot;truco&amp;quot; que quiz&amp;aacute; no conozca: En Windows Vista, al abrir el men&amp;uacute; Inicio, pulsar simult&amp;aacute;neamente las teclas Ctrl y Shift (May&amp;uacute;sculas) y hacer clic con el bot&amp;oacute;n derecho sobre una regi&amp;oacute;n libre del men&amp;uacute;, nos aparecer&amp;aacute; una opci&amp;oacute;n adicional a la ya cl&amp;aacute;sica &amp;quot;Propiedades&amp;quot;: &amp;quot;Salir de Explorer&amp;quot;. Esta opci&amp;oacute;n es especialmente &amp;uacute;til cuando haya realizado alg&amp;uacute;n cambio en la configuraci&amp;oacute;n que requiera de un reinicio del explorador para que surta efecto. Hasta ahora quiz&amp;aacute;&amp;nbsp;lo que haya hecho es &amp;quot;matar&amp;quot; al proceso Explorer.exe usando Process Explorer, con todos los riesgos que conlleva el &amp;quot;matar&amp;quot; a un proceso. La opci&amp;oacute;n &amp;quot;Salir de Explorer&amp;quot; realiza los pasos correctos de cierre del explorador, que incluyen, entre otras cosas,&amp;nbsp;el almacenar en el Registro del sistema ciertas configuraciones residentes en memoria. Al &amp;quot;matar&amp;quot; al proceso estas configuraciones se pierden irremediablemente.&lt;/p&gt;
&lt;p&gt;Lamentablemente, esta opci&amp;oacute;n no est&amp;aacute; presente en Windows XP y anteriores, por lo que tendr&amp;aacute; que, como m&amp;iacute;nimo, reiniciar la sesi&amp;oacute;n para lograr un efecto similar en esos sistemas.&lt;/p&gt;</description></item><item><title>Acabando con los mitos: Memoria usada por bases de datos (Database Snapshot)</title><link>http://msmvps.com/blogs/eladio_rincon/archive/2007/12/04/acabando-con-los-mitos-memoria-usada-por-bases-de-datos-database-snapshot.aspx</link><pubDate>Tue, 04 Dec 2007 06:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1377797</guid><dc:creator>Eladio</dc:creator><description>&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Hace unos días, vimos que independientemente de la base de datos desde la que se accedía a la información, las páginas leídas no se duplicaban en el buffer cache. Sin embargo, ¿qué pasa con Database Snapshot? ¿Funcionará igual?
&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Pequeña introducción a Database Snapshot (DBS).
&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Lo que DBS nos aporta es una vista de la base de datos en un instante determinado (cuando se creó). Lo que hace por debajo SQL Server, es que cuando el usuario necesita información de la BD DBS:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Si los datos NO se han modificado desde el momento de la creación de la DBS, leerá la información de la BD original.
&lt;/li&gt;&lt;li&gt;Si los datos SI se han modificado desde el momento de la creación de la DBS, leerá la información de la DBS combinándola con la información de la BD original: por ejemplo, una tabla que en el momento de la creación del snapshot tenía 5 filas, y en el momento actual tiene 3, para consultar el estado de la tabla en el estado original leerá 3 filas de la BD original + 2 filas de la BDS.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Veamos cómo funciona internamente más allá de la explicación conceptual; Primero crearemos una tabla grande en la base de datos Adventureworks con el siguiente script (tabla con 1 millón de filas):
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;use&lt;/span&gt; Adventureworks&lt;br /&gt;go
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;
			&lt;span style="color:gray;"&gt;exists&lt;/span&gt;
			&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;select&lt;/span&gt;
			&lt;span style="color:gray;"&gt;*&lt;/span&gt;
			&lt;span style="color:blue;"&gt;from&lt;/span&gt;
			&lt;span style="color:green;"&gt;sys.tables&lt;/span&gt;
			&lt;span style="color:blue;"&gt;where&lt;/span&gt;
			&lt;span style="color:blue;"&gt;name&lt;/span&gt;
			&lt;span style="color:gray;"&gt;=&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;tabla_1Millon_filas&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;drop&lt;/span&gt;
			&lt;span style="color:blue;"&gt;table&lt;/span&gt; tabla_1Millon_filas&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;/span&gt;go&lt;span style="color:gray;"&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;create&lt;/span&gt;
			&lt;span style="color:blue;"&gt;table&lt;/span&gt; tabla_1Millon_filas &lt;span style="color:gray;"&gt;(&lt;br /&gt;&lt;/span&gt;    id1 &lt;span style="color:blue;"&gt;bigint&lt;/span&gt;
			&lt;span style="color:blue;"&gt;identity&lt;/span&gt;
			&lt;span style="color:blue;"&gt;primary&lt;/span&gt;
			&lt;span style="color:blue;"&gt;key&lt;/span&gt;&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt; relleno &lt;span style="color:blue;"&gt;char&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;50&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:blue;"&gt;default&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt; v &lt;span style="color:blue;"&gt;char&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;1&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;null)&lt;br /&gt;&lt;/span&gt;go&lt;span style="color:gray;"&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:green;"&gt;-- insertar 1.000 x 1.000 = 1.000.000 filas&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;declare&lt;/span&gt; @i &lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;set&lt;/span&gt; @i&lt;span style="color:gray;"&gt;=&lt;/span&gt;1&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;while&lt;/span&gt; @i&lt;span style="color:gray;"&gt;&amp;lt;=&lt;/span&gt;1000&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;begin&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;insert&lt;/span&gt; tabla_1Millon_filas &lt;span style="color:gray;"&gt;(&lt;/span&gt;v&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;select&lt;/span&gt;
			&lt;span style="color:blue;"&gt;top&lt;/span&gt;
			&lt;span style="color:gray;"&gt;(&lt;/span&gt;1000&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;null&lt;/span&gt;
			&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;from&lt;/span&gt; Sales&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderHeader&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;set&lt;/span&gt; @i&lt;span style="color:gray;"&gt;=&lt;/span&gt;@i&lt;span style="color:gray;"&gt;+&lt;/span&gt;1&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;end&lt;/span&gt;&lt;span style="color:green;"&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;select&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt; [cantidad] &lt;span style="color:blue;"&gt;from&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;tabla_1Millon_filas
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;A continuación crearemos el snapshot; para ello ejecutaremos la siguiente instrucción:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;
			&lt;span style="color:gray;"&gt;exists&lt;/span&gt;
			&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;select&lt;/span&gt;
			&lt;span style="color:blue;"&gt;name&lt;/span&gt;
			&lt;span style="color:blue;"&gt;from&lt;/span&gt;
			&lt;span style="color:green;"&gt;sys.databases&lt;/span&gt;
			&lt;br /&gt;        &lt;span style="color:blue;"&gt;where&lt;/span&gt;
			&lt;span style="color:blue;"&gt;name&lt;/span&gt;
			&lt;span style="color:gray;"&gt;=&lt;/span&gt; N&lt;span style="color:red;"&gt;&amp;#39;DBS_Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;drop&lt;/span&gt;
			&lt;span style="color:blue;"&gt;database&lt;/span&gt; DBS_Adventureworks&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;/span&gt;go&lt;span style="color:gray;"&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:green;"&gt;-- create the snapshot database&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;create&lt;/span&gt;
			&lt;span style="color:blue;"&gt;database&lt;/span&gt; DBS_Adventureworks &lt;span style="color:blue;"&gt;on&lt;/span&gt;
			&lt;span style="color:gray;"&gt;(&lt;/span&gt;
			&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;name&lt;/span&gt;
			&lt;span style="color:gray;"&gt;=&lt;/span&gt; Adventureworks_Data&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;
			&lt;span style="color:blue;"&gt;filename&lt;/span&gt;
			&lt;span style="color:gray;"&gt;=&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;c:\program files\microsoft sql server\mssql.1\mssql\data\dbs_Adventureworks.ss&amp;#39;&lt;/span&gt;
			&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;as&lt;/span&gt;
			&lt;span style="color:blue;"&gt;snapshot&lt;/span&gt;
			&lt;span style="color:blue;"&gt;of&lt;/span&gt; Adventureworks&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;span style="color:green;"&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;A continuación, borraremos de la base de datos original (Adventureworks), las 10.000 primeras filas:
&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:green;"&gt;-- borrado de 10.000 filas&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;use&lt;/span&gt; Adventureworks&lt;br /&gt;go&lt;br /&gt;&lt;span style="color:blue;"&gt;delete&lt;/span&gt;
			&lt;span style="color:blue;"&gt;from&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;tabla_1Millon_filas&lt;br /&gt;&lt;span style="color:blue;"&gt;where&lt;/span&gt; id1 &lt;span style="color:gray;"&gt;&amp;lt;=&lt;/span&gt; 10000
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Y ahora ya estamos preparados para ver el comportamiento de las lecturas. Usaremos la siguiente consulta que devuelve el número de páginas en memoria para cada base de datos – con la que ya estás familiarizado:&lt;br /&gt;
	&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt;
			&lt;span style="color:blue;"&gt;AS&lt;/span&gt; cached_pages_count&lt;br /&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;*&lt;/span&gt; 8. &lt;span style="color:gray;"&gt;/&lt;/span&gt; 1024 &lt;span style="color:blue;"&gt;AS&lt;/span&gt; MB&lt;br /&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE&lt;/span&gt; database_id &lt;br /&gt;
			&lt;span style="color:blue;"&gt;WHEN&lt;/span&gt; 32767 &lt;span style="color:blue;"&gt;THEN&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;ResourceDb&amp;#39;&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:blue;"&gt;ELSE&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:blue;"&gt;END&lt;/span&gt;
			&lt;span style="color:blue;"&gt;AS&lt;/span&gt; Database_name&lt;br /&gt;&lt;span style="color:blue;"&gt;FROM&lt;/span&gt;
			&lt;span style="color:green;"&gt;sys.dm_os_buffer_descriptors&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;IN&lt;/span&gt;&lt;br /&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;DBS_Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;GROUP&lt;/span&gt;
			&lt;span style="color:blue;"&gt;BY&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;database_id
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Primero limpiaremos el cache de datos para tener unos resultados exactos (por favor, no ejecutar esto en producción&lt;span style="font-family:Wingdings;"&gt;J&lt;/span&gt;):
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:green;"&gt;-- limpieza de caché&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;use&lt;/span&gt;
			&lt;span style="color:blue;"&gt;master&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;dbcc&lt;/span&gt; dropcleanbuffers&lt;span style="color:gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;dbcc&lt;/span&gt; freeproccache&lt;span style="color:gray;"&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Habilitaremos STATISTICS IO que también nos muestra información válida en cuanto a las lecturas físicas y lógicas realizadas:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;set&lt;/span&gt;
			&lt;span style="color:blue;"&gt;statistics&lt;/span&gt;
			&lt;span style="color:blue;"&gt;io&lt;/span&gt;
			&lt;span style="color:blue;"&gt;on
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Y a continuación, contaremos las filas que tiene la tabla de 1 millón de filas en cada base de datos con la siguiente consulta:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;use&lt;/span&gt; DBS_Adventureworks&lt;br /&gt;go&lt;br /&gt;&lt;span style="color:blue;"&gt;print&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;Snapshot...&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;select&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt; [cantidad_en_snapshot]&lt;br /&gt;&lt;span style="color:blue;"&gt;from&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;tabla_1Millon_filas&lt;br /&gt;go
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt;
			&lt;span style="color:blue;"&gt;AS&lt;/span&gt; cached_pages_count&lt;br /&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;*&lt;/span&gt; 8. &lt;span style="color:gray;"&gt;/&lt;/span&gt; 1024 &lt;span style="color:blue;"&gt;AS&lt;/span&gt; MB&lt;br /&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE&lt;/span&gt; database_id &lt;br /&gt;
			&lt;span style="color:blue;"&gt;WHEN&lt;/span&gt; 32767 &lt;span style="color:blue;"&gt;THEN&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;ResourceDb&amp;#39;&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:blue;"&gt;ELSE&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:blue;"&gt;END&lt;/span&gt;
			&lt;span style="color:blue;"&gt;AS&lt;/span&gt; Database_name&lt;br /&gt;&lt;span style="color:blue;"&gt;FROM&lt;/span&gt;
			&lt;span style="color:green;"&gt;sys.dm_os_buffer_descriptors&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;IN&lt;/span&gt;&lt;br /&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;DBS_Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;GROUP&lt;/span&gt;
			&lt;span style="color:blue;"&gt;BY&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;database_id&lt;br /&gt;go
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;use&lt;/span&gt; Adventureworks&lt;br /&gt;go&lt;br /&gt;&lt;span style="color:blue;"&gt;print&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;Source bd...&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;select&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt; [cantidad_en_bd_original]&lt;br /&gt;&lt;span style="color:blue;"&gt;from&lt;/span&gt; dbo.tabla_1Millon_filas&lt;br /&gt;go
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt;
			&lt;span style="color:blue;"&gt;AS&lt;/span&gt; cached_pages_count&lt;br /&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;count&lt;/span&gt;&lt;span style="color:gray;"&gt;(*)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;*&lt;/span&gt; 8. &lt;span style="color:gray;"&gt;/&lt;/span&gt; 1024 &lt;span style="color:blue;"&gt;AS&lt;/span&gt; MB&lt;br /&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE&lt;/span&gt; database_id &lt;br /&gt;
			&lt;span style="color:blue;"&gt;WHEN&lt;/span&gt; 32767 &lt;span style="color:blue;"&gt;THEN&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;ResourceDb&amp;#39;&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:blue;"&gt;ELSE&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;br /&gt;
			&lt;span style="color:blue;"&gt;END&lt;/span&gt;
			&lt;span style="color:blue;"&gt;AS&lt;/span&gt; Database_name&lt;br /&gt;&lt;span style="color:blue;"&gt;FROM&lt;/span&gt;
			&lt;span style="color:green;"&gt;sys.dm_os_buffer_descriptors&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;IN&lt;/span&gt;&lt;br /&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;&amp;#39;DBS_Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;GROUP&lt;/span&gt;
			&lt;span style="color:blue;"&gt;BY&lt;/span&gt;
			&lt;span style="color:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;database_id&lt;span style="color:gray;"&gt;)&lt;/span&gt;
			&lt;span style="color:gray;"&gt;,&lt;/span&gt;database_id&lt;br /&gt;go
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Y obtenemos los siguientes resultados:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;cached_pages_count          MB          Database_name&lt;br /&gt;-----------------------------------------------------&lt;br /&gt;114          0.890625          AdventureWorks&lt;br /&gt;&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;Snapshot...&lt;br /&gt;cantidad_en_snapshot&lt;br /&gt;--------------------&lt;br /&gt;1000000&lt;br /&gt;&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;cached_pages_count          MB          Database_name&lt;br /&gt;-----------------------------------------------------&lt;br /&gt;10261           80.164062          DBS_Adventureworks&lt;br /&gt;  114           0.890625           AdventureWorks&lt;br /&gt;&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;Source bd...&lt;br /&gt;cantidad_en_bd_original&lt;br /&gt;-----------------------&lt;br /&gt;990000&lt;br /&gt;&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;cached_pages_count          MB          Database_name&lt;br /&gt;-----------------------------------------------------&lt;br /&gt;&lt;span style="color:red;"&gt;10261&lt;/span&gt;
			&lt;span style="color:red;"&gt;80.164062&lt;/span&gt;
			&lt;span style="color:red;"&gt;DBS_Adventureworks&lt;/span&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;10324&lt;/span&gt;
			&lt;span style="color:red;"&gt;80.656250&lt;/span&gt;
			&lt;span style="color:red;"&gt;AdventureWorks&lt;/span&gt;&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Que nos deja un poco sorprendidos: fíjate que de la BDS, tenemos en memoria más de 10.000 páginas, al igual que las 10.000 de la BD original. Que nos viene a tirar por tierra otro mito que existe en la comunidad, obteniendo la siguiente conclusión:
&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Cuando la BDS necesita leer páginas de la BD original, las páginas las sube a su caché de datos (el de la BD), independientemente de que las tenga o no &amp;quot;cargadas&amp;quot; la BD Original.
&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Unos cuantos datos más: si te fijas en el resultado de Statistics IO, el resultado de las physical reads nos deja un poco traspuestos &lt;span style="font-family:Wingdings;"&gt;J&lt;/span&gt;:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;Snapshot...&lt;br /&gt;cantidad_en_snapshot&lt;br /&gt;--------------------&lt;br /&gt;1000000&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;Table &amp;#39;tabla_1Millon_filas&amp;#39;. Scan count 1, logical reads 10253, &lt;span style="color:red;"&gt;physical reads 0, read-ahead reads 10253&lt;/span&gt;, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;Source bd...&lt;br /&gt;cantidad_en_bd_original&lt;br /&gt;-----------------------&lt;br /&gt;990000&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:9pt;"&gt;Table &amp;#39;tabla_1Millon_filas&amp;#39;. Scan count 1, logical reads 10153, physical &lt;span style="color:red;"&gt;reads 1, read-ahead reads 10149&lt;/span&gt;, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.&lt;br /&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;¿Tiene algún sentido que en una BD con la caché limpia (hemos ejecutado cleanbuffers), se lea el contenido de una tabla de usuario sin realizar lecturas físicas? Y además, ¿existe la posibilidad de realizar 0 lecturas físicas, y de esas lecturas físicas se lean por adelantado (read-ahead) más de 10.000 páginas? No, ¿verdad? pues STATISTICS IO nos ha engañado &lt;span style="font-family:Wingdings;"&gt;J&lt;/span&gt;
	&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Para dejar la base de datos en el estado original utilizaremos el comando RESTORE:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;use&lt;/span&gt;
			&lt;span style="color:blue;"&gt;master&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;restore&lt;/span&gt;
			&lt;span style="color:blue;"&gt;database&lt;/span&gt; Adventureworks&lt;br /&gt;&lt;span style="color:blue;"&gt;from&lt;/span&gt;
			&lt;span style="color:blue;"&gt;database_snapshot&lt;/span&gt;
			&lt;span style="color:gray;"&gt;=&lt;/span&gt;
			&lt;span style="color:red;"&gt;&amp;#39;DBS_Adventureworks&amp;#39;&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;Conclusiones&lt;/span&gt;:&lt;span style="text-decoration:underline;"&gt;
			&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Aunque conceptualmente, DBS combina los datos que mantiene la BD Original + los cambios sucedidos desde la creación de la DBS, cada base de datos es independiente, y los datos que necesita leer, residirán en su propia área de memoria:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;La BD Original en el momento de creación del Snapshot tenía 100 páginas.
&lt;/li&gt;&lt;li&gt;Con el paso del tiempo de la original se borraron 30 páginas, por lo que en la Snapshot se registraron las 30 páginas &amp;quot;cambiadas&amp;quot;.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Al realizar lecturas de páginas sucederá lo siguiente:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Lecturas en la BDS de la tabla original devolverá 100 páginas, y en su área de memoria contendrá las 100 páginas.
&lt;/li&gt;&lt;li&gt;Lecturas en la BD Original leerán las 70 páginas, y en su área de memoria contendrá las 70 páginas.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;strong&gt;
		&lt;/strong&gt; &lt;/p&gt;</description></item></channel></rss>