Como escribir información dentro del exe?

Tus preguntas. Algoritmos o Grupos de Comandos formando Programas Escripts.
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Como escribir información dentro del exe?

Mensaje por Chefito »

Jejejeje....pues eso. Estos días se ha discutido la mejor forma de poder introducir información dentro del propio exe que genera el compilador de AutoIt para poder trabajar más tarde con ésta. El post inicial lo podeis encontrar aquí: http://www.emesn.com/autoitforum/viewto ... f=1&t=2247

Hay que recordar que si un archivo exe está abierto el win no te deja modificar nada de éste. Por esta causa se suele recurrir a soluciones externas como comandos de consola, archivos suplementarios batch, vbs, etc, para utilizarlos cuando se cierre.

A ver las formas que se os ocurren. Las ideas valen, pero me gustaría mucho que las acompañarais de código .

A mi se me han ocurrido muchas, pero trabajaré con una que tengo en mente que está muy bien (no necesitaría crear ningún archivo externo. Solamente trabajaría con objetos ). No se si funcionará porque nunca la he utilizado . Probaremos a ver que pasa.

Espero códigos para que nos den ideas a todos!!!!

Os dejo un código base para el que quiera empezar a hacer pruebas.

Código: Seleccionar todo

#include <GUIConstantsEx.au3>

#OnAutoItStartRegister "Inicio"
OnAutoItExitRegister("Final")

Local $edit, $msg

GUICreate("Mi GUI")  

$edit = GUICtrlCreateEdit("Este es mi texto inicial", 10, 32, 300, 50)
GUISetState()

While 1
	$msg = GUIGetMsg()	
	If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
GUIDelete()
Func Inicio()
	
EndFunc

Func Final()
	
EndFunc
He puesto un edit para guardar en el exe la información que escribais en éste. Recordad que luego la teneis que recuperar. Es un ejemplo. Podeis poner cualquier control.
También he puesto una función de inicio y otra de final. La de inicio es para meter el código que recupere la información contenida en el exe y la carga en el lugar correspondiente al ejecutar el programa. En mi ejemplo sería en el control Edit.
La de final no hace falta obligatoriamente, pero pienso que es mejor ejecutar el código que guarde la información en el exe cuando se vaya a salir del programa, ya que si está abierto no va a ser posible. Con esto conseguimos que el código que haga esto se ejecute minimamente, ya que de otra forma tendría que estar comprobando continuamente cuando se cerraría el programa.

Recordad que esto solo funcionará sobre el script compilado a un exe :smt002 .

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
gna08
Hacker del Foro
Mensajes: 379
Registrado: 27 Sep 2008, 18:51
Ubicación: Cordoba, Argentina

Re: Como escribir información dentro del exe?

Mensaje por gna08 »

jejej no pense k la pregunta causaria tal :smt031 .. bueno yo tenia echo algo antes de preguntar.. pero no lo eh terminado..
una de mis ideas es usar el reshack como herramienta extra k lo extrae el soft principal y me sirve para extraer y añadir (luego de k se cierre) datos al programa.. y lo mejor k es cuestion de segundos o casi nada para añadir el dato tan solo usando

Código: Seleccionar todo

-addoverwrite ho.ini, INI, datos,
y por asi decirlo.. abria k tener en cuenta unos 600 kb extra incluyendo la herramienta reschak y el propio au3..


Luego pongo el ejemplo.. :smt023
Aunk no m Buskes, Seguro m enkontras!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Creo que no hace falta complicarse la vida con un reshack, simplemente añadiendo el ini con un copy binario sería suficiente, lo he comprobado y el programa sigue funcionando, el comando sería:
COPY /b programa.exe+archivo.ini programa.exe

Lo he comprobado y ni siquiera pregunta si quieres machacar el exe, lo hace solito. Naturalmente el exe no tiene que estar en ejecución, para eso se saca el BAT con fileinstall, se cierra el programa, y se ejecuta el bat, cómo asegurarse el bat de que se ha cerrado el exe es algo que aún tengo que mirar, ¿hay algún comando tipo Delay en los BAT?, entonces con esperar un par de segundos antes de actualizar...
Cuando el BAT hace la copia borra el INI externo (que ya está dentro del exe) ¡y a sí mismo!. Eso no podríamos hacerlo con un EXE, pero como dice Chefito un BAT sí puede autoborrarse, toma ya.

También he comprobado en el EXE resultante, que repito, funciona, que los datos están ahí (lo he mirado con un editor binario). Como digo aún no he hecho código pero lo he probado todo manualmente y veo que es factible, ahora hay que automatizarlo.

La cosa es extraer los datos al empezar el programa, se puede poner una marca al ini, se busca desde el final hacia el principio esa marca (se lee en binario pero se busca los códigos ascii de esa marca), y a partir de ahí están los datos. Si los datos son un INI, es decir, un archivo de texto, se puede simplemente poner un CHR(1). Eso porque creo que los EXE no terminan con ningún carácter especial de fin de fichero ¿no? si fuera así se busca ese fin de fichero y lo extra son nuestros datos.
Si no se modifican no hay que hacer nada, si se modifican se crea el ini con los nuevos datos, se saca el BAT con el fileinstall y cerramos, luego el bat vuelve a meter los datos (el ini) en el exe y borra ese ini y a así mismo.
Quien dice INI dice cualquier tipo de archivo con el formato que queramos, como si lo queremos guardar en un formato binario...

Y esta es mi idea...
A ver si luego o esta tarde puedo hacer un código de ejemplo...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Pensándolo un poco se me ocurre un problema... no sólo se trata de añadir datos con un COPY /B... ¡hay que substituirlos! es decir, quitar los viejos...

Una solución es tener un FileInstall del exe original, aunque eso es un poco chapucero porque es tenerlos dos veces... habrá que pensarlo mejor...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2085
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

Re: Como escribir información dentro del exe?

Mensaje por BasicOs »

Como han comentado, siempre se puede incluir con fileinstall el compilador de autoit con los recursos, y en una carpeta temporal recompilar el exe y sustituirlo de nuevo.
Otra opción copiar aparte el exe, y se puede ser modificar el exe como con un editor hexadecimal, y escribir sobre algunas partes del exe que no son binarios, sino más constantes, como variables o textos.
El problema de modificar exes, es que en seguida van a pitar todas las alarmas de seguridad del pc, al ser operaciones "fuera de lo normal".
Es mejor tener 2 archivos, el exe y otro para datos, como un ini, sql, etc.... y luego reempaquetarlos con un compresor, en un exe autoejecutable (TENDRIÁS que reempaquetar con algunas funciones desde el programa al salir por ejemplo. :smt026
Los datos se hicieron para guardarse fuera no obstante, y los exe para no modificarlos, en principio claro.
Salu22:)
Avatar de Usuario
gna08
Hacker del Foro
Mensajes: 379
Registrado: 27 Sep 2008, 18:51
Ubicación: Cordoba, Argentina

Re: Como escribir información dentro del exe?

Mensaje por gna08 »

BasicOs escribió:Los datos se hicieron para guardarse fuera no obstante, y los exe para no modificarlos, en principio claro.
Jajja es cierto por eso kien dijo k los computadores son para uso personal en akellas epocas donde recien se inventaban las primeras PC xD...
_____
La idea de Reempaketar o recomprimir me parece INCOMODO debido a k tiene k tomarse su tiempo para agregar todos los datos de nuevo, sin contar si son muchos archivos, su tamaño, etc..
lo de agregar datos binarios es interesante.. un pokito desordenado pero algo se puede hacer para organizarse.. esta bueno para tener en cuenta.. todas las ideas son validas. :smt023
Aunk no m Buskes, Seguro m enkontras!
Avatar de Usuario
Rupert.25
Hacker del Foro
Mensajes: 247
Registrado: 17 Jul 2007, 18:27

Re: Como escribir información dentro del exe?

Mensaje por Rupert.25 »

Y hay manera de borrar el contenido del Ini del Exe?

de esa manera, se borraria el contenido anterior, y se pondría el nuevo. Aunque no sé muchos de comandos Bat, así que no se si sea posible.
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Bueno más o menos estoy de acuerdo con BasicOS, ya sabéis mis opiniones sobre la preferencia sobre los INIs, incluso con portables. (En realidad este hilo empezó en el que enlaza Chefito al principio, esas cosas se discuten allí).

Pero también estoy de acuerdo en que quizás en algunas ocasiones una técnica así sea interesante. Y desde luego como ejercicio de programación ha sido muy interesante.

He aquí mi versión, la verdad es que me gusta como ha quedado, porque ¡¡al final ni FileInstall, ni EXEs de apoyo, ni archivos BAT!! :smt003 :smt020 :smt024

El problema de no poder (o no saber) modificar el EXE desde el bat (sí añadir, pero no cambiar) lo soluciono lógicamente haciéndolo desde el EXE. Casi todo lo hago desde el EXE, y el BAT queda tan simple... que ni uso un archivo, mando el comando con un Run(@ComSpec & ' /c'...) y como eso se ejecuta asíncronamente puedo cerrar el EXE para que ese comando acabe el trabajo. La estructura de trabajo es la siguiente:

EN EL EXE:
.- Al iniciar buscar datos, si hay los toma y si no da valores por defecto (es decir, lo he hecho para que no sea necesario que el EXE contenga datos, ideal para no tener que manipular una primera compilación)
.- Interacción con el usuario.
.- Al finalizar, si el usuario quiere guardar cambios:
----Si los datos no han cambiado simplemente salimos
----Si han cambiado hacemos copia del EXE (que no es de escritura pero sí de lectura).
----Cambiamos datos EN LA COPIA del EXE
----Mandamos comando CMD de finalización y acabamos el programa

En el comando CMD de finalización:
.- Espera unos segundos a que se cierre el exe
.- Sustituye el EXE original por el modificado con un MOVE


Sobre los detalles de implementación de cómo hacer estas cosas podéis ver el código comentado al final de este comentario. Comento aquí algunas generalidades:
En el ejemplo sólo guardo como dato un String, ¡pero para nada hace esto un ejemplo trivial!. Pensad que ese String puede ser un montón de datos a extraer con un simple StringSplit o el texto de un archivo INI.
Por supuesto aún se puede ir más allá y guardar datos binarios (como imágenes), de hecho la cadena la tengo que almacenar en binario... Para manejar datos binarios lo mejor supongo que sería montarse estructuras con las funciones DllStruct....

Trabajo en binario casi todo el rato porque el EXE es binario, claro, pero me he encontrado con pocas funciones para trabajar en binario puro así que al final manejo representaciones de ese binario en String para poder hacer búsquedas, extraer fragmentos, añadir... (sí existe por ejemplo BinaryMid, pero falta lo demás). También es cierto que estoy trabajando con la versión 3.3 de AutoIt, igual me estoy perdiendo algo pero no recuerdo haber visto ampliación de funciones para binario en los "History".

Para esperarme en el comando de consola a que cierre el EXE no he encontrado un método plenamente satisfactorio. Al principio hacía un DIR de Windows\system32 para que se tirara un rato haciendo algo, pero eso es muy variable ;-). Buscando comandos estándar que me dieran una pausa controlable sólo he encontrado ping, con el parámetro -w se podría hacer esperar el tiempo que queramos con una IP bloqueante, pero eso es peliagudo, además no es aplicable si no hay acceso internet... Al menos se puede usar el hecho de que cuando haces varios pings (parámetro -n) entre ping y ping se espera algo así como un segundo. Se puede entonces hacer ping al bucle local (127.0.0.1) que tiene la gran ventaja que existe aunque no haya internet conectado y que no da otras demoras pues responde enseguida.
Actualmente le doy 3 segundos antes de hacer el MOVE, aunque he visto que es tiempo de sobra.
Así que no ejecutéis enseguida después de salir o no veréis cambios, ¡esperad 3 segundos a que tenga tiempo de poner el nuevo EXE!

Posibles mejoras:
.- Comprobar si el EXE es modificable (no está en un CD, etc.) y si no lo es advertir al usuario de que no podrá guardar datos.
.- Si hay mecanismos para trabajar directamente en binario, que quizás existan pero yo simplemente desconozco, pues usarlos para que sea más eficiente que estar pasando a String (que además ocupa más, pues cada byte se expande a dos)
.- Si se va a tratar con EXEs y datos grandes quizás sea mejor leer el EXE a fragmentos descartando hasta que se encuentre la marca de datos, y tomando a partir de ahí. También se pueden ir leyendo fragmentos desde el final (posicionándose con FileGetPos) pues los datos están siempre al final. Si son de tamaño fijo incluso se puede tomar el tamaño concreto y no hace falta ni marca de datos.
.- Con Exes/Datos grandes mejor trabajar en la misma unidad de disco, así el MOVE no tiene que copiar si no está en la unidad del sistema (para ser "aseado" trabajo en el temporal de Windows). Eso tiene el inconveniente de que el usuario ve aparecer el archivo temporal, pero si son varias megas...
De todas maneras para varias megas yo no usaría este tipo de técnicas de datos en EXE, para eso mejor un INI o incluso una base de datos...

Ala, espero que os guste, mejor compilarlo con las opciones por defecto (para que comprima con UPX y así ocupe menos y sea todo más rápido). La primera vez no tiene datos, no pasa nada, como digo el programa lo comprueba y ofrece un valor por defecto (que no guardará si no se cambia).

Código: Seleccionar todo

#cs ----------------------------------------------------------------------------

 Script:         GuardaDatosEnEXE.au3
 Versión AutoIt: 3.3.0.0
 Autor:          Ximo Izquierdo

 Objetivo del Script:
	Implementa mecanismo de guardado de datos en el propio EXE

#ce ----------------------------------------------------------------------------

#include <GUIConstantsEx.au3>

Opt("MustDeclareVars",1)

If Not @Compiled Then
	MsgBox(48, "Ejecución Abortada", "Este script sólo puede ejecutarse si está compilado.")
	Exit
EndIf

; Marca de inicio de datos en el EXE, como mis datos son texto puede ser muy simple:
; algunos caracteres no imprimibles más algo de texto para asegurarme.
; La condición es que la marca no pueda estar contenida en los datos.
; Podría ser aún más simple si obligo a que el EXE siempre lleve datos, cosa que no hago,
; pero si no ojo por si esa combinación se da en el binario original...
; (si siempre hay datos no es problema porque como busco desde el final la primera ocurrencia
; que encuentre será mi marca)
; Lo paso a binario y me quedo con su representación en string quitando el "0x" inicial
Global $marcaInicioDatos = _BytesString(Chr(0)&Chr(1)&"DATA")


Global $DATO, $txtDato, $btnCancelar, $btnGuardar
GuiCreate("Ejecutable con datos incrustados guardables", 370,160)

$DATO = _LeeDatoGuardado()
GUICtrlCreateLabel("Dato actualmente guardado: " & @LF & $DATO, 25,16, 300,30)
GUICtrlSetFont(-1, 9.5, 800)

GUICtrlCreateLabel("Escriba cadena a guardar:", 25,64, 129,17)
$txtDato = GUICtrlCreateInput($DATO, 25,83, 320,21)

$btnCancelar = GUICtrlCreateButton("Cancelar", 72,123, 100,24)
$btnGuardar = GUICtrlCreateButton("Guardar y Salir", 192,123, 100,24 )
GUICtrlSetState(-1, $GUI_DEFBUTTON)

GUISetState(@SW_SHOW)

While 1
	Switch GUIGetMsg()
		Case $btnGuardar
			_SalirGuardando(GUICtrlRead($txtDato))
		Case $GUI_EVENT_CLOSE, $btnCancelar
			ExitLoop
	EndSwitch
WEnd

Func _LeeDatoGuardado()
	Local $fExe, $fBin, $pos
	;Buscamos marca de datos en el ejecutable
	$fExe = FileOpen(@ScriptFullPath, 16)
	$fBin = String(FileRead($fExe))
	FileClose($fExe)
	$pos = StringInStr($fBin, $marcaInicioDatos, 2, -1)
	If $pos <> 0 Then
		; Marca encontrada, extraemos los datos, están desde después de la marca hasta el final
		Return BinaryToString("0x" & StringMid($fBin, $pos+StringLen($marcaInicioDatos)))
	Else
		; No hay datos, devolvemos valor por defecto
		Return "¡Autoit es una pasada!"
	EndIf
EndFunc

Func _SalirGuardando($txt)
	Local $datoBin, $fExe, $fBin, $nomTemp, $fTemp, $pos, $cmd
	If $DATO == $txt Then Exit ; Dato no cambiado, salimos sin más

	; Leemos EXE y buscamos inicio de datos si existe
	$fExe = FileOpen(@ScriptFullPath, 16)
	$fBin = String(FileRead($fExe))
	FileClose($fExe)
	$pos = StringInStr($fBin, $marcaInicioDatos, 2, -1) ;buscamos desde el final
	; Si ya había datos los quitamos antes de poner los nuevos
	If $pos <> 0 Then $fBin = StringMid($fBin, 1, $pos-1)

	;Metemos nuevo dato y creamos el EXE modificado
	$fBin &= $marcaInicioDatos & _BytesString($txt)
	$nomTemp = @TempDir & "\" & @ScriptName & ".TEMP"
	$fTemp = FileOpen($nomTemp, 18) ;Escritura binaria, nuevo archivo
	FileWrite($fTemp, Binary($fBin))
	FileClose($fTemp)

	; Mandamos a la consola el comando que sustituye el EXE en ejecución por el modificado y salimos
	; Esperamos 3 segundos antes de mover el archivo, debería ser tiempo de sobra para desbloquear el ejecutable
	; Nombres de archivo entre comillas por si llevan espacios
	$cmd = @ComSpec & ' /c ping 127.0.0.1 -n 3 > nul && MOVE /Y "' & $nomTemp & '" "' & @ScriptFullPath & '"'
	;ConsoleWrite($cmd & @LF)
	Run($cmd, @TempDir, @SW_HIDE)
	Exit
EndFunc

Func _BytesString($expr)
	;Devuelve en un String la representación binaria de una expresión, sin el "0x" inicial
	Return StringTrimLeft(Binary($expr), 2)
EndFunc
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
gna08
Hacker del Foro
Mensajes: 379
Registrado: 27 Sep 2008, 18:51
Ubicación: Cordoba, Argentina

Re: Como escribir información dentro del exe?

Mensaje por gna08 »

Exelente... lo habia pensado pero me daba pereza todo el trayecto :smt019 xD
Muy bien logrado ximorro.. pero kisas sea incomodo para cierto tipo de datos. Lo voy a probar y comento..
Salu2 :smt038
Aunk no m Buskes, Seguro m enkontras!
Avatar de Usuario
gna08
Hacker del Foro
Mensajes: 379
Registrado: 27 Sep 2008, 18:51
Ubicación: Cordoba, Argentina

Re: Como escribir información dentro del exe?

Mensaje por gna08 »

Perfecto :smt035 :smt035 no se me ubiera ocurrido lo del ping xD... creo k es justo lo k necestiabamos xD.. veamos k comenta el resto y propone otras ideas xq no? :smt017
REspeecto al multiples datos k opinas?? recuerdo que yo cierta ves hice algo parecido en archivos para guardar e identificar mis propios archivos agregando datos binarios .. separando datos con algun tipo caracteres al azar unicos de manera k tenga tags por ej:

<5a4sd6-data-1>bla bla bla</5a4sd6-data-1><5a4sd6-data-2>mas blabla</5a4sd6-data-2>

y de alguna forma ya sea con _stringBetween kisas extraer los datos.. k sugieren.. :smt017

Saludos :smt024
Aunk no m Buskes, Seguro m enkontras!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Si puedes almacenar esos varios datos en un string es muy sencillo, y es lo habitual, pues los números los puedes guardar en string y luego al leerlos los vuelves a pasar a número (que con lo poco tipado que es AutoIT no hay que hacer prácticamente nada.
Juntas los diferentes datos con un carácter de separación, que no debe estar en los datos, claro, pero como es ASCII puedes usar un carácter especial como CHR(1) (hago algo así para marcar mis datos en el EXE)
Ese carácter de separación por defecto es "|" en AutoIt, pero puedes cambiarlo a conveniencia. Luego esos datos los recoges directamente en un array con StringSplit

Código: Seleccionar todo

; Múltiples datos que queremos guardar
$Dato1 = "dato1"
$Dato2 = "dato2"
$Dato3 = "dato3"
$Dato4 = "dato4"

;Al guardar los datos:
$CadenaParaExe = $Dato1 & "|" & $Dato2 & "|" & $Dato3 & "|" & $Dato4
;Eso se mete en el exe por ejemplo con mi programa, ¡pues ahora es sólo un String!

;----------------------------------

;Al extraer los datos:
$DatosEnExe = $CadenaParaExe ;esto realmente se leería del EXE
$aDatos = StringSplit($DatosEnExe, "|")

;Recogemos los datos del array resultante, quizás podrían manejarse de ahí,
;tampoco haría falta sacarlos. Pero bueno, es trivial:
$Dato1 = $aDatos[1] ;en $aDatos[0] está el número de datos
$Dato2 = $aDatos[2]
$Dato3 = $aDatos[3]
$Dato4 = $aDatos[4]
Y vaya, que puedes tener la estructura más compleja, como comentaba una especie de INI, un archivo CSV, etc. (al fin y al cabo cualquier archivo de texto se puede pasar a un único string). Y sí, también datos puramente binarios. Esas cosas las comentaba en el comentario donde he puesto mi propuesta, ¡¡espero que lo hayas leído!! ;-)

Efectivamente ¡espero ver las soluciones de los demás! Si es posible será más interesante si se implementan otras perspectivas diferentes, claro, como lo de los archivos empaquetados, por ejemplo.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Como escribir información dentro del exe?

Mensaje por Chefito »

Muy chulo Ximorro :smt038 . El programa está muy bien.
Ximorro escribió:El problema de no poder (o no saber) modificar el EXE desde el bat (sí añadir, pero no cambiar) lo soluciono lógicamente haciéndolo desde el EXE. Casi todo lo hago desde el EXE, y el BAT queda tan simple... que ni uso un archivo, mando el comando con un Run(@ComSpec & ' /c'...) y como eso se ejecuta asíncronamente puedo cerrar el EXE para que ese comando acabe el trabajo
Muy buena idea.
Ximorro escribió:Para esperarme en el comando de consola a que cierre el EXE no he encontrado un método plenamente satisfactorio. Al principio hacía un DIR de Windows\system32 para que se tirara un rato haciendo algo, pero eso es muy variable . Buscando comandos estándar que me dieran una pausa controlable sólo he encontrado ping, con el parámetro -w se podría hacer esperar el tiempo que queramos con una IP bloqueante, pero eso es peliagudo, además no es aplicable si no hay acceso internet... Al menos se puede usar el hecho de que cuando haces varios pings (parámetro -n) entre ping y ping se espera algo así como un segundo. Se puede entonces hacer ping al bucle local (127.0.0.1) que tiene la gran ventaja que existe aunque no haya internet conectado y que no da otras demoras pues responde enseguida.
También muy buena idea. Esta forma para hacer un retraso en los batch (llamar al localhost) la ví hace tiempo, lo que pasa que ya mi me acordaba. Tengo el batch bastante olvidado.
He encontrado otra forma de crear un contado utilizando el reloj del sistema:
http://foro.elhacker.net/scripting/cron ... msg1040920
Y un par de formas de controlar si un proceso está ejecutándose:
http://foro.el-hacker.com/f82/g-comprob ... do-138931/
Ximorro escribió:.- Si hay mecanismos para trabajar directamente en binario, que quizás existan pero yo simplemente desconozco, pues usarlos para que sea más eficiente que estar pasando a String (que además ocupa más, pues cada byte se expande a dos)
Siempre puedes intentar utilizar las funciones para manejo de ficheros: filegetpos, filesetpos, fileflush, fileread, filewrite, etc.
Y como último recurso siempre nos quedan las apis de win para el manejo de datos, aunque esto tiene que ser un tanto dificil :smt017 .
Ximorro escribió:Si se va a tratar con EXEs y datos grandes quizás sea mejor leer el EXE a fragmentos descartando hasta que se encuentre la marca de datos, y tomando a partir de ahí. También se pueden ir leyendo fragmentos desde el final (posicionándose con FileGetPos) pues los datos están siempre al final. Si son de tamaño fijo incluso se puede tomar el tamaño concreto y no hace falta ni marca de datos.
Mejor posicionate con FileSetPos :smt005 :smt016 . Supongo que haya sido un fallo técnico :smt003 .

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Me alegro de que os haya gustado.
Encima igual lo uso en uno de mis programas, y mira que yo era de los defensores del INI, pero en mi salvapantallas (http://www.emesn.com/autoitforum/viewto ... f=4&t=1987) prefiero que no necesite archivos de configuración por separado, un SCR mejor solito, mucho más manejable para el usuario, que lo tiene que poner en las entrañas del sistema (si quiere que aparezca en la lista con los demás). Y como algo así no pasa nada si al pasarlo a alguien le pasas tu configuración...

Lo de la espera para hacer un batch tan complejo prefiero lo del ping en una línea, así me evito el archivo BAT.

Lo del programa tasklist no lo conocía ¿en qué S.O. estará disponible? Me gustaría usar algo estándar. Mola la idea de estar esperando a que se cierre el programa, pero ese comando tarda tanto en ejecutarse que cuando sacas la lista el programa ya ha finalizado :smt003
Pero es un comando MUY interesante, una especie de administrador de tareas para la consola... (bueno sólo muestra información, no cierra procesos ni nada de eso, pero ya es algo interesante)
Puestos a hacer algo complejo (o sea, que ya necesitemos un BAT) preferiría hacer un bucle que compruebe si la copia se ha podido hacer, y si es que no pues que repita. En mi caso supongo que sería repetir mientras el archivo temporal exista, eso significará que el MOVE no ha podido ejecutarse (porque el destino aún estaba en uso).
(Ah, no había visto el programa qprocess, tampoco sabía que existía, parece que responde más rápido que tasklist porque puedes preguntarle por un proceso concreto (en tasklist buscan "a mano" en la lista resultado). Vaya, muchos comandos nuevos por la consola, la duda es desde cuando existen y si están en todos los S.O. donde trabaja AutoIt...) La de cosas nuevas que han salido en la consola de comandos y yo sin enterarme :smt002


Lo de los procesos binarios era por ejemplo a buscar la marca de inicio de datos en la ristra binaria, una especie de StringInStr pero con bytes: BytesInBinary. Como no existe tengo que pasarlo a String para hacer las búsquedas. La extracción, BinaryMid, sí existe, pero si no encuentro primero la posición donde extraer... :smt002

Sí, sí, FileSetPos, era para ver si estábais atentos :smt005
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Esperar a que el programa termine:

La verdad es que estoy contento por cómo me ha quedado por la simplicidad de la solución, pero la parte que no me gusta mucho es eso de esperar unos segundos a que termine el programa: apurar el tiempo es difícil, si te quedas corto no actualiza, no encuentro otra manera de esperar aparte de ping, o sea, ajustes de un segundo...

Con los enlaces estos de Chefito me pica la idea de hacer algo que espere realmente a que el programa finalice, tarde lo que tarde, pero no más tiempo.
Al principio lo había hecho con qprocess (este me gusta más porque va al grano, tasklist también funciona pero es más lento y hay que buscar en los resultados con find). Funciona perfecto, pero sigue sin gustarme la idea de usar un programa externo que quizás no esté en todos los S.O. Pasa algo parecido con ping, pero ping está ahí desde hace siglos y no parece que lo vayan a quitar...

Pues bien, siguiendo esa idea se me ha ocurrido hacer algo directamente con MOVE, que al fin y al cabo también devuelve un código de error si falla. Simplificando todo lo que he podido he llegado a este BAT que espera a que finalice el programa, y cuando finaliza hace el MOVE:
(los nombres de archivo habría que ponerlos por código, y entre comillas)

Código: Seleccionar todo

:repite
move /Y archivotemporal.tmp ejecutableoriginal.exe >nul 2>nul || GOTO :repite
¿Simple, no? (con qprocess es una línea más, pues qprocess se usa para la comprobación y cuando acaba hay que hacer el MOVE)
Se puede hacer con un IF ERRORLEVEL 0 GOTO repite, en vez de la parte del OR, pero la cosa es hacerlo lo más compacto posible porque...

...ahora la cuestión es: ¿ES POSIBLE PONER ESO EN UNA LÍNEA? o dicho de otra manera ¿Es posible ponerlo de alguna manera para que se pueda ejecutar con cmd.exe /c o similar?.

A ver si se os ocurre algo, si no es inevitable hacer un archivo BAT (yo no uso FileInstall, lo creo desde código, así genero los nombres de archivo dinámicamente).
El BAT sería igual al código anterior pero añadiendo la línea que lo auto-borre.

Una consideración es que esto hunde la CPU hasta que finaliza (también ocurría con qprocess), por otro lado eso es un tiempo muy pequeño pues el BAT se lanza justo antes del Exit del programa, así que de ahí a que el EXE quede desbloqueado pasa poco tiempo.
En cualquier caso se podría poner el famoso ping después de la etiqueta, para que intente cada segundo, creo que no es necesario pero tampoco es mala solución.

A ver si se os ocurre cómo ponerlo sin tener que hacer un BAT guardado a disco... :smt006 :smt006
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Como escribir información dentro del exe?

Mensaje por Chefito »

Precisamente estuve mirando ayer en intentar poner una etiqueta y un goto etiqueta en una sola línea, pero chico, no hubo manera :smt012 .
Luego pensé es si se podía hacer alguna triquiñuela con el bucle for...in....do. Pero ya no lo miré.
No se si habrá alguna solución para esto :smt017 .

Yo estoy investigando. Estoy trabajando directamente con los datos binarios, pasandole el string en binario, pero estoy teniendo problemas. Se me cuelan caracteres extraños al principio, y caracteres null por medio del texto :smt017 . Veremos a ver si lo solucionamos. Empecé ayer a mirarlo :smt005 .
También he podido coger solamente los bytes del final que necesito con las funciones que trae AutoIt y trabajar con ellos(bastante facil).

Si consigo solucionar esto no hará falta una copia del archivo exe. Se podrá trabajar directamente con él :smt002 .

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Efectivamente creo que para hacer que espere al desbloqueo de escritura habrá que hacer necesariamente un BAT, quizás haya una manera totalmente diferente de hacerlo, si a alguien se le ocurre...

Lo de los caracteres nulos puede ser por la conversión de string a binario, al poner los ASCII8 en 16 bits le pone un cero de relleno. Si es eso para recuperarlo haz el BinaryToString, como hago yo con mi método...

Lo de coger los bytes del final es fácil si los datos son de tamaño fijo, y efectivamente así se simplifican las cosas. Hombre si sabes por ejemplo que siempre hay menos de 100 bytes pues coges 100 bytes del final y buscas donde empiezan en ese trozo, en vez de en todo el archivo como hago yo (aunque yo busco desde el final, así que tampoco es que se recorra todo el código).

No entiendo lo que quieres decir de trabajar directamente con el archivo EXE, para modificarlo no tiene que estar en ejecución ¿has encontrado una manera de modificarlo desde el BAT? ¿quizás con un exe auxiliar? ¿es que te has saltado la protección de Windows en ejecutables? tú eres capaz :smt005

¡Espero ver tu solución!...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Como escribir información dentro del exe?

Mensaje por Chefito »

Bueno bueno. Siento el retraso, pero he tenido estos días la visita de mi novia y eso es lo primero de atender :smt005 .

Hoy tenía todo el domingo para mí y he creado el código que tenía en mente. Puede que para algunos sea algo complicado. Si alguien quiere saber algo que no entienda, que pregunte, que con gusto se lo intentaré explicar :smt002 .

Con permiso de Ximorro he utilizado la base de su código para ahorrarme algo de tiempo con la gui :smt002 .

Una pequeña explicación del código (algunos matices):

ESTO QUE VOY A DECIR A CONTINUACIÓN ES MUY IMPORTANTE: Como el tamaño de los exe originales no cambian, he utilizado este tamaño en bytes para saber el final del fichero exe y el principio de los datos insertados. Teneis que fijaros muy bien en esto. Yo lo que hacía era, cuando acababa el código script, lo compilaba con el botón derecho del ratón y le veía su tamaño. Una vez que sabía el tamaño exacto, lo ponía bien en la constante $SizeExe y lo volvía a compilar. Esta vez ya debería funcionar bien.

El corazón del código es la generación de un archivo vbs. Estos archivos tienen mucha mucha mucha más potencia que los batch, y encima no suelen utilizar archivos externos para hacer las cosas. Lo que si utilizan son muchos objetos para hacer cosas complicadas. Genero el archivo vbs y lo guardo en el directorio temporal, para que al finalizar se borre.

En el centro del corazón encontramos el objeto ADODB.Stream para manejo de ficheros, tanto de texto como de binario (esto es lo más interesante). Por supuesto os digo que en AutoIt podeis utilizar este objeto sin problemas. Hay mucha información en google. Desde explicaciones hasta funciones ya hechas. Yo he mirado mucho esta página: http://www.w3schools.com/ADO/ado_ref_stream.asp , ya que están todas las propiedades y métodos del objeto.

Utilizo otros objetos para hacer otras cosas, como saber si un proceso está ejecutado y borrar un archivo. Están comentados en el código.

La recogida de datos del exe la hago en AutoIt. Lo que hago es averiguar el tamaño en bytes de los datos insertados en el exe y, gracias a esto, poder posicionar el puntero en el comienzo de los datos para luego cogerlos y transformarlos a tipo string. Lo podía haber hecho con el objeto ADODB.Stream, pero quería demostrar que se puede hacer con las funciones de AutoIt.

El código es el siguiente:

Código: Seleccionar todo

#include <GUIConstantsEx.au3>
#include <Constants.au3>

Opt("MustDeclareVars",1)

If Not @Compiled Then
   MsgBox(48, "Ejecución Abortada", "Este script sólo puede ejecutarse si está compilado.")
   Exit
EndIf

Global Const $SizeExe=316085	;tamaño en bytes del archivo compilado exe original.
Global $DATO, $txtDato, $btnCancelar, $btnGuardar

GuiCreate("Ejecutable con datos incrustados guardables", 370,160)

$DATO = _LeeDatoGuardado()
GUICtrlCreateLabel("Dato actualmente guardado: " & @LF & $DATO, 25,16, 300,30)
GUICtrlSetFont(-1, 9.5, 800)

GUICtrlCreateLabel("Escriba cadena a guardar:", 25,64, 129,17)
$txtDato = GUICtrlCreateInput($DATO, 25,83, 320,21)

$btnCancelar = GUICtrlCreateButton("Cancelar", 72,123, 100,24)
$btnGuardar = GUICtrlCreateButton("Guardar y Salir", 192,123, 100,24 )
GUICtrlSetState(-1, $GUI_DEFBUTTON)

GUISetState(@SW_SHOW)

While 1
	Switch GUIGetMsg()
		Case $btnGuardar
			If Not($DATO==GUICtrlRead($txtDato)) Then _SalirGuardando(GUICtrlRead($txtDato))
			Exit
		Case $GUI_EVENT_CLOSE, $btnCancelar
			ExitLoop
	EndSwitch
WEnd

Func _LeeDatoGuardado()
	Local $fExe, $nBytesDatos, $fBin
	;Abrimos el archivo en modo binario para leerlo.
	$fExe = FileOpen(@ScriptFullPath, 16)
	$nBytesDatos=$SizeExe-FileGetSize(@ScriptFullPath)	;averiguamos el tamaño en bytes de los datos insertados en el exe (en negativo).
	If $nBytesDatos <> 0 Then		;Si el tamaño de los datos es distinto de 0 significa que hay datos....logico no? ;)=
		FileSetPos($fExe,$nBytesDatos,$FILE_END)	;posiciono el puntero en el comienzo de los datos indexados en el exe.
		$fBin = FileRead($fExe)		;leo los datos del archivo
		Return BinaryToString($fBin)	;transformo los datos de binario a string
	Else
		Return ""
	EndIf
	FileClose($fExe)
EndFunc

Func _SalirGuardando($txt)
	Local $Scriptvbs, $file
	Local Const $pathFileVBS=@TempDir & "\Aplicacion.vbs"
	
	;código del archivo vbs que se ejecutará justo antes de cerrarse la aplicación.
	;Este código lee el fichero e inserta los nuevos datos en el exe. También detecta algún error. Al final se borra a sí mismo.
	
	;función que te indica si existe un proceso en ejecución. Utilizo el objeto WScript.Shell. Tambien utilizo información de Windows.
	;Si el proceso existe da true, y si no da false. Encontrada en: http://www.davidsuarez.es/2008/09/saber-si-un-proceso-se-esta-ejecutando-visual-basic-script-vbs/
	$Scriptvbs = 'Function ExisteProceso(NombreProceso)' & @CR
	$Scriptvbs &= 'Set WshShell = WScript.CreateObject ("WScript.Shell")' & @CR
	$Scriptvbs &= 'Set colProcessList = GetObject("Winmgmts:").ExecQuery ("Select * from Win32_Process")' & @CR
	$Scriptvbs &= 'For Each objProcess in colProcessList' & @CR
	$Scriptvbs &= 'If objProcess.name = NombreProceso then' & @CR
	$Scriptvbs &= 'ExisteProceso = True' & @CR
	$Scriptvbs &= 'Else' & @CR
	$Scriptvbs &= 'ExisteProceso = False' & @CR
	$Scriptvbs &= 'End if' & @CR
	$Scriptvbs &= 'Next' & @CR
	$Scriptvbs &= 'Set WshShell = Nothing' & @CR
	$Scriptvbs &= 'Set colProcessList = Nothing' & @CR
	$Scriptvbs &= 'End Function' & @CR

	;Esta función transforma los datos string a binario para luego poder insertarlos directamente en el exe.
	;Utilizo el objeto ADODB.Stream con todas sus posibilidades para trabajar con ficheros binarios y de texto.
	;Stream_StringToBinary Function
	;2003 Antonin Foller, http://www.motobit.com
	;Modificada por chefito
	$Scriptvbs &= 'Function Stream_StringToBinary(Text)' & @CR
	$Scriptvbs &= 'Dim BinaryStreamLocal, DatosResult' & @CR
	$Scriptvbs &= 'Set BinaryStreamLocal = CreateObject("ADODB.Stream")' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.Type = adTypeText' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.CharSet = "iso-8859-1"' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.Open' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.WriteText Text' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.Position = 0' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.Type = adTypeBinary' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.Position = 0' & @CR
	$Scriptvbs &= 'DatosResult=BinaryStreamLocal.Read' & @CR
	$Scriptvbs &= 'BinaryStreamLocal.close' & @CR
	$Scriptvbs &= 'Stream_StringToBinary = DatosResult' & @CR
	$Scriptvbs &= 'End Function' & @CR
	
	$Scriptvbs &= 'Const adTypeText = 2' & @CR
	$Scriptvbs &= 'Const adTypeBinary = 1' & @CR
	$Scriptvbs &= 'Const fichero = "' & @ScriptFullPath & '"' & @CR
	$Scriptvbs &= 'Dim BinaryStreamFile, BinaryStreamDato, BinaryStreamAux, TrozoFile, TrozoDato, ContBucle, ContinuarScript, Datos' & @CR
	
	$Scriptvbs &= 'ContBucle=0' & @CR
	$Scriptvbs &= 'ContinuarScript=True' & @CR
	$Scriptvbs &= 'Datos="' & $txt & '"' & @CR
	
	;bucle. Si existe el proceso de nuestro exe no sale del bucle. Tiene un contador para parar el bucle si al cierto tiempo sigue detectando el proceso.
	;$Scriptvbs &= 'Set WshShell = WScript.CreateObject("WScript.Shell")' & @CR
	$Scriptvbs &= 'Do While ExisteProceso("' & @ScriptName & '")' & @CR
	$Scriptvbs &= 'WScript.Sleep 50' & @CR
	;$Scriptvbs &= 'WshShell.Sleep=50' & @CR
	$Scriptvbs &= 'ContBucle=ContBucle+1' & @CR
	$Scriptvbs &= 'If ContBucle=60 Then' & @CR		;cada 20 es un segundo de espera antes de dar el error y salir del script
	$Scriptvbs &= 'ContinuarScript=False' & @CR
	$Scriptvbs &= 'MsgBox "No se han podido guardar los datos",16,"Error al grabar los datos"' & @CR
	$Scriptvbs &= 'Exit Do' & @CR
	;$Scriptvbs &= 'WScript.Quit' & @CR
	$Scriptvbs &= 'End If' & @CR
	$Scriptvbs &= 'Loop' & @CR
	
	;si se ha cerrado el proceso bien y ha salido del bucle, entra en esta condición que contiene todo el código de inserción de los datos al exe.
	$Scriptvbs &= 'If ContinuarScript Then' & @CR
	$Scriptvbs &= 'Set BinaryStreamAux = CreateObject("ADODB.Stream")' & @CR
	$Scriptvbs &= 'BinaryStreamAux.Type = adTypeBinary' & @CR
	$Scriptvbs &= 'BinaryStreamAux.Open' & @CR
	$Scriptvbs &= 'Set BinaryStreamFile = CreateObject("ADODB.Stream")' & @CR
	$Scriptvbs &= 'BinaryStreamFile.Type = adTypeBinary' & @CR
	$Scriptvbs &= 'BinaryStreamFile.Open' & @CR
	$Scriptvbs &= 'BinaryStreamFile.LoadFromFile Fichero' & @CR
	$Scriptvbs &= 'TrozoFile=BinaryStreamFile.Read(' & $SizeExe & ')' & @CR
	$Scriptvbs &= 'binarystreamFile.position=0' & @CR
	$Scriptvbs &= 'binarystreamAux.write TrozoFile' & @CR
	
	$Scriptvbs &= 'If Datos<>"" Then' & @CR
	$Scriptvbs &= 'TrozoDato=Stream_StringToBinary(Datos)' & @CR
	$Scriptvbs &= 'Set BinaryStreamDato = CreateObject("ADODB.Stream")' & @CR
	$Scriptvbs &= 'BinaryStreamDato.Type = adTypeBinary' & @CR
	$Scriptvbs &= 'BinaryStreamDato.Open' & @CR
	$Scriptvbs &= 'binarystreamDato.write TrozoDato' & @CR
	$Scriptvbs &= 'binarystreamDato.position=0' & @CR
	$Scriptvbs &= 'binarystreamDato.copyto binarystreamAux' & @CR
	$Scriptvbs &= 'BinaryStreamDato.close' & @CR
	$Scriptvbs &= 'End If' & @CR
	
	$Scriptvbs &= 'binarystreamAux.savetofile fichero,2' & @CR
	$Scriptvbs &= 'End If' & @CR
	
	$Scriptvbs &= 'BinaryStreamFile.close' & @CR
	$Scriptvbs &= 'BinaryStreamAux.close' & @CR

	;código para borrar el propio fichero vbs. Utilizo el objeto Scripting.FileSystemObject.
	$Scriptvbs &= 'Dim fso' & @CR
	$Scriptvbs &= 'Set fso = CreateObject("Scripting.FileSystemObject")' & @CR
	$Scriptvbs &= 'fso.DeleteFile "' & @TempDir & "\Aplicacion.vbs" & '",True' & @CR
	$Scriptvbs &= 'Set fso=Nothing' & @CR	
	
	;creo el fichero vbs y guardo el código anterior en su interior.
	$file = FileOpen($pathFileVBS, 2)
	FileWrite($pathFileVBS, $Scriptvbs)
	FileClose($file)
	ShellExecute("Aplicacion.vbs","",@TempDir)	;ejecuto el archivo vbs.
	;Exit
EndFunc
Le he añadido una chorradilla :smt005 . Comparo la cadena recuperada con la cadena a guardar. Si son iguales no modifico el exe, ya que no haría falta.
No le he puesto ningún texto en el input al principio. Por cierto, se me ocurre otra forma simple de poner un texto al principio del input. Si le quisiese poner algún texto al principio lo pondría ejecutanto una vez el exe y poniendoselo para que lo añadiese en el ejecutable :smt005 :smt005 :smt005 . No os parece??? Pero esto tiene una cosita mala (no mucho :smt016 ). Que tendría que trabajar con el ejecutable (abrirlo, leerlo y coger el texto). Esto sería algo más lento que ponerselo directamente.

Voy a adjuntar el archivo con el código script y éste ya compilado.

Saludos.
Adjuntos
Ejemplo Insertar datos en exe.rar
Contiene código script, script compilado a ejecutable (exe) y archivo de texto con el código vbs
(297.13 KiB) Descargado 339 veces
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Mare el código VBScript asusta, me lo estudiaré con tranquilidad. :smt002

No mola demasiado eso de compilar para ver el tamaño y luego recompilar poniendo ese tamaño a mano. Creo que se podría evitar poniendo un dato extra a continuación de los del usuario: el tamaño de los datos.
El último int de los datos (leer a piñón fijo los dos últimos bytes) tendría el tamaño de los datos, y eso se usaría en el FileSetPos para leerlos.
El problema lógicamente es la primera vez que se ejecuta, que ahí habrá cualquier cosa porque aún no hemos escrito datos. Así rápido veo dos soluciones:
a) Meter dos bytes a 0 con un "Copy /b". No me gusta demasiado porque hay que manipular la primera compilación, y es lo que quiero evitar, aunque al menos es menos complejo que mirar el tamaño y volver a recompilarlo.
b) Poner una marca de "datos guardados", sería como lo que hago yo para marcar el principio de los datos, pero al final, por ejemplo 4 bytes con valores fijos. Si no está la marca es que aún no hay datos. Complica un poco el código pero así es "compilar y listo".
Además, si usas UPX puede que no recompile exactamente a ese tamaño, a lo mejor sólo cambia un byte pero ya te ha fastidiado. Y no te digo nada si usas Obfuscator, cada compilación tendrá un tamaño, especialmente al comprimir.

Por cierto, yo tampoco guardo el valor si no ha cambiado, y además doy uno por defecto si aún no hay ninguno ;-)

Por ahora creo que usaré mi método (quizás con el bat que espera a que se cierre el EXE, que es la ventaja que tiene tu vbs respecto a mi "CMD /C" inicial). Creo que mi versión es más simple para tener casi la misma funcionalidad (claro que aún me tengo que estudiar el vbs), ¡y además es mío! :smt003
El tuyo mejora el hecho de ir directo a leer los datos, quizás modifique el mío con eso del tamaño de los datos al final del EXE para no leer todo el archivo en una cadena.
También haces comprobación de errores, genial, yo eso lo tendría que hacer desde AutoIt, creo que miraría al principio si el archivo es de sólo lectura para avisar al usuario nada más empezar que no se podrán guardar datos. Si hay problemas posteriores habría que hacerlo desde el bat, ahí es más complicado y el vbs gana de calle. Con un BAT supongo que haría un número de intentos fijos antes de darlo por imposible.

Joer cada vez que miro el código del vbs flipo, pero qué bruto, qué máquina :smt003
Por cierto, ¿lo tienes por casualidad en un archivo a parte indentado para leer bien el código?

Hum, me he encontrado un problema, si una vez que tiene datos intento guardar una cadena vacía (no poner datos) da error... Creo que sería cosa de comprobarlo en el vbs, al hacer eso se dejaría el EXE como el original, sin datos.

En mi caso no queda el exe original, yo dejo la marca de datos. Lo hice adrede porque es diferente si el usuario quiere poner datos vacíos (marca de datos sin datos a continuación) o que el exe realmente no tiene datos (sin marca de datos). He distinguido los casos pero es cosa de gustos, también se puede quitar la marca de datos al encontrarse una cadena vacía, con lo que se obtiene el EXE original. Claro que al recuperar el dato en mi caso daré el valor por defecto, en vez de la cadena vacia, he ahí la diferencia.

Parece que defiendo a ultranza mi método pero tampoco es eso, me gusta mucho del tuyo que se espera a que acaba el proceso y el control de errores (menos lo de cadena vacía, aunque eso lo arreglas en 10 segundos). Lo que menos me gusta es lo de mirar el tamaño para recompilar con el nuevo dato, por los problemas que te comentaba arriba.

En mi método original no mola nada lo de esperarse dos segundos a que acabe el EXE, es mejor con el BAT con el bucle, aunque me gustaba mucho la idea del "CMD /C" por no sacar ningún archivo extra al temporal...
También me falta hacer comprobación de errores, afortunadamente puedo hacer buena parte desde AutoIt.

¡Enhorabuena por tu método!, es muy interesante ver otras posibilidades :smt041 Ahora me tengo que estudiar ese vbs con la escritura binaria :smt027

¡Animáos los demás! Había ideas revolucionarias como ejecutarlo desde un comprimido y recomprimir con los datos, ¿cómo va la cosa?
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Como escribir información dentro del exe?

Mensaje por Ximorro »

Analizando el código de Chefito he visto algo que yo hacía mal: al comprobar si los datos a guardar coinciden con lo guardado (para no volver a guardar) lo hacía con el operador "=", pero eso no es caso sensitivo, lo correcto es hacerlo con "==" que con números es lo mismo pero para cadenas distingue mayúsculas y minúsculas.

Gracias Chefito a ver qué más me enseñas :smt003
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Como escribir información dentro del exe?

Mensaje por Chefito »

Ximorro escribió:Mare el código VBScript asusta, me lo estudiaré con tranquilidad.
Jajajajaja....que va que va, no es para tanto :smt016 . El que lo mire con detenimiento más o menos lo puede entender. La sintasis es muy parecida a AutoIt, e identica a vb, para el que sepa este otro lenguaje.
Ximorro escribió:No mola demasiado eso de compilar para ver el tamaño y luego recompilar poniendo ese tamaño a mano.
Cuestión de gusto. Eso simplemente se hace una vez para poder saber el tamaño exacto del fichero exe. Tampoco es que te vaya a costar un montón, no? :smt003 .
Ximorro escribió:Creo que se podría evitar poniendo un dato extra a continuación de los del usuario: el tamaño de los datos.
Sí. Sería una forma de evitarlo. Pero ya tienes que poner unos pocos cálculos más y paso. Prefiero trabajar sobre un dato fijo, ya que se supone que éste no debe cambiar nunca (el tamaño del fichero original). Si cambiase.....malo. Un programa maligno puede haber metido datos de más :smt005 .
Lo dicho, cuestión de gustos :smt002 .
Ximorro escribió:El último int de los datos (leer a piñón fijo los dos últimos bytes) tendría el tamaño de los datos, y eso se usaría en el FileSetPos para leerlos.
Sí, sería una buena idea. Pero tiene fallos. En este caso puede que funcionase si no fuesen muchos los datos que se introducen. Pero que pasa si es un edit y le metes un montón de texto que sobrepase el tamaño de los dos últimos bytes??? Podríamos pensar en coger el final hasta que se acaben los bytes numéricos. Tampoco valdría, porque el texto del usuario podría acabar en dígitos. Con todo esto, solamente nos queda el intentar poner una marca única para reconocer los datos. Esto obliga a ir recorriendo bytes desde el final hasta encontrar la marca.
Lo dicho, prefiero un valor fijo y si tengo que tratar con datos binarios del fichero, que solamente sea un trozo del final.
Ximorro escribió:Meter dos bytes a 0 con un "Copy /b". No me gusta demasiado porque hay que manipular la primera compilación, y es lo que quiero evitar, aunque al menos es menos complejo que mirar el tamaño y volver a recompilarlo.
Antes de utilizar Copy para sustituir integramente el archivo exe, prefiero tratarlo como lo hago :smt001 .
Y lo de mirar el tamaño y volver a recompilar....complejo????? Que dices tío, si es más sencillo. Recuerda que lo de mirar el tamaño solo se hace al principio compilando una vez y ya está :smt023 .
Ximorro escribió:Por cierto, yo tampoco guardo el valor si no ha cambiado, y además doy uno por defecto si aún no hay ninguno
Deacuerdo deacuerdo ..... :smt005 :smt005 .
Ximorro escribió:Por ahora creo que usaré mi método (quizás con el bat que espera a que se cierre el EXE, que es la ventaja que tiene tu vbs respecto a mi "CMD /C" inicial). Creo que mi versión es más simple para tener casi la misma funcionalidad (claro que aún me tengo que estudiar el vbs), ¡y además es mío!
El tuyo mejora el hecho de ir directo a leer los datos, quizás modifique el mío con eso del tamaño de los datos al final del EXE para no leer todo el archivo en una cadena.
Jejeje.....nada chico, aquí están los códigos, utiliza el que quieras :smt001 . Incluso puedes hacer una versión mejorada utilizando lo mejor de los dos :smt002 .
No te voy a negar que siempre nos inclinamos a los hechos por uno mismo cuando tiene casi la misma funcionalidad :smt003 . Eso nos pasa a todos.
De de que el tuyo es más simple para tener casi la misma funcionalidad.....mmmmmm....yo no lo veo así. El mío se complica por el archivo vbs pero nada más. Y porque se complica??? Pues porque reviso el proceso del exe, hago un bucle que no afecte mucho a los recursos del ordenador, hago algo de tratamiento de errores, no sustituyo simplemente el archivo por otro, sino que los trato directamente desde vbs.....hombre, yo creo que son muchas cosas más no? :smt005 .
Ximorro escribió:¿lo tienes por casualidad en un archivo a parte indentado para leer bien el código?
Una gran parte. Al final empecé a hacer pequeñas modificaciones directamente sobre el código AutoIt.
No te preocupes que yo te lo indento :smt002 .
Ximorro escribió:Hum, me he encontrado un problema, si una vez que tiene datos intento guardar una cadena vacía (no poner datos) da error... Creo que sería cosa de comprobarlo en el vbs, al hacer eso se dejaría el EXE como el original, sin datos.
Se me pasaría. Seguro que es una tontería. Luego lo miro y lo vuelvo a subir. Gracias por avisar compa :smt023 .
Ximorro escribió:Lo que menos me gusta es lo de mirar el tamaño para recompilar con el nuevo dato, por los problemas que te comentaba arriba.
Creo que con el tema que explico de recompilar te estás equivocando :smt017 . Te recuerdo que lo de recompilar es una vez, cuando ya tienes hecho el script, lo compilas con un tamaño aproximado (sabemos que va a tener un tamaño en bytes de 6 cifras), le miras los bytes que tiene el exe, cambias este dato y lo vuelves a compilar.......y ya está listo para usarse el exe. No le veo tanto trabajo :smt017 .
Ximorro escribió:aunque me gustaba mucho la idea del "CMD /C" por no sacar ningún archivo extra al temporal...
Jajajaja.....esa es otra de las grandes diferencias del tuyo al mío. Yo por desgracia tengo que crear y sacar el archivo vbs para ejecutarse. Se puede poner todo en una línea (sí, se puede :smt002 ), pero por desgracia el WScript.exe, que es el interprete de comandos solo lee los comandos en un archivo :smt013 .
Pero yo te digo una cosa......tú método no copia el bat pero hace una copia del exe que pienso que es peor, por lo menos en tamaño :smt003 . El mío apenas copia poco más de 2 kbytes del archivo vbs pero no hace copias del exe, ya que trabajo directamente sobre éste :smt016 .
Tenía una gran idea inial, que era la de meter el vbscript en un objeto IE oculto para que no se copiase absolutamente nada, pero tuve muchos problemas, y encima, como siempre, depender de que en la configuración del IE el usuario tenga activa la casilla de ejecución de script. Aunque casi todos la tenemos no? :smt005 .
Ximorro escribió:¡Enhorabuena por tu método!, es muy interesante ver otras posibilidades Ahora me tengo que estudiar ese vbs con la escritura binaria
Gracias hombre!!! Como te dije el tuyo está también muy bien. Seguramente el método del ping no se me hubiese ocurrido nunca :smt002 .
Estudia estudia....y si tienes dudas en algo pregunta :smt002 .

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Responder