miércoles, 14 de diciembre de 2011

Liberar el puerto 80 en Windows 7

Me acaba de pasar que, a la hora de depurar un proyecto, el Visual Studio me obsequie con este mensajito:

No se puede iniciar el servidor de desarrollo de Visual Studio.
El puerto 80 está en uso.


El problema es que hay algún servicio que está ocupando el puerto 80, y el servidor de desarrollo de VS "Cassini" no se puede arrancar.

Una solución es cambiar el puerto en el servidor de desarrollo.
En el proyecto, botón derecho, propiedades, y le cambiamos el puerto




Si no queremos cambiar el puerto, otra solución es encontrar el servicio que lo ocupa.
Para ello, abrimos la consola (cmd) y ejecutamos "netstat -ab"


Allí vemos que el TCP 80 lo tiene ocupado un servicio del que no tenemos más información.
Así que nos toca ir a los servicios que pudieran ser sospechosos de estar ocupando el puerto 80, pararlos y probar el "netstat -ab" hasta que el puerto 80 quede liberado.

Para parar los servicios, escribid "services.msc" en el botón "inicio -> buscar programas y archivos"

Los servicios que son candidatos a ocupar el puerto 80 son:
"Servicio Agente de implementación web" (lo instala el Web Deploy 2.0)
"SQL Server Reporting Services (MSSQLSERVER)"
"SQL Server Integration Services 10.0"
 "BrandCache"

Internet Information Server y el Apache o XAMPP también se cogen el puerto 80 por defecto.

La solución correcta es, una vez detectado el programa que lo ocupa, cambiarlo en su configuración a otro puerto en vez de ir parando servicios.

viernes, 2 de diciembre de 2011

Error en el DNS-323: Acceso denegado




Tengo un NAS D-Link DNS-323.

 En él confío todos mis documentos, fotos, programas, etc.

Tiene 2 discos duros y se puede configurar para usarlos por separado, linealmente, Raid0 o Raid1 (en espejo).

Ya empezaba a confiar plenamente en él cuando, de repente un día, al acceder a una carpeta, aparece un mensaje de error:"ACCESO DENEGADO".

Recorro todo el disco y veo que hay algunos archivos y carpetas con ese problema. No puede verlos, ni copiarlos, ni moverlos...

Un sudor frío recorre mi cuerpo cuando veo carpetas de fotos de momentos importantes con ese problema.


WTF?  (¿Pero qué narices le pasa?)

El DNS-323 lleva internamente Linux, y expone un servidor samba a la red.
Parece que el Windows Vista y Windows 7, al haber aumentado los niveles de seguridad, ha perdido alguna compatibilidad con Samba, en el modo Share.

He recopilado los siguientes enlaces que hablan del tema.

http://www.sevenforums.com/network-sharing/3737-samba-network-share-issue-windows-7-a-3.html

http://web.mit.edu/rhel-doc/4/RH-DOCS/rhel-rg-es-4/s1-samba-security-modes.html

http://superuser.com/questions/115337/windows-7-connecting-to-samba-shares

http://www.arkko.com/linux/vistanas.html

Como solución, casi todos hablan de rebajar el nivel de seguridad de Windows7 y ponerlo a la altura de Samba, o cambiar el modo de seguridad de Share a User


Opté por otra línea de trabajo; y así poder saber recuperar los documentos (que es realmente lo que me interesa) : Poder dar permisos a los ficheros.

Aprovechando que el firmware del dns-323 puede ejecutar scripts, instalamos un software llamado fun_plug que nos monta un linux con su servicio Telnet arrancado.


En este enlace se explica de forma extensa los pasos a seguir.
http://nas-tweaks.net/40/installation-of-the-fonz-funplug-0-5-for-ch3snas-ch3mnas-dns-323-and-many-more/

Los pasos a seguir son:
  • Nos descargamos los ficheros fun_plug y fun_plug.tgz de aquí.
  • Lo copiamos al raíz del DNS-323
  • Reiniciamos.
A partir de ahora, tendremos el telnet activado.
También tendremos una carpeta "ffp" que es el sistema de ficheros que ha creado.

Por línea de comando, podemos hacer "telnet 192.168.2.X" (ojo, poned la IP vuestra :))

Para aplicar contraseña, seguiremos los siguientes pasos dentro del telnet:

pwconv
passwd
usermod -s /ffp/bin/sh root

pwck
grpck

login

Comprobamos que funciona todo bien.

Ahora guardamos el password con el comando
store-passwd.sh

Con estos pasos, tenemos acceso al NAS a través de un telnet protegido por contraseña.

Ahora queda localizar las carpetas y ver qué permisos tienen los archivos.

Con ls -l tenemos una vista a los permisos de los ficheros.
El disco se monta en /mnt/HD_a2















Los casos de ficheros que daban problemas tenían permisos rwx --- --- y usuario nobody.

(El usuario Nobody es equivalente al usuario anónimo).

Sin meternos en tema de usuarios, grupos y demás, nos situamos en el directorio de archivos que queramos cambiar y ejecutaremos:

chmod 777 *

Si queremos cambiar los permisos en los subdirectorios:

chmod -R 777 *

En este caso, podemos ver que los permisos cambian a rwx rwx rwx, y ya son accesibles desde Windows.

Esto es todo; espero que os sea de utilidad.








lunes, 21 de noviembre de 2011

El todopoderoso control listview (1)

El control ListView de ASP.NET (no confundirlo con el control ListView de WinForms) es un nuevo control ASP.NET que apareció en el Framework 3.5.

La documentacíón completa del control la tenéis en http://msdn.microsoft.com/es-es/library/system.web.ui.webcontrols.listview.aspx

Otro artículo muy bueno lo tenéis en http://msdn.microsoft.com/es-es/magazine/cc337898.aspx

Lo de "todopoderoso" lo digo porque puede sustituir a todos los controles enlazables (Repeater, gridview, formview, detailsview...), con lo que usando sólo este control puedes hacer cualqier control enlazado.  (pudiendo hacer incluso gridviews con inserciones!!!)

El secreto del ListView es el uso de las plantillas.

Si, por ejemplo, quisiéramos montar una grid, montaríamos algo parecido a esto:


En el Layout template definiríamos el formato de la parte externa a los datos (encabezado, pie...)

En el ItemTemplate definiríamos el formato que queremos de los datos




Un ejemplo básico

Vamos a ver un ejemplo:

Creamos una clase "Persona.cs"

public class Persona
{    
     public int Id { get; set; }    
     public string Nombre { get; set; }    
     public string Apellidos { get; set; }    
     public string Poblacion { get; set; }
}

Creamos una clase "RepPersona.cs", que hará de repositorio y de almacén de datos. Por supuesto, en un entorno real, los métodos irían contra una base de datos, pero por simplificar, lo hacemos con una lista.
public class RepPersona
{
    protected List<Persona> _personas = new List<Persona>();

    public RepPersona()
    {
        _personas.Add(new Persona() { Id = 1, Nombre = "Jose", Apellidos = "Garcia", Poblacion = "Valencia" });
        _personas.Add(new Persona() { Id = 2, Nombre = "Manuel", Apellidos = "Martinez", Poblacion = "Barcelona" });
        _personas.Add(new Persona() { Id = 3, Nombre = "Juan", Apellidos = "Gómez", Poblacion = "Madrid" });
    }

    public List<Persona> DamePersonas()
    {
        return _personas.ToList<Persona>();
    }
}


Ahora crearemos una página ASP.NET y crearemos el ObjectDataSource que lea los datos del repositorio y el ListView

<asp:ObjectDataSource runat="server" ID="odsDatos" DataObjectTypeName="Persona"
    SelectMethod="DamePersonas" TypeName="RepPersona"> </asp:ObjectDataSource>


<asp:ListView runat="server" ID="lvwDatos" DataSourceID="odsDatos">
    <LayoutTemplate>
        <table class="tabla1">
            <tr>
                <th>Id</th>
                <th>Nombre</th>
                <th>Apellidos</th>
                <th>Poblacion</th>
            </tr>

        <asp:PlaceHolder runat="server" ID="ItemPlaceholder"/>
        </table>     
    </LayoutTemplate>
    <ItemTemplate>
        <tr>
            <td><%#Eval("Id") %></td>
            <td><%#Eval("Nombre")%></td>
            <td><%#Eval("Apellidos")%></td>
            <td><%#Eval("Poblacion")%></td>
        </tr>
    

    </ItemTemplate>  
</asp:ListView>


Este código devolvería el siguiente resultado:

Aquí vemos una sección de LayoutTemplate, con un PlaceHolder, y un ItemTemplate.

En el LayoutTemplate, vemos la parte fija; es decir, el <table> y el encabezado.
El PlaceHolder es sustituido por el ItemPlaceHolder tantas veces como registros hayan.

Al ListView, en este caso, no hace falta que se le especifique el nombre del PlaceHolder si el PlaceHolder se llama "ItemPlaceHolder". Si el PlaceHolder se llamara de otra forma, habría que especificar el atributo "ItemPlaceholderID" con el nombre especificado.

Trabajar con plantillas es una forma muy flexible de representar datos.



Vamos a mostrar otro formato de plantilla

<asp:ListView runat="server" ID="LvwDatos2" DataSourceID="odsDatos">
    <LayoutTemplate>
        <h2>Personas</h2>
        <asp:PlaceHolder runat="server" ID="ItemPlaceholder"></asp:PlaceHolder>
    </LayoutTemplate>
    <ItemTemplate>
        <table>
            <tr>
                <td >(<%#Eval("Id") %>)</td>
            </tr>
            <tr>
                <td><%#Eval("Apellidos")%>, <%#Eval("Nombre")%></td>
            </tr>
            <tr>
                <td><%#Eval("Poblacion")%></td>
            </tr>
        </table>
    </ItemTemplate>    
    <ItemSeparatorTemplate>
----------
    </ItemSeparatorTemplate>
</asp:ListView>


Esto mostrará la siguiente salida

Aquí vemos que cada ItemTemplate tiene su propia tabla, y que hay un ItemSeparatorTemplate que permite añadir una plantilla entre cada itemTemplate

Agrupaciones

También podremos usar agrupaciones para poder mostrar items agrupados.

Mostremos un ejemplo de ListView con agrupaciones.

<asp:ListView runat="server" ID="LvwDatos3" DataSourceID="odsDatos" GroupItemCount="2">
    <LayoutTemplate>
        <h2>Personas</h2>
        <table>
            <asp:PlaceHolder runat="server" ID="GroupPlaceholder"></asp:PlaceHolder>
        </table>
    </LayoutTemplate>
    <GroupTemplate>
        <tr>
            <asp:PlaceHolder runat="server" ID="ItemPlaceholder"></asp:PlaceHolder>
        </tr>
    </GroupTemplate>
    <ItemTemplate>
        <td>
            <table>
                <tr>
                    <td>(<%#Eval("Id") %>)</td>
                </tr>
                <tr>
                    <td><%#Eval("Apellidos")%>, <%#Eval("Nombre")%></td>
                </tr> 
                <tr>
                    <td><%#Eval("Poblacion")%></td>
                </tr>                         
            </table>
        </td>
    </ItemTemplate>     
</asp:ListView>


Esta plantilla produciría la siguiente salida:


En este código podemos observar:

  • Con el atributo GroupItemCount indicamos el número de Items que aparecerán por grupo.
  • El LayoutTemplate tiene un PlaceHolder con el ID "GroupPlaceHolder". A este ID le pasa lo mismo que el ID "ItemPlaceHolder" Si se usa este ID, no es necesario especificarlo en el atributo "GroupPlaceHolderID" del listview.
  • Con el elemento "GroupTemplate" indicamos el código a usar por el grupo. En este caso, por cada grupo de 2 elementos, insertará una fila nueva de la tabla (<tr>)


De momento, esto es todo por ahora.
Me quedan otros posts donde introduciré las inserciones, las modificaciones y las paginaciones de este "todopoderoso" control.