24 sept 2011

Solución 8 - Excel 2007 API en Windows Server 2008 x64

Una vez creada y publicada la aplicación que usa la API Excel 2007 en Windows Server 2008 x64, puede lanzaros este error al intentar abrir un xlsx con la función Open() de la API :

Microsoft Office Excel cannot access the file 'c:\temp\test.xls'. There are several possible reasons:
• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.


Por mágica que parezca la solución, está reside en crear una nueva carpeta llamada Desktop en C:\Windows\SysWOW64\config\systemprofile\, quedando de esta manera: 

C:\Windows\SysWOW64\config\systemprofile\Desktop

Hay que dar permisos "Control Total" a esta carpeta de la aplicación del IIS (AppPool) de la aplicación web que usa la API Excel 2007. Debe utilizar internamente esta carpeta de forma temporal para realizar la lectura del xlsx.

Aquí tenéis parte de dónde encontré la solución, que nos dice que la creación de la carpeta varia dependiendo la versión del servidor:

...

This solution is ...
・Windows 2008 Server x64

  Please make this folder.

  C:\Windows\SysWOW64\config\systemprofile\Desktop
・Windows 2008 Server x86
  Please make this folder.
  C:\Windows\System32\config\systemprofile\Desktop
  ...instead of dcomcnfg.exe.

...

20 sept 2011

Solución 7 - Problemas de Idioma (CultureInfo) en DCOM Excel

Puede darse el caso que cuando uno esta desarrollando con la API de Excel (Office) tenga instalada la versión en español (en mi caso, Office 2007 español) y luego se tenga en el servidor de producción la versión en inglés (en mi caso, Office 2007 inglés).
Esto pueda acarrear una serie de errores y excepciones genéricos bastante difíciles de interpretar. La solución es poner dos funciones: al principio y final del uso de la API . Estas funciones asignan de forma temporal el CultureInfo que corresponda al idioma del Office de producción:


void SetNewCurrentCulture()
{
    oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
}
void ResetCurrentCulture()
{
    System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
}


Los errores pueden ser desde "Invalid DateTime" hasta de funciones propias de la API de Excel.

19 sept 2011

Solución 6 - Dar permisos DCOM (en Servicio de componentes)

Puede que tengáis que dar permisos a un DCOM dentro de vuestro servidor para poder usar alguna DLL en vuestras aplicaciones. Estos permisos se otorgan desde el "Servicio de componentes", pero puede ser que al registrar este DCOM no encontréis en el Servicio de componentes este servicio nuevo registrado. Eso es debido ha que todavía no se ha actualizado el Servicio de componentes.

Para poder actualizar el configurardor del DCOM (que se encuentra en servicio de componentes) pódeis atajar el problema por otra vía. Se puede ir "montando" poco a poco, gracias a la aplicación "mmc" , gracías a esto podreis obtener una versión actualizada de todos los componentes DCOM y otorgar los permisos.

Me encontré este problema queriendo dar permisos al componente del Office "Microsoft Excel Application", y nunca me había visto con este problema hasta que intente registrarlo en una máquina de 64 bits:


On 64 bit system with 32 bit Office try this:
  1. Start
  2. Run
  3. mmc -32
  4. File
  5. Add Remove Snap-in
  6. Component Services
  7. Add
  8. OK
  9. Console Root
  10. Component Services
  11. Computers
  12. My Computer
  13. DCOM Config
  14. Microsoft Excel Application
  15. ...

14 sept 2011

Solución 5 - "SandCastle"

Automatiza el proceso de documentación.
Permite crear .chm y .html de la documentación que hay incrustada en el código de proyectos, de estética muy similar al MSDN.


Instalar Sandcastle

Instalar el “Sandcastle Help File Builder”


 Para escritorio: Añadir el proyecto/solución.
 Para web y webservices: Es necesario publicar como “updatable” y añadir el web.config una nueva sección (http://www.ewoodruff.us/shfbdocs/Index.aspx?topic=html/b772e00e-1705-4062-adb6-774826ce6700.htm).  Hay que añadir una dll en el Bin: EWSoftware.CodeDom.dll .

<configuration>
  <system.codedom>
    <compilers>
      <!-- For C# -->
      <compiler language="c#;cs;csharp" extension=".cs"
        compilerOptions="/docpath:C:\Publish\Docs"
        type="EWSoftware.CodeDom.CSharpCodeProviderWithDocs,
              EWSoftware.CodeDom, Version=1.1.0.0, Culture=neutral,
              PublicKeyToken=d633d7d5b41cbb65">
        <!-- NOTE: Change value to "v3.5" for .NET 3.5 projects -->
        <providerOption name="CompilerVersion" value="v2.0"/>
      </compiler>
 
      <!-- For VB.NET -->
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
        compilerOptions="/docpath:C:\Publish\Docs"
        type="EWSoftware.CodeDom.VBCodeProviderWithDocs,
              EWSoftware.CodeDom, Version=1.1.0.0, Culture=neutral,
              PublicKeyToken=d633d7d5b41cbb65">
        <!-- NOTE: Change value to "v3.5" for .NET 3.5 projects -->
        <providerOption name="CompilerVersion" value="v2.0"/>
      </compiler>
    </compilers>
  </system.codedom>
</configuration>

En esta sección indicar donde se van a guardar los xml generados del proyecto (/docpath). Luego en el SHFB añadir las dll’s necesarias, la solución/projecto y los xml generados.

Ejemplo. En el caso de querer documentar los servicios de un webservice se tendría que añadir al SHFB:  App_code.xml, App_code.dll y WService.sln

Posibles problemas detectados:
-          Necesidad de cambiar variables globales DXROOT y PATH: http://www.ewoodruff.us/shfbdocs/html/378d6894-02b8-4ee9-9c50-58f278490ed8.htm. Solo ocurre cuando has instalado incorrectamente versiones incompatibles de Sandcastle y Sandcastle Help File Builder.

12 sept 2011

Solución 4 - "Auto Fix de usuario/sesión al restaurar Backup"

Esta solución la he utilizado varias veces ya que no usarla significa recrear los usuarios de la BBDD al restaurar un Backup.

Me la paso un compañero de trabajo. Si haces un Backup de una BBDD de SQL y la restauras en otra sentencia SQL Server se pierde el mapeo de usuarios de la BBDD y los inicios de sesión del SQL Server.


If you already have a login id and password for this user, fix it by doing:
EXEC sp_change_users_login 'Auto_Fix', 'user'
If you want to create a new login id and password for this user, fix it by doing:
EXEC sp_change_users_login 'Auto_Fix', 'user', 'login', 'password'


11 sept 2011

Solución 3 - Invocar función de servidor (C#) desde cliente (JavaScript)"

Hoy me he pelado durante 2 horas con este problema, pero al fin lo saque:

Hay varias soluciones, pero me centro en la que he aplicado,(sospecho que..) la más insegura.

Tenia que realizar un div pop-up de confirmación para eliminar un producto de un carrito de compra de una aplicación web .NET. El problema venía dado porqué esta función de EliminarProducto() hacía PostBack al servidor y el pop-up tenía que estar hecho en JQuery (Javascript). Ejecución en Cliente y ejecución en Servidor no son buenos compañeros.
Aún tengo que comprobar que sea compatible en todos los navegadores.

La solución se hallaba en la instrucción oculta javacript que permite los PostBacks del .NET. He tenido que parar la ejecución, realizar el pop-up confirmación Jquery, y luego proseguir (si tocaba) la ejecución donde lo había dejado, en el PostBack.

La instrucción interna de .NET en Javascript que se debía parar era :  __doPostback('idcontrolnet', ''). 
Lo que no me ha convencido ha sido el cómo he obtenido el  'idcontrolnet'. Lo he sacado haciendo splits del atributo "href" del LinkButton (también se puede hacer el atributo "pathname").


<script type="text/javascript">
        $().ready(function () {
            $('#dialogContent').dialog({
                autoOpen: false,
                modal: true,
                bgiframe: true,
                title: "MySql Membership Config Tool",
            });
        });

        function rowAction(uniqueID) {

        $('#dialogContent').dialog('option', 'buttons',
        {
            "OK": function () {
                    //uniqueID.pathname.replace("__doPostBack('", "").replace("','')", "");
                 __doPostBack((uniqueID.href).replace("javascript:__doPostBack('", "").replace("','')", ""), '');
                $(this).dialog("close"); 
                return false; 
            },
            "Cancel": function () { $(this).dialog("close"); }
        });

                    $('#dialogContent').dialog('open');

                    return false;
                }
 
    </script>

    <asp:Repeater ID = "RptItems" runat = "server" onitemdatabound="RptItems_ItemDataBound" onitemcommand="RptItems_ItemCommand">
        <ItemTemplate>
            <li>
                <asp:Literal ID = "LitID" runat = "server" Visible = "false" Text = '<%# Eval("ID") %>'></asp:Literal>
                <div class="thumb">
                    <asp:Image ID = "ImgItem" runat = "server" Width = "52" Height = "42" />
                </div>
                <div class="right_col">
                    <div class="title"><asp:Literal ID = "LitNombre" runat = "server" Text = '<%# Eval("ProductoNombre") %>'></asp:Literal></div>
                    <div class="info">Qty: <asp:Literal ID = "LitCantidad" runat = "server" Text = '<%# Eval("Cantidad") %>'></asp:Literal> | Talla: <asp:Literal ID = "LitTalla" runat = "server" Text = '<%# Eval("TallaNombre") %>'></asp:Literal></div>
                    <asp:LinkButton ID = "LnkEliminar" runat = "server" OnClientClick="return rowAction(this);" CssClass = "delete" CommandArgument = '<%# Eval("ID") %>' CommandName = "borrar" ><span class="icon">&nbsp;</span>Eliminar</asp:LinkButton>
                    <div class="price"><asp:Literal ID = "LitPrecio" runat = "server" ></asp:Literal>$</div>
                </div>
            </li>
        </ItemTemplate>
    </asp:Repeater>
Fuente: http://www.integratedwebsystems.com/2009/12/using-jquery-modal-dialog-confirmation-with-an-asp-net-server-control/

9 sept 2011

Solución 2 - "ToHtml.com - Códigos en blogs"

Herramienta  muy útil y sencilla para dar estilos de código a los textos. Convierte texto plano de un lenguaje de programación a HTML, identandolo y simulando al formato que tendríamos en un IDE. Permite escoger entre una serie de estilos generales dependiendo el color de fondo y detecta un montón de lenguajes de programación de forma automática y manual:



8 sept 2011

Solución 1 - "JQuery - función find()"

Una herramienta muy útil para añadir efectos ópticos y navegar entre tags HTML es el framework de Javascript Jquery. Tras añadir la referencia js a tu proyecto podrás utilizar esta potente herramienta que facilita el trabajo a la hora de bregar con el "duro" javascript. Una de las funciones que he descubrido recientemiente es el metodo find().

http://api.jquery.com/find/


<p>
   <span id="primero" />
   <a>
      <span id="segundo" />
   </a>
   <strong><span id="tercero" data-item="megusta" /></strong>
</p>

Esta función nos devuelve todos los tags descendientes que hemos puesto como parámetro de entrada, respetando la jerarquía de forma descendiente:

$('p').find('span') //Nos devolvería todos los elementos 'span' contenidos en el tag 'p'. En el ejemplo los dos span ("primero" y "segundo").


$('p').find('a span ') //Nos devolvería todos los elementos 'span' contenidos en el tag 'a' y a su vez en el tag 'p'. En el ejemplo en el span "segundo"-.

También se pueden añadir criterios de búsqueda, como por ejemplo:

$('p').find('span[class="megusta"]') //Nos devolvería el span "tercero".

7 sept 2011

Primera entrada

Con este blog pretendo centralizar todas las "soluciones" a los problemas que tengo en el día a día como programador .NET (en la actualidad). Las que me voy encontrando y son dignas de recordar y compartir.