martes, noviembre 30, 2010

Cómo crear administración de usuarios en ASP.Net

1) Editar el fichero web.config:



2) Crear la clase MiAppRoleProvider, que derive de RoleProvider. Hacer botón derecho sobre ésta última para "Implementar clase base" (<- Creará el esqueleto de los métodos abstractos). Insertar en los métodos recién creados el código pertinente.

Nota: Los métodos que no soporte nuestra aplicación, deberían lanzar una excepción NotSupportedException en vez de NotImplementedException.
3) Idem para MiAppMembershipProvider, que derive de MembershipProvider.

4) Modificar la clase MiAppRoleProvider:

4.1) Crear una variable miembro privada string _applicationName = "MiAplicacion";
4.2) Implementar el get/set de la propiedad ApplicationName, retornando/asignando la variable anterior.
4.3) Implementar el método GetAllRoles con return new string[] {"Administrador", "Técnico"} o algo del estilo.
4.4) Implementar el método GetRolesForUser, que tiene que devolver el rol (string) del usuario dado.
5) Modificar la clase MiAppMembershipProvider según convenga (no lo detallo).
6) Los métodos de nuestro proyecto a los que queramos restringir para el rol Administrador (p.e.) deberemos ponerles un atributo tal como este: [PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role="Administrador"). También se pueden restringir permisos por nombre de usuario además de por rol.
Nota: Se deben incluir los namespaces System.Security.Principal y System.Security.Permissions.
7) Para el UI, se utilizar el control asp:Login haciendo las adaptaciones oportunas (de diseño y/o comportamiento).

viernes, noviembre 05, 2010

Ejemplo básico de uso de LINQ

1. Nuevo proyecto WinForms
2. Añadir a formulario (name=grdPelis). Acoplar a contenedor primario.
3. Agregar al proyecto un nuevo elemento de tipo "Clases de LINQ to SQL" (name=MSDNVideo).
4. Clicar sobre "Explorador de servidores" en la superficie de diseño del nuevo elemento dbml.
5. Arrastrar la(s) tabla(s) (o vistas) que sea menester (p.e. Peliculas) desde el "explorador de servidores" a dicha superficie.
6. En el Form_Load() añadir el siguiente código:
MSDNVideoDataContext dc = new MSDNVideoDataContext();

BindingList pelis = new BindingList();

var query = (from pelicula in dc.Peliculas select pelicula).Take(10).Skip(2);

foreach (Pelicula peli in query)
{
pelis.Add(peli);
}

this.grdPeliculas.DataSource = pelis;

martes, mayo 05, 2009

Obtener los campos de un assembly de .Net mediante Reflection

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void btnObtener_Click(object sender, EventArgs e)
{
// Obtener las clases que contiene determinado assembly
Assembly a = Assembly.LoadFile(this.txtAssemblyPath.Text);
Type[] mytypes = a.GetTypes();
BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

// Para cada clase, obtener sus campos
foreach (Type t in mytypes)
{
this.txtFields.Items.Add("-------------------------------------------");
this.txtFields.Items.Add("Type: " + t.Name);
this.txtFields.Items.Add("-------------------------------------------");

FieldInfo[] fi = t.GetFields(flags);
foreach (FieldInfo m in fi)
{
this.txtFields.Items.Add(m.Name + " (" + m.FieldType.FullName + ")");
}
}
}
}
}

martes, junio 17, 2008

XPS (o el PDF de Microsoft)

Microsoft ha inventado su propio formato de documento-papel (rivalizando con pdf?) llamado XPS (XML Paper Specification).
Los documentos en este formato deben tener extensión .xps aunque internamente es un .zip que contiene el texto en .xml + imágenes y demás (similar a docx, extensión de los documentos de Word 2007).

Ya veremos si tiene éxito...

Para más info ver www.microsoft.com/xps

jueves, abril 03, 2008

Mantenimiento con "LinQ to SQL"/"Entity Data Model (EDM)"

En Visual Studio 2008 aparece LinQ, y en el Framework 3.5, EDM (Entity Data Model).

A continuación explico brevemente cómo hacer un mantenimiento básico con esto (sólo el modelado de entidades, no la capa de presentación):

1) Abrir un proyecto de Visual Studio 2008 de WinForms (p.e.).
2) Añadir un nuevo item de tipo "LinQ to SQL Classes". Se abre un "designer" para modelar la entidad.
3) Arrastrar desde el Server Explorer las tablas que formen parte de la entidad (p.e. Orders y OrderDetails). Esto crea un "DataContext".

4) Desde el interface se utiliza el "DataContext" para obtener la lista completa o cada uno de los elementos de la entidad. Por ejemplo, con "Orders":

MiDataContext dc = new MiDataContext();

//Obtener una "order" (Acceso a la BDD)
Order order1 = dc.Orders.First();

//Modificar la "order"
order1.ShipCountry = "Spain";

//Insertar nueva "order"
Order order2 = new Order();
order2.ShipCity = "Barcelona";
order2.InsertOnSubmit();

//Eliminar una "order"
dc.Orders.DeleteOnSubmit(dc.Orders.Where(/*...*/));

//Persistir cambios (en la BDD)
dc.SubmitChanges();

miércoles, abril 02, 2008

Impresión matricial en C


// A continuación se explican 2 maneras de generar una impresión matricial.
// 1) En RawDataFileToPrinter() se utiliza la estructura AddJob/ScheduleJob.
// Utilizando GetJob() se puede obtener el nombre del fichero de impresión
// por si tengo que hacer cosas con él (p.e. en entorno ASP).
// 2) En RawDataFileToPrinter2() se utiliza la estructura
// StartDocPrinter/WritePrinter, porque con 1) no se puede acceder a
// impresoras de red desde S.O. basados en W2000.
//
// NOTA: Para impresión no matricial de un WMF se utiliza PlayMetafile(hPrinter,WMF...)


//Jaac 23/07/2002
// Copiada de MSDN!!!
// RawDataToPrinter - sends binary data directly to a printer
//
// szPrinterName: NULL-terminated string specifying printer name
// lpData: Pointer to raw data bytes
// dwCount Length of lpData in bytes
//
// Returns: TRUE for success, FALSE for failure.
//
BOOL RawDataToPrinter(LPSTR szPrinterName, LPBYTE lpData, DWORD dwCount)
{
HANDLE hPrinter;
DOC_INFO_1 DocInfo;
DWORD dwJob;
DWORD dwBytesWritten;

// Need a handle to the printer.
if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) )
return FALSE;

// Fill in the structure with info about this "document."
DocInfo.pDocName = "My Document";
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = "RAW";
// Inform the spooler the document is beginning.
if( (dwJob = StartDocPrinter( hPrinter, 1, (LPSTR)&DocInfo )) == 0 )
{
ClosePrinter( hPrinter );
return FALSE;
}
// Start a page.
if( ! StartPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Send the data to the printer.
if( !WritePrinter( hPrinter, lpData, dwCount, &dwBytesWritten ) )
{
EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// End the page.
if( ! EndPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Inform the spooler that the document is ending.
if( ! EndDocPrinter( hPrinter ) )
{
ClosePrinter( hPrinter );
return FALSE;
}
// Tidy up the printer handle.
ClosePrinter( hPrinter );
// Check to see if correct number of bytes were written.
if( dwBytesWritten != dwCount )
return FALSE;
return TRUE;
}

//Jaac 23/07/2002
// Adaptación de RawDataToPrinter de MSDN
// RawDataFileToPrinter - sends binary data directly to a printer
//
// szPrinterName: NULL-terminated string specifying printer name
// szFileName: Pointer to file containing raw data bytes
//
// Returns: TRUE for success, FALSE for failure.
//
BOOL RawDataFileToPrinter(LPSTR szPrinterName, LPSTR szDataFileName, LPSTR szDocTitle)
{
HANDLE hPrinter;
HANDLE hDataFile;
DOC_INFO_1 DocInfo;
DWORD dwJob;
DWORD dwBytesWritten;
DWORD dwBytesRead;
char lpData[0x1000];

// Need a handle to the printer.
if( !OpenPrinter( szPrinterName, &hPrinter, NULL ) )
return FALSE;

// Fill in the structure with info about this "document."
DocInfo.pDocName = szDocTitle;
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = "RAW";

// Inform the spooler the document is beginning.
if( (dwJob = StartDocPrinter( hPrinter, 1, (LPSTR)&DocInfo )) == 0 )
{
ClosePrinter( hPrinter );
return FALSE;
}

/*// Start a page.
if( !StartPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}*/

// Open raw data file
if( (hDataFile = CreateFile( szDataFileName,
GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}

// Read-Write data
for(;;)
{
dwBytesRead = 0;

// Read data from file
if( !ReadFile( hDataFile, lpData, sizeof(lpData), &dwBytesRead, NULL ) )
{
//EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
CloseHandle( hDataFile );
return FALSE;
}

// Comprobar si se ha alcanzado el final del DataFile.
if(dwBytesRead == 0)
break;

// Send the data to the printer.
if( !WritePrinter( hPrinter, lpData, dwBytesRead, &dwBytesWritten ) )
{
//EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
CloseHandle( hDataFile );
return FALSE;
}
}

// Close DataFile handle
if( !CloseHandle( hDataFile ) )
{
//EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}

/*// End the page.
if( !EndPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}*/

// Inform the spooler that the document is ending.
if( !EndDocPrinter( hPrinter ) )
{
ClosePrinter( hPrinter );
return FALSE;
}

// Tidy up the printer handle.
if( !ClosePrinter( hPrinter ) )
{
return FALSE;
}

// ok
return TRUE;
}

//Jaac 23/07/2002
// Adaptación de RawDataToPrinter de MSDN
// RawDataFileToPrinter - sends binary data directly to a printer
//
// szPrinterName: NULL-terminated string specifying printer name
// szFileName: Pointer to file containing raw data bytes
//
// Returns: TRUE for success, FALSE for failure.
//
BOOL RawDataFileToPrinter2(LPSTR szPrinterName, LPSTR szDataFileName, LPSTR szDocTitle)
{
HANDLE hPrinter;
ADDJOB_INFO_1 info;
char path[1000];
DWORD Nece;
HANDLE hFileJob;
HANDLE hFileSpool;
DWORD leidos;
DWORD grabados;
PRINTER_DEFAULTS PrinterDefs;

info.Path = (LPTSTR) &path[0];

PrinterDefs.DesiredAccess = PRINTER_ALL_ACCESS; // | PRINTER_ACCESS_ADMINISTER;
PrinterDefs.pDatatype = NULL;
PrinterDefs.pDevMode = NULL;
if (!OpenPrinter(PrinterName, &hPrinter, &PrinterDefs/*NULL*/))
return FALSE;

if(AddJob(hPrinter,(DWORD)1,(LPBYTE)&path[0],(DWORD)sizeof(path),(LPDWORD)&Nece))
{
info = *((ADDJOB_INFO_1 *)&path[0]);

{//Jaac 11/07/2002: Para ASP...
DWORD dwNeeded, dwReturned;
int i;
JOB_INFO_2 *pJobInfo;
//char sAutor[] = "Jaac";
char sMascara[_MAX_FNAME];
char sMascaraExt[_MAX_EXT];
char sPageCount[5];
//char sCopies[2];

GetJob(hPrinter, info.JobId, 2, NULL, 0, &dwNeeded);
pJobInfo = malloc( dwNeeded );
GetJob(hPrinter, info.JobId, 2, pJobInfo, dwNeeded, &dwReturned);

if (strlen(g_sTitleByProgram) > 0)
{
pJobInfo->pDocument=malloc(strlen(g_sTitleByProgram)+1);
strcpy(pJobInfo->pDocument, g_sTitleByProgram);
}
else
{
pJobInfo->pDocument = malloc(strlen(FormHdr.name)+1);
strcpy(pJobInfo->pDocument, FormHdr.name);
}

_splitpath( FrFileName, NULL, NULL, sMascara, sMascaraExt );
strcat(sMascara, sMascaraExt);
sprintf(sPageCount, "%d", PageCount);
//sprintf(sCopies, "%d", (OpcionInforme.NroCopias>1) ? OpcionInforme.NroCopias : 1);

pJobInfo->pDocument = realloc(pJobInfo->pDocument,
strlen(FormHdr.name)+1+
strlen(info.Path)+1+
strlen(sMascara)+1+
strlen(sPageCount)+1);
//strlen(sCopies)+1);

strcat(pJobInfo->pDocument, "|");
strcat(pJobInfo->pDocument, info.Path);
strcat(pJobInfo->pDocument, "|");
strcat(pJobInfo->pDocument, sMascara);
strcat(pJobInfo->pDocument, "|");
strcat(pJobInfo->pDocument, sPageCount);
//strcat(pJobInfo->pDocument, "|");
//strcat(pJobInfo->pDocument, sCopies);

//pJobInfo->pNotifyName = &sAutor[0];
SetJob(hPrinter, info.JobId, 2, pJobInfo, (DWORD)(0));

free(pJobInfo);
}

hFileSpool = CreateFile(info.Path,
GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
if(hFileSpool != INVALID_HANDLE_VALUE)
{

hFileJob = CreateFile(FileJob,
GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if(hFileJob != INVALID_HANDLE_VALUE)
{
// bucle leer grabar
for(;;)
{
leidos = grabados = 0;

ReadFile(hFileJob,buffer,sizeof(buffer),&leidos,NULL);
if(leidos == 0) break;
WriteFile(hFileSpool,buffer,leidos,&grabados,NULL);
}

CloseHandle(hFileJob);
}
CloseHandle(hFileSpool);
}
ScheduleJob(hPrinter,info.JobId);
}
else
{
// el AddJob ha fallado ( debe ser un NT compartiendo impresora)
PRINTER_INFO_2 APrinter[100];
DWORD Needed;
DWORD copiados;

char remoto[512];
remoto[0] = '\0';
if(!EnumPrinters(
PRINTER_ENUM_CONNECTIONS,
PrinterName, // name of printer object
2, // specifies type of printer info structure
(LPBYTE)&APrinter, // pointer to buffer to receive printer info structures
sizeof(APrinter), // size, in bytes, of array
&Needed, // pointer to variable with no. of bytes copied (or required)
&copiados // pointer to variable with no. of printer info. structures copied
))
{
return FALSE;
}
else
{
strcpy(remoto,APrinter[0].pServerName);
strcat(remoto,"\\");
strcat(remoto,APrinter[0].pShareName);
}
hFileSpool = CreateFile(remoto,
GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
if(hFileSpool != INVALID_HANDLE_VALUE)
{
hFileJob = CreateFile(FileJob,
GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);

if(hFileJob != INVALID_HANDLE_VALUE)
{
// bucle leer grabar
for(;;)
{
leidos = grabados = 0;

ReadFile(hFileJob,buffer,sizeof(buffer),&leidos,NULL);
if(leidos == 0) break;
WriteFile(hFileSpool,buffer,leidos,&grabados,NULL);
}

CloseHandle(hFileJob);
}
CloseHandle(hFileSpool);
}
}
ClosePrinter(hPrinter);
}

martes, febrero 05, 2008

Mantenimientos Master-Details con Datasets


Supuestos:





  • BDD: Northwind.

  • Tabla master: Orders. PK: OrderID, identidad autoincremental.

  • Tabla details: Orders. PK: OrderID, ProductID. FK: OrderID (relación con Orders.OrderID, enforced for INSERTs and UPDATEs pero sin Cascade Update ni Cascade Delete).


  • Proyecto WinForms en VS2005 (.Net Framework 2.0)

  • Creación de dataset (DatasetNorthwind) creado por diseño que incluye las tablas Orders, OrderDetails y tal vez otras, y sus relaciones.

  • Pantalla de 2 grids editables (nuevo, editar, borrar), donde el primero tiene un BindingSource = DatasetNorthwind.Orders, y el segundo el FK_xxx del anterior (seleccionable por diseño).








Si se ha hecho correctamente, al navegar por el primer grid se irá actualizando el segundo.





A tener en cuenta:





Si modificamos directamente en los grids (editando, añadiendo y borrando, tanto pedidos enteros como líneas), el dataset asociado (DatasetNorthwind) irá guardando las modificaciones.





En el momento de persistir dichas modificaciones a la base de datos (xxxTableAdapter.Update), se deben tener en cuenta las relaciones:






  1. El eliminar un pedido del grid, no elimina automáticamente sus líneas, y si quedan líneas "huérfanas" en el dataset, al hacer el Update se producirá un error.

  2. Al añadir un pedido, sus líneas toman el OrderID de la cabecera, pero este valor no es definitivo hasta que se hace el Update, pero este valor definitivo no se propaga por defecto a las líneas. (Algo equivalente ocurriría si se pudiera modificar el OrderID en las cabeceras, pero este caso no lo trataré).




Carga de pantalla (Form_Load)





this.ordersTableAdapter.Fill(this.dataSetNorthwind.Orders);
this.order_DetailsTableAdapter.Fill(this.dataSetNorthwind.Order_Details);





Implementar altas/bajas/editar (1er método)



Para solucionar el punto 1 a tener en cuenta, implementaremos el evento Orders_OrdersRowDeleting():

void Orders_OrdersRowDeleting(object sender, DataSetNorthwind.OrdersRowChangeEvent e) {
if (MessageBox.Show(
"Se eliminará el pedido " + e.Row.OrderID.ToString() + ".",
"Eliminar pedido",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Information)
== DialogResult.OK)
{
try {
DataSetNorthwind.Order_DetailsRow[] orderDetails = e.Row.GetOrder_DetailsRows();
foreach (DataSetNorthwind.Order_DetailsRow orderDetail in orderDetails)
{
orderDetail.Delete();
}
}
catch (Exception ex)
{
throw new Exception("No se han podido eliminar los detalles del pedido " + e.Row.OrderID.ToString() + ".", ex);
}
}


El manejador de este evento se debe insertar a mano en el Form_Load, tras el InitializeComponent( ):

this.dataSetNorthwind.Orders.OrdersRowDeleting += new DataSetNorthwind.OrdersRowChangeEventHandler(Orders_OrdersRowDeleting);

En el momento de salvar los cambios, se debe tener en cuenta el punto 2 (y el 1):


private void SaveChanges()
{
try
{
//Nuevos pedidos (cabeceras nuevas)? --> En los detalles hay que asignar el OrderID en el momento en que el pedido se da de alta
if (this.dataSetNorthwind.Orders.GetChanges(DataRowState.Added) != null)
{
foreach (DataSetNorthwind.OrdersRow order in this.dataSetNorthwind.Orders)
{
if (order.RowState == DataRowState.Added)
{
DataSetNorthwind.Order_DetailsRow[] orderDetails = order.GetOrder_DetailsRows();
this.ordersTableAdapter.Update(order);
foreach (DataSetNorthwind.Order_DetailsRow orderDetail in orderDetails)
{
orderDetail.OrderID = order.OrderID;
this.order_DetailsTableAdapter.Update(orderDetail);
}
}
}
}
//Resto: Hay que actualizar primero los detalles por si se han eliminado pedidos
//Para que el eliminar funcione correctamente, previamente se ha implementado el evento Orders_OrdersRowDeleting
this.order_DetailsTableAdapter.Update(this.dataSetNorthwind.Order_Details);
this.ordersTableAdapter.Update(this.dataSetNorthwind.Orders);
}
catch (Exception ex)
{
throw new Exception("Error intentando guardar los cambios", ex);
}
}


Implementar altas/bajas/editar (2º método)

En el DatasetNorthwind, editar la relación FK_xxx y forzar Delete Rule = Cascade y Update Rule = Cascade. En el salvar poner:

this.ordersTableAdapter.Update(this.dataSetNorthwind.Orders);
this.order_DetailsTableAdapter.Update(this.dataSetNorthwind.Order_Details);









Implementar ficha con DataBinding





Pasos:

  1. En el diseño de la pantalla, añadir el DatasetNorthwind.
  2. En cada TextBox indicar, en la propiedad (DataBindings)/Text el campo que toque del BindingSource.
  3. Implementar el FillByOrderID, desde el diseño del DatasetNorthwind mostrar el menú contextual sobre la tabla Orders, seleccionar AddQuery y crear el select... where OrderID = @OrderID.
  4. En el Form_Load:
    this.ordersTableAdapter.FillByOrderID(this.dataSetNorthwind.Orders, orderID);
  5. En el evento Guardar hacer:

    /*Para los controles que tengan Data Source Update Mode = Never (DataBindings/Advanced)
    foreach (System.Windows.Forms.Control control in this.Controls)
    {

    if (control.DataBindings["Text"] != null)
    control.DataBindings["Text"].WriteValue();

    }*/
    this.ordersBindingSource.EndEdit(); //Es necesario para que el RowState pase de Unchanged a Modified.
    this.ordersTableAdapter.Update(this.dataSetNorthwind.Orders);
    this.DialogResult = DialogResult.OK;
  6. Y en el Cancelar (o salir sin guardar):
    this.ordersBindingSource.CancelEdit();

jueves, diciembre 13, 2007

Mis Favoritos (bookmarks) de Logic:

Bar Codes
Aecoc - Guía de calidad en simbología - Puntos críticos
Barcode Types (Bokai Barcode)
Manual_Técnico_para_Aplicar_el_Estándar_EANUCC_128.pdf
UCC - EAN-128
Inmersión Office 12 y Share Point v3
Downloads
Erika Ehrli Blog
Office 12 at PDC
Walqa-Feb'06
Windows Vista Developer Center Windows Workflow Foundation
[PDC] Office 12, SharePoint v3 slides
Microsoft
Jose Murillo's Blog
MSDN Events and Webcasts
Portal Server
Actas de reuniones de seguimiento de tareas
Documentos y listas
Página Principal - Área Desarrollo
Página Principal
Seguimiento I+D (Viejo)
Seguimiento I+D
Seguimiento PDA
Programación
Mobile
desarrollo Mobile - Home
Errores de SQL CE
QuickStarts Source Control Viewer
_.Net
.Net - Windows Forms FAQ
CodeGuru Event Handling in .NET Using C#
Creating System Tray Applications in Windows Forms
India .Net Forum
Lutz Roeder's Programming.NET C# VB CLR WinFX
Microsoft Windows Forms QuickStarts Tutorial
MSDN - Web Services
MSDN2 Library
Programar.NET Sitios de Interes
The Code Project - C# Script (missing puzzle piece) - C# Programming
All About Scripting
CodeGuru Forums - Visual C++ Programming
DCE 2005 - Mis Cursos
Desarrolla con MSDN
Elección de la arquitectura de capa de presentación correcta (Microsoft Architect Journal)
iTextSharp (Generar PDF's)
Microsoft patterns & practices Center Getting Started
MSDN Home Page
MSDN Magazine Source Code - 2005
Patrones y Antipatrones una Introducción
Programando...
Página principal de MSDN Online en Español
Search Web Services!
Ten Essential Tools Visual Studio Add-Ins Every Developer Should Download Now -- MSDN Magazine, December 2005
UDDI Explorer (WebserviceX.NET)
Web Service Definition Language (WSDL) - Ejemplo petición stock
Welcome to XMLSoftware
Vínculos
Hotmail gratuito
Personalizar vínculos
Windows Media
Windows
12 Tips for Creating Better Presentations
AltaVista - Babel Fish Traducción
MSN.com

martes, diciembre 04, 2007

El análisis PERT (Program Evaluation and Review Technique) es una técnica basada en redes para la gestión de proyectos que contempla las relaciones de precedencia e interdependencia de las actividades que lo conforman.

Para cada actividad en PERT se debe determinar un Tiempo Optimista (ta), un Tiempo Probable (tm) y un Tiempo Pesimista (tb). Asumiendo que estos tiempos siguen la distribución de probabilidad "beta" podemos obtener el Tiempo Esperado (te) y su Varianza (sigma) como:







Links:

lunes, diciembre 03, 2007

Links sobre Análisis DAFO:
Temas interesantes de Software Libre:

Referencias sacadas del link anterior:

Links buscando info sobre temas de Expo:QA 2007:

De Michael Bolton:

Sobre mi estancia en la Expo:QA 2007:

jueves, noviembre 15, 2007

Cómo vincular datos de SharePoint a Excel

  1. En el menú de Excel, seleccionar Datos / Obtener datos externos / Nueva consulta de base de datos...
  2. MS Access Database*
  3. Seleccionar el archivo K:\I+D_Documentacion\EMP\Estadis\EPMEstadis.mdb (o lo que toque).
  4. Seleccionar la tabla que toque.
  5. ...

Pero esto presupone que ya existe una mdb que contiene vínculos al SharePoint. Para crear estos vínculos, en Access hacer:

  1. Menú Archivo / Obtener datos externos / Vincular tablas
  2. En Tipo de archivos seleccionar Windows SharePoint Services()
  3. Seleccionar el sitio que toque (http://srvproject/sites/projectserver_362)
  4. Seleccionar la(s) tabla(s) que toque
  5. ...

Cómo importar datos de SharePoint a Excel

  1. En el menú de Excel seleccionar Datos / Obtener datos externos / Importar datos...
  2. +Conectar con nuevo origen de datos.odc
  3. Servicios de obtención de datos
  4. Listas de Windows SharePoint Services
  5. http://srvproject/sites/projectserver_362 (o lo que toque)
  6. Seguimiento ImasD

Nota: esto crea una lista no enlazada (no se puede actualizar).

miércoles, noviembre 14, 2007

Cómo obtener las clases (y sus métodos y propiedades) de un assembly de .net utilizando Reflection

// Obtener las clases que contiene determinado assembly

Assembly a = Assembly.LoadFile(/* Assembly (path completo)*/);

Type[] mytypes = a.GetTypes();

BindingFlags flags = ( BindingFlags.NonPublic
BindingFlags.Public BindingFlags.Static
BindingFlags.Instance BindingFlags.DeclaredOnly);

// Para cada clase, obtener sus campos

foreach (Type t in mytypes)

{

this.txtFields.Items.Add("Type: " + t.Name);

FieldInfo[] fi = t.GetFields(flags);

foreach (FieldInfo m in fi)

{

this.txtFields.Items.Add(m.Name + " (" + m.FieldType.FullName + ")");

}

}

martes, abril 13, 2004

Error: "System.Security.SecurityException: Request for the permission of type System.Security.Permissions.FileIOPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed."

Código:

XmlTextReader xmlReader = new XmlTextReader(@"c:\mifile.jac");
xmlReader.Read;

Explicación:

El proyecto se está ejecutando desde una unidad de red (K:). Si se copia al disco duro local ya no se produce el error.