Buscar

Javier Caceres – jacace

Javier's blog about C#, Software Architecture and Design

Categoría

Preguntas

The system cannot find the file specified using System.Diagnostics.Process.Start #askjacace

Hello dear readers,

Recently one of my colleagues asked me the following question:

When the following line is executed from a Web Application in Visual Studio works alright:

System.Diagnostics.Process.Start(@”[MappedNetworkDrive]:\[Folder]\[FileWithoutExtension]”);

However, when it is invoked in the production server it fails with the following message:

[Win32Exception (0x80004005): The system cannot find the file specified]
   System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo) +614
   System.Diagnostics.Process.Start() +56
   System.Diagnostics.Process.Start(ProcessStartInfo startInfo) +49
   System.Diagnostics.Process.Start(String fileName) +31
   Recomat.Tablero.Button1_Click(Object sender, EventArgs e) +10
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +111
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +110
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565

After looking at the code I made my mind and concluded that web applications should not invoke any kind of executable (including: .exe, .bat, ) in that manner. Having that said and IF this application is a simple Proof Of Concept or a throw away work at college then the possible reasons of failure are described below:

(1) The full path is not specified: in this case the problem will be solved by simply adding the file extension (as it occurred to someone else here).

(2) The user account IUSR can’t access the file: in this case simply add read permission to this user account.

Thanks again.

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP

Intel Black Belt Software Developer

Aprendiendo C# – Video (3)

Hola estimados lectores del blog,

Hoy he publicado la tercera entrega de esta serie, la cual está compuesta de 3 cortos videos que cubren los siguientes temas: firmas de métodos (parámetros por referencia y keyword static), manejo de excepciones (try/catch/finally y excepciones específicas) y estructuras de datos (arreglos, listas, diccionarios y hash).
He creado en YouTube un watch list con los 3 videos y sus sub partes para que los puedan verlos fácilmente:

El código resultante del ejemplo del cajero automático (usando listas y basado en un archivo) y la diapositiva utilizada/slides están en my onedrive:

Slides y codigo de ejemplo

Espero que sea de su agrado. No olviden dejar aquí sus comentarios/preguntas.

Saludos,

Javier

Aprendiendo C# – Video (2)

Hola a todos,

En este segundo video vamos a revisar conceptos importantes del .NET Framework y vamos a empezar a trabajar en aplicaciones WinForms. Debido a la limitación en tamaño en YouTube debí dividir el video en 3 partes descritas a continuación.

Parte 1: Conceptos Fundamentales del .NET Framework:

Parte 2: Introducción a aplicaciones WinForms:

Parte 3: Como pasar datos entre ventanas y configurar propiedades de las mismas.

Los slides y el código utilizado se encuentran aqui (en onedrive).

Saludos,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP

Intel Black Belt Software Developer

Aprendiendo C# – Video (1)

Hola a todos,

Hoy he iniciado una de las tareas que he querido hacer por mucho tiempo: videos / tutoriales de C#/.NET desde cero hasta nivel medio. Una de las razones detrás de esta decisión es observar que la introducción a este “universo” es a veces uno de los pasos mas difíciles para quienes desean o necesitan aprender. El primer video esta compuesto por 5 partes (esto debido al limite de 15 mins impuesto en Youtube). Cada parte se “embebe” a continuación con su respectivo comentario.

Parte 1: este video habla de conceptos básicos de POO y presenta una introducción a Visual Studio.

Parte 2: este video contiene Tipos y Variables en C#

Parte 3: este video muestra ejemplos de herencia y polimorfismo

Parte 4: este video habla de conceptos de .NET e interfaces:

Parte 5: este video muestra como modelar un cajero automatico (ATM) en C#:

Los slides y el código utilizado se encuentran aqui (en onedrive).

Saludos,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP

Intel Black Belt Software Developer

Entendiendo los tipos de cadenas de la Win32

Para quienes inician en el desarrollo en C++/Win32 o quienes desarrollan en C#/PInvoke pronto  descubriran que Windows tiene varias definiciones para el tipo de dato char (C++) o string (C#). Las multiples definiones obedecen (desde mi punto de visto) al buen proposito de mantener el codigo generico en cuanto al soporte o no de caracteres Unicode.

Es tan comun la confusion de estos tipos de datos que una macro facil de consumir como por ejemplo MCIWndSave causa comentarios en los foros como “MCIWndSave is not saving ok the filename” debido a que se utiliza incorrectamente como lo muestra el siguiente codigo:

char file[96]="";
strcpy(file,"aud.wav");
MCIWndSave(m_hMCIWnd, file);

Existen otros malos ejemplos con llamados ANSI. Para ayudar a eliminar las dudas entre las definiciones de las cadenas en Windows decidi elaborar la siguiente tabla para resumirlos:

ANSI UNICODE
TCHAR char WCHAR, wchar_t
PTSTR/LPTSTR PSTR: char* PWSTR: WCHAR*
LPSTR: char* LPWSTR: WCHAR*
PTCHAR: TCHAR* PCHAR: char* PWCHAR: WCHAR*
PCTSTR/LPCTSTR PCSTR: const char* PCWSTR: WCHAR*
LPCSTR: const char* LPCWSTR: const WCHAR*

De los anteriores tipos tal vez solo identifiques al char. Pues bien la clasificacion divide en el grupo que soporta caracteres Unicode (2 bytes) y en el grupo que solo soporta caracteres ANSI (1 byte). El char es de tipo ANSI, por lo cual podras representar todos los caracteres del idioma ingles con facilidad pero no para representar otra escritura como el texto Cyrilic. Asi mismo la version Unicode del char es el WCHAR.

Basado en el char (ANSI) y el WCHAR (Unicode) encontramos los punteros/apuntadores/pointers a ellos, los cuales pueden ser variables o constantes. En el caso de los char* se definen como PSTR (Pointer to STRing) o LPTSTR (Long Pointer to STRing). Auque se definan Long Pointer la verdadera diferencia la crea el desarrollador porque la definicion segun la macro  es la misma. Los const char* pueden ser PCSTR (Pointer to Constant String) o LPCSTR (Long Pointer To Constant String).

Los WCHAR* y const WCHAR* siguen la misma filosofia de los char* y const char*, es decir existe dos definiones para los varibales (PWSTR y LPWSTR) y dos para los constantes (PCWSTR y LPCWSTR). Adicionalmente existe el TCHAR que dependiendo si existe o no el #define Unicode se convierte en char o WCHAR. Un par de ejemplos de cadenas ANSI y Unicode:

char* unaCadena="una cadena";
WCHAR* unaCadena=L"una cadena";
TCHAR* unaCadena= _T("una cadena");

Del mismo modo existen versiones de todas las funciones para cada definicion, por ejemplo:

strlen(unaCadena);
wcslen(unaCadena);
_tcslen(unaCadena);

Si quieres aprender mas puedes visitar la documentacion en MSDN o este articulo en CodeProject.

Cheers,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP
Intel Black Belt Software Developer

Proyecto Web C# para Principiantes en CodePlex

Hola a tod@s,

Debido a la gran aceptación del proyecto didáctico CRM y a los comentarios positivos recibidos en el post original (28 de Noviembre de 2011) he decidido subir el código fuente a http://crmprj.codeplex.com/ en CodePlex para facilitar la participación y sincronización del trabajo en el. A partir de este momento los interesados pueden participar en este desarrollo.

Este proyecto es un ejemplo básico de una aplicación Web en C# y sus propósitos son educativos para que principiantes, aprendices y en general, quienes inician en el desarrollo en C# tengan un punto de partida en sus trabajos académicos o profesionales. Este proyecto es liberado “AS IS”.

Saludos,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional -MVP-
Intel Back Belt Software Developer

Login Failed for user: “sa” – C#

Un lector del blog me pregunta el porqué se le presenta una excepción llamada “Login Failed for user: userName” en una aplicación desarrollada con C#. Las propiedades de la conexión en SQL Management Studio y la excepción se muestran en las siguientes imágenes:

Así mismo el lector comenta que ha probado con Integrated Security=True y con el User ID con el cual ha iniciado sesión en Windows pero aún no logra conexión, como se muestra en la siguiente imágen:

Después de revisar las imágenes encontré que en la cadena de conexión no se está utilizando el User ID de la cadena de conexión con el formato: nombreMaquina\nombreUsuario (teniendo en cuenta que la máquina no hace parte de un dominio, en caso que si hiciera parte de un dominio el formato del User ID debería ser: nombreDominio\nombreMaquina). La forma de evitar la excepción es simplemente utilizando el User ID en el formato correcto (nombreMaquina\nombreUsuario).

Aprovecho ésta ocasión para recomendar el repositorio de cadenas de conexión más grande y tradicional en la web, el legendario: http://www.connectionstrings.com/. La importancia de éste sitio es tan grande que me atrevería a decir que la cadena de conexión que no se encuentre allí no existe.

Saludos,

Javier Andrés Cáceres Alvis

Intel Black Belt Software Developer

Microsoft Most Valuable Professional

En Que Casos se Debe Usar un SqlCommand o SqlDataAdapter en C#

[Update 11-Aug-2012:  Si quiere saber mas sobre la arquitectura en la que esta basado el DataSet/DbDataAdapter puede ver el siguiente post: Are Typed DataSets dead? Si quiere saber mas sobre optimizar el llenado de los DataSet sin DbDataAdapter puede visitar el siguiente post: Filling a DataSet with the Data Application Block]

Hola a todos,

Un lector del blog me hace la siguiente pregunta:

en que casos se debe usar un SqlCommand o un SqlDataAdapter;  Solo con el SqlDataAdapter pude hacer una consulta general

Un SqlCommand se utiliza cuando necesitas ejecutar un tipo de sentencia Sql a la base de datos (los tipos pueden ser: Delete, Update, Insert o Select). Por su parte el SqlDataAdapter se utiliza si requieres ejecutar más de un tipo de sentencia Sql o si trabajarás en escenarios desconectados.

Ejemplo de SqlCommand:

        public List Listar()
        {
            SqlConnection con = new SqlConnection(cadenaConexion);
            SqlCommand com = new SqlCommand("LISTAR_CAMPANAS", con);
            com.CommandType = System.Data.CommandType.StoredProcedure;

            con.Open();

            SqlDataReader drCampanas = com.ExecuteReader();
            List listaCampanas = new List();

            while (drCampanas.Read())
            {
                listaCampanas.Add(Cargar(drCampanas));
            }

            drCampanas.Close();
            con.Close();
            return listaCampanas;
        }

Ejemplo de SqlDataAdapter (basado en el ejemplo anterior pero levemente modificado):

 public List Listar()
 {
 SqlConnection con = new SqlConnection(cadenaConexion);
 SqlCommand com = new SqlCommand("LISTAR_CAMPANAS", con);
 com.CommandType = System.Data.CommandType.StoredProcedure;
 SqlDataAdapter da = new SqlDataAdapter(com);
 con.Open();

 SqlDataReader drCampanas = da.SelectCommand.ExecuteReader();
 List listaCampanas = new List();

 while (drCampanas.Read())
 {
 listaCampanas.Add(Cargar(drCampanas));
 }

 drCampanas.Close();
 con.Close();
 return listaCampanas;
 }

En el ejemplo anterior se muestra como un SqlDataAdapter puede contener a un SqlCommand (llamado “com” en el ejemplo) que representa una sentencia Select; de igual forma, se puede agregar comandos que representen las sentencias Insert, Update y Delete utilizando sus respectivas propiedades:

            SqlCommand dummyCommand = new SqlCommand();
            da.UpdateCommand = dummyCommand;
            da.DeleteCommand = dummyCommand;
            da.InsertCommand = dummyCommand;

Si no necesitas trabajar en escenarios desconectados y si solo necesitas utilizar un comando a la vez, utiliza un SqlCommand, de lo contrario un SqlDataAdapter.

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP
Intel Black Belt Software Developer

No se controló InvalidOperationException – C#

Hola a todos,

Un lector del blog me pregunta sobre una excepción en C# y la comparto para que sea útil a otras personas:

Pregunta: “Un pequeño programa por consola, que permite crear, consultar y borrar. Uso el List<> para almacenar y listar, todo va bien pero al borrar me esta generando esta excepción: He verificado pero no se que pasa?”

Respuesta: no se pueden eliminar colecciones mientras se recorren, según la documentación de MSDN el foreach puede tener resultados inesperados cuando se modifican los elementos: http://msdn.microsoft.com/es-es/library/ttw7t8t6(v=vs.80).aspx

La solución para lo anterior es no utilizar un foreach para modificar, utilizar algo como un for.

Saludos,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP
Intel Black Belt Software Developer

Crea un blog o un sitio web gratuitos con WordPress.com.

Subir ↑