Problema muy extraño con ShellEjecute

Iniciado por RiasChan, 20 Marzo 2020, 02:28 AM

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

Serapis

Citarpero si selecciono de nuevo el archivo y una vez vuelto a seleccionar  (obviamente la ruta no cambia ni se modifica a la vista, es exactamente la misma) si anda el ejecutador de mi programa... con solo volver a seleccionar lo mismo

El tema es que lo que selecciono es un bat, entonces en realidad el shell si lo ejecuta, pero se cierra rapidamente, como si fallara algo interno del bat, pero lo tan extraño que destaco, es que simplemente volviendo a cargar manualmente (con mi boton examinar) el archiv bat, si anda. Y la ruta no se modifica.

Es mas, en la linea anterior a ejecutar el shellejecute, puse un msgbox para que muestre al path del programa, y en ambos casos (cuando restauro el preset desde la base de datos, o seleccionado ahi mismo sin usar el recorset) el path es exactamente el mismo y no hay una / de menos o de mas o : o esas cosas..

que podrá ser?
Hablas de un modo inconcreto. No se puede adivinar que falla en un programa que falla, así, sin más.

Luego pones un vídeo (que no voy a ver), en vez de simplemente hacer un copypaste de texto, con el contenido del bat... y el contenido del código que hace la llamada al bat. Es rápido, es fácilmente consultable y se puede repasar cuantas veces sea preciso de forma rápida (un vídeo exige volver a verlo todo de nuevo y se pierde mucho tiempo con ello).

Si haces esto último marcado en negrita, pués se le podrá echar un vistazo rápido...

RiasChan

#11
Esto pone el Path del archivo en el TXT Path:

Dim cadenita
Dialogo.ShowOpen
txtPath.Text = Dialogo.FileName
txtSucia.Text = Dialogo.FileTitle
cadenita = Len(txtPath.Text)
If cadenita > 255 Then
MsgBox "La ruta de este programa es demasiado lejana, debe seleccionar una ruta más corta de destino", vbCritical
txtPath.Text = ""
Exit Sub
End If
c_var = 0


Cadenita es un simple método para que el cliente no me selecicone algo en la ultima subcarpeta del nucleo de system32 con 3000 subcarpetas previas.

txtsucia guarda el EXE, por que se usa para otra funcion del programa que no tiene problemas.

Si yo ahi le doy Play anda, anda con el ShellExecute:

Private Declare Function ShellExecute Lib "shell32.dll" Alias _
   "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
   ByVal lpFile As String, ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
   
'---------- El boton Play:

ret = ShellExecute(Me.hwnd, "Open", txtPath, "", "", 3)


Ya ahi anda, sin problemas, el bat y lo que sea.

Luego este boton, Guarda los TXT en una base de datos:

Private Sub EntradaPreset()
   Dim rs As ADODB.Recordset
       If Not Conectar() Then Exit Sub
       Set rs = New ADODB.Recordset
           rs.Open ("Preset"), cn, adOpenKeyset, adLockOptimistic
           rs.AddNew
           rs!codigo = lblCodigoPreset
           rs!nombre = txtPreset
           rs!Path = txtPath
           rs!exenames = txtSucia
           rs.Update
           Set rs = Nothing
           Call contadorPreset
           Desconectar
End Sub


ContadorPreset es un bucle que guarda en otro registro un numero de codigo para no mezclar los registros de la BD


Luego, cargas esa preset desde el otro boton:

Private Sub LlamadaDeDatos()
Dim rs As ADODB.Recordset
Dim sql As String
If Not Conectar() Then Exit Sub
Set rs = New ADODB.Recordset
sql = "Select * FROM Preset WHERE nombre = '" + cboPreset.List(cboPreset.ListIndex) + "'"
rs.Open (sql), cn, adOpenKeyset, adLockOptimistic ' abre rs
txtPath.Text = ""
txtPath.Text = rs!Path
txtSucia.Text = rs!exenames
End If
Set rs = Nothing
Desconectar

end sub


Y le das play, con el primer ShellExecute, y anda con todos los archivos, excepto con el Bat Con el bat se cierra la ventana DOS al cargar los datos del Bat. El bat tiene esto:

setx GPU_FORCE_64BIT_PTR 0
setx GPU_MAX_HEAP_SIZE 100
setx GPU_USE_SYNC_OBJECTS 1
setx GPU_MAX_ALLOC_PERCENT 100
setx GPU_SINGLE_ALLOC_PERCENT 100
EthDcrMiner64.exe -epool us2.ethermine.org:4444 -ewal 0x8cce0e45e02439fe85f35b2235.MineraHanswellRX5epsw x -mport 0 -showdiff 1 -showpower 1 -dbg -1 -rxboost 0



Ahora, si desde el Examinar primero de todos que abre el CommonDialog, vuelves a seleccionar el archivo.bat (ya cargada la preset y con la falla) ... anda y no falla
, empieza a usar el bat sin problemas.

Tiene un par de cosas extrañas en los recordesets, pero si se consdidera que el ShellExecute toma la ruta completa y sin espacios ni carcateres ni barras de mas ni de menos, idénticos y funciona... pero no quiere funcionar con el bat... creo que el problma es algo del bat. Pero tampoco cuadara por que si se hace ese remedio casero si funciona... What Te FuAkckk




Serapis

Bueno, solo he mirado (de momento) el primer parrafo.
Contienes un grave error...

Aunque revisas que el usuario no haya elegido un path inaccesible, no revisas que haya cancelado.
Si cancela, txtPath.Text, Dialogo.FileName, txtSucia.Text y Dialogo.FileTitle quedan con valor "".

Se puede preguntar por si están vacíos, pero es más cómodo tratarlo como un error.
Te pongo ese párrafo para solucionar ese caso, cuando revises que a pesar de ello te siguiere dando error, pués se revisa el resto del código.

Código (VB) [Seleccionar]

Private Function SeleccionaFile() As Boolean
    Dim cadenita
   
    With Dialogo
        .DialogTitle = "Elija un fichero ejecutable..."
        .Filter = "Ejecutables (.exe .com .vbs)|*.exe;*.com;*.vbs|Exe (.exe)|*.exe|Com (.com )|*.com|VB Script (.vbs)|*.vbs" ' ...etc...
        .CancelError = True
        On Error GoTo Cancelado
        .ShowOpen
       
        txtPath.Text = .FileName
        txtSucia.Text = .FileTitle
    End With
   
    cadenita = Len(txtPath.Text)
    If cadenita > 255 Then
        MsgBox "La ruta de este programa es demasiado lejana, debe seleccionar una ruta más corta de destino", vbCritical
        txtPath.Text = ""
        Exit Function
    End If
   
    SeleccionaFile = True
    Exit Function
Cancelado:
    If (Err.Number = 32755) Then
        MsgBox "el usuario ha cancelado la eleccion de fichero..."
        ' hacer lo que corresponda a este caso... tipicamente no hacer nada al devolver.
    Else
        Call MsgBox("Ocurrio un error inesperado..." & CStr(Err.Number), , "Dialogo de seleccion de fichero")  ' no se espera que esto suceda... pero si alguna vez ocurre, al reportar el mensaje, hay por donde indagar...
    End If
End Function



' ... despues... en la llamada

if (SeleccionaFile = TRUE) then
  '... se invoca lo que sea que haces...
else
  ' pero si devuelve false, es lo mismo que si el usuaro no hubiera realizado ninguna accion
end if



Por cierto, como dices que invocas un ejecutable, imagino que el control 'Commondialog' tiene filtrado para elegir solo ficheros ejecutables, no???. Que has establecido algún valor en las propiedades 'Filter'. Sino el usuario podría elegir cualquier cosa... he puesto un filter de ejemplo...

RiasChan

Amigo perdon que te responda asi, pero creo que no me comprendes.No uso el CommonDialog para cargar la preset, El shellExecute lee desde un TXT, que está ahí, legible, y si copias y pegas manualmente y lo abres, peus abre el bat, pero el shellexecute no lo hace. En el momento que falla, es completamente independiente del CommonDialog.

Lo mas triste es que cuando si uso el commond dialog  si anda.

El único problema que tiene es que cuando cargas la preset, y le das play ahi no lee los bat. Solo los bat. En primera instancia desde el commond dialog (y sin tener la modificacion que me diste) tampoco tira error y anda bien- (Seguramente lo haga si el usuario pone cancelar... Aunque tampoco quedaria texto en el txtpath, por lo cual ya salteria con mi cartel de error propio al dar play al programa...

No entiendo que relación puede tener el ShellExecute con el CommonDialog, ya que el ShellEjexute usa un txt para cargar la referencia y usar el programa, no el CommonDialog, y la direccion traida por el CommondDialog al TXtpath esta correcta.

Y no no hay filtro, el programa trae y ejecuta cualquier cosa. Ya probe fotos musica, lo que sea, y lo abre con el programa asociado predetermiandamente.

De hecho trae y ejecuta todo correctamente

Serapis

Ok, te entiendo.

Si cuentas que el programa funciona correctamente de un modo pero no cuando tomas el mismo path, y lo pasas al shellexecute, las dos posibilidades más inmediatas son:
A - Problema con la redefinición del string pasado al shell execute.
B - Problemas de permisos sea del usuario o de la carpeta donde yace el fichero. Esto último e smás dependiente del S.O. que del programa, si el usuario toma los permisos adecuados o ejecuta el programa con permisos de administrador...

Incluso aún siendo esto último, por orden (si fuera el caso) procede examinar primero que el string recibido se pase correctamente a sehllexecute.

Seguiré leyendo tu mensaje previo para ver si aparece el código donde quede recogido dicha llamada y si aparece el contenido de uno de esos txt, donde conste la ruta, para dilucidar el posible problema.

...a la noche saco un ratito, lo reviso y te comento.

Serapis

CitarSi yo ahi le doy Play anda, anda con el ShellExecute:

Private Declare Function ShellExecute Lib "shell32.dll" Alias _
    "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
    ByVal lpFile As String, ByVal lpParameters As String, _
    ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
   
'---------- El boton Play:

ret = ShellExecute(Me.hwnd, "Open", txtPath, "", "", 3)

Ya ahi anda, sin problemas, el bat y lo que sea.
Luego este boton, Guarda los TXT en una base de datos:
...
ContadorPreset es un bucle que guarda en otro registro un numero de codigo para no mezclar los registros de la BD
Luego, cargas esa preset desde el otro boton:
...
Y le das play, con el primer ShellExecute, y anda con todos los archivos, excepto con el Bat Con el bat se cierra la ventana DOS al cargar los datos del Bat....
El caso es que al final no veo ningún string con las rutas que fallan y con las rutas que funcionan...
El contenido del bat, carece de importancia, lo mismo que carecería de importancia el contenido de un txt, o de una imagen, lo que dices que falla es la apertura.


Aísla la llamada a una función como esta (a fin de ver que rutas recibe y que errores genera).
Código (vb) [Seleccionar]

Private Sub Ejecutar(ByRef Comando As String, ByRef Orden As String)
    Static contador As Long
    Const HANDLE_INSTANCIA As Long = 32

    Debug.Print contador ; comando;
    contador  = (contador  + 1)

    ret = ShellExecute(Me.hwnd, orden, comando, "", "", 3)

    If (ret <= HANDLE_INSTANCIA) Then
        Debug.Print " FALLO: " & ret
    Else
        Debug.Print
    End If
End Sub


que se llamaría así:
Código (vb) [Seleccionar]
call ejecutar(txtpath, "Open")

Ejecuta varias veces con los que funcionan y con los que no... haz luego una captura a la ventana debug ( y la subes a alguna web y la pones aquí), con las rutas y los valores de error, podrá determinarse qué sucede.
si además muestras la misma salida cuando dices que las ejecutas llamadas desde el commondialog, mejor que mejor, porque así podrá compararse las diferencias entre ambos paths.

BlackZeroX

Me dio un poco de pereza leer las respuestas chonchas...

Pero me suena que es tema de primero ubicarte en el path de ejecucion y luego ejecutarlo. por lo que entendi Tu haces esto:

cargas el archivo y ejecutas

y si intentas

cargas el archivo -> te ubicas en el path -> Ejecutas

* Cargar el archivo no es ubicarte en la ruta...

Saludos.
The Dark Shadow is my passion.

RiasChan

Hola, luego de enfriarme otros 30 dia, retomé esto y ya está la la causa (encontrada).

Resumen: El problema está al ejecutar directamente un archivo Bat (desconzoco si todos o solo ese) desde el ShellExecute. Me di cuenta por que decidí buscar archivos con los controles viejos Drive/Dir/file. Y éstos 3 me dejan en el txtPath literalmente  la ruta seleccionada, que termina en .LNK (yo el bat ese lo abro con un acceso directo). Entonces, tanto al instante de crearlo como al guardar y restaurar la preset, siempre es el LNK y al ejecutar el acceso directo funciona en todos los casos.

Pero el CommonControls, al poner un acceso directo ya me pone el vinculo directo en el txtpath, y de ahi todos los problemas de antes.

Ahora ¿¿por que??

En defnitiva, el problema está en el ShellExecute, o el método que use, al ejecutar directamente el BAT. Incluso ejectuando el accesodirecto que da al bat anda, pero el BAT en sí no... jamas vi algo tan extraño.