[C++][?] Error en ReadConsole()

Iniciado por Horricreu, 18 Junio 2010, 22:36 PM

0 Miembros y 1 Visitante están viendo este tema.

Horricreu

Bueno, tengo este código que compila perfectamente y no crashea, pero siempre me termina al MessageBox() de error:

Código (cpp) [Seleccionar]
#include <windows.h>

int main()
{
        HANDLE hHeap = GetProcessHeap();

        LPSTR lpBuffer = "Escribe la ruta del fichero: ";
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, lstrlen(lpBuffer), 0, 0);

        LPSTR lpFileName = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
       DWORD nNumberOfCharsRead = 0;
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), lpFileName, &nNumberOfCharsRead, 0, 0);

HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);

if(hFile == INVALID_HANDLE_VALUE) MessageBox(0, "Error", "Error", 0);

else MessageBox(0, "Funciona", "Funciona", 0);

return 0;
}


El caso es que al escribir la ruta del fichero, me dice error aunque exista. ¿Alguna solución? Seguramente se tiene que recurrir al debuggeo pero aun no sé.

Muchas gracias y saludos :P

Littlehorse

Si tenes la base de la ruta en lpBuffer, cuando leas el nombre del archivo, debes concatenar esos datos en un solo buffer a la hora de llamar a CreateFile, de lo contrario no tiene mucho sentido tener una base de ruta en un buffer y el nombre del archivo en otro.

También cabe remarcar que lstrlen(lpFilename) va a devolver 0, y ademas uno de los parámetros de ReadConsole es incorrecto, debería ser un LPDWORD (DWORD &charsread por ejemplo) de lo contrario te debería dar un error. No recuerdo si dicho parámetro es opcional o no, revisalo en la MSDN pero creo que no lo es.

Seguramente CreateFile te devuelve ERROR_PATH_NOT_FOUND por lo antes mencionado, así que procura llamar a GetLastError para encontrar el problema.

Algo así:

Código (cpp) [Seleccionar]

HANDLE hFile = CreateFile(lpFileName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
   if(hFile==INVALID_HANDLE_VALUE)
     printf("CreateFile error: %d\n",GetLastError());


Y luego buscas en la MSDN los códigos de error.

Saludos!
An expert is a man who has made all the mistakes which can be made, in a very narrow field.

Horricreu

#2
Ok, vamos por partes:


  • lpBuffer es sólo para que se muestre esta cadena de texto en la consola. lpFileName es la ruta del fichero que vamos a esciribir, ¿entiendes?
  • No entiendo lo de lstrlen(). ¿No está bien? Por cierto, es verdad, el parámetro 4 de ReadConsole() NO es opcional, me lo deje. Muchas gracias ;)
  • Exacto, CreateFile() me devuelve error 3, por lo tanto como dijiste me devuelve ERROR_PATH_NOT_FOUND.

No puede ser que CreateFile() me devuelva ERROR_PATH_NOT_FOUND porque escribo la ruta tal y como está :-\

Littlehorse, muchas gracias por tu ayuda. Saludos :P

Eternal Idol

Si reservas memoria para la cadena haciendo que esta este inicializada a 0 (HEAP_ZERO_MEMORY) entonces lstrlen obviamente devolvera como resultado 0, esa funcion devuelve el numero de caracteres y estas cadenas estan terminadas por 0, es dcir no hay ningun caracter, en lugar de lstren deberias usar MAX_PATH - 1 por ejemplo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Horricreu

#4
Si hago esto que me dices:

Código (cpp) [Seleccionar]
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), lpFileName, MAX_PATH - 1, &lpNumberOfCharsRead, 0);

No me funciona :-\ Es esto lo que me dices que haga, ¿no?

Saludos :P

EDITO: muestro el código con las correcciones que me habéis dado (sigue sin funcionar :-\):

Código (cpp) [Seleccionar]
#include <windows.h>

int main()
{
LPSTR lpBuffer = "Escribe la ruta del fichero: ";
DWORD nNumberOfCharsRead = 0;

LPSTR lpFileName = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);

WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, lstrlen(lpBuffer), 0, 0);

ReadConsole(GetStdHandle(STD_INPUT_HANDLE), lpFileName, MAX_PATH - 1, &nNumberOfCharsRead, 0);

HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);

if(hFile == INVALID_HANDLE_VALUE) MessageBox(0, "Error", "Error", 0);

else MessageBox(0, "Funciona", "Funciona", 0);

return 0;
}

Eternal Idol

La lectura es correcta, si lo depuras lo vas a ver, el tema es que eso incluye el salto de linea (\r\n) y para el nombre del archivo no es correcto. Ahora lo que tenes que hacer es terminar la cadena antes (hacelo con cuidado y teniendo en cuenta que el usuario puede escribir cualquier cosa).
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Horricreu

#6
Cita de: Eternal Idol en 19 Junio 2010, 17:04 PM
La lectura es correcta, si lo depuras lo vas a ver, el tema es que eso incluye el salto de linea (\r\n) y para el nombre del archivo no es correcto. Ahora lo que tenes que hacer es terminar la cadena antes (hacelo con cuidado y teniendo en cuenta que el usuario puede escribir cualquier cosa).

Ok, ya tengo codificada esta parte según lo que me dijiste de \r\n, pero aun así el programa tampoco va:

Código (cpp) [Seleccionar]
if (lpNumberOfCharsRead > 2)
{
LPSTR lpRealFile = (LPSTR)lpFileName + lpNumberOfCharsRead - 2;
*lpRealFile = 0;
}


Pero, como sabes que incluye \r\n. ¿En la MSDN sale? Te agradecería si me pasaras el enlace donde encontraste esta información :)

Saludos :P

Eternal Idol

Estaras poniendo mal el path  :rolleyes: Depuralo, si lo hubieras hecho ya sabrias que el \r\n estaba en la cadena, no hace falta nada mas.
Igualmente el modo de lectura por defecto implica que ReadConsole no devuelva hasta que el usuario aprete ENTER:

"High-Level Console Modes
The behavior of the high-level console functions is affected by the console input and output modes. All of the following console input modes are enabled for a console's input buffer when a console is created:



Line input mode
Processed input mode
Echo input mode

...
ENABLE_LINE_INPUT Used with a console input handle to cause the ReadFile and ReadConsole functions to return when the ENTER key is pressed. If line input mode is disabled, the functions return when one or more characters are available in the input buffer."
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Horricreu

Es verdad, acabo de depurar y lo dice. Ahora no sé porque aun no va. Escribo la ruta del fichero bien :-\

Saludos :P

Littlehorse

Lo que haces dentro del if no es lo mas adecuado ya que implica utilizar un puntero extra.

Basta con usar la notación de arreglos luego de tu if:

lpFileName[lstrlen(lpFileName)-2]=0;


Por otro lado ten en cuenta que \r\n no son los únicos caracteres inválidos para una ruta, por lo tanto el buffer que la contiene requiere una validación antes de ser procesada.

Un consejo, cuando tengas un error que no puedes encontrar, revisa los parámetros de las funciones que no hacen lo que deben porque en este caso esos han sido el problema principal desde el principio.

En cuanto al código, a mi me funciona y CreateFile me devuelve el handle correcto. En todo caso estarás poniendo mal la ruta.

Saludos
An expert is a man who has made all the mistakes which can be made, in a very narrow field.