Launch an executable without using Shell on Console target

Hi all!

I’m looking for a way to launch an executable (along with some parameters) from a console/service application on Windows (and maybe Linux). Simple as that!

The catch is that I want my app to launch it and then forget about it, so I can’t use Shell, as it would require the Shell object to remain in scope for the entire lifetime of the called application. And I can’t have that.

This is possible with FolderItem.Open on the Desktop, but why is it not implemented on the Console target?

Any way to do it?

Thanks

Register the console program as a one - time service on Linux, and then use the shell to start the service

var s as new shell
s.Execute(“systemctl restart your.service”)

Thanks, but I need this primarily on Windows.
Plus, I suspect I’d need superuser permission to do that, which is not something I’ll be necessarily having.

folderitem.open doesn’t exist?

Folderitem.Open is Desktop-only for some reason that is beyond me

Create a feature request perhaps ?

The catch is that I want my app to launch it and then forget about it, so I can’t use Shell, as it would require the Shell object to remain in scope for the entire lifetime of the called application. And I can’t have that.

So you want a detached windows process, the just use shell, since windows doesn’t hold a parent process…:wink:

Var sh As New Shell
sh.ExecuteMode = Shell.ExecuteModes.Synchronous
sh.Execute("path/to/exe --param1")
if sh.ExitCode = 0 Then
// process lauched, let it go out of scope it will keep running.. on windows atleast
else
// Process failed to launch
end if
// let it go out of scope, here it should be kept running check taskmgr.exe
1 Like

Consider of a process that takes a couple of hours to complete.
The way I understand it, starting it through a Shell in Synchronous mode will just freeze my application until the external process has completed.
I will not get the sh.ExitCode immediatelly after the sh.Execute. I think I’m not getting this wrong :slight_smile:

On windows you can set the shell.timeout = 1 if you don’t want to know the actual exitcode…
Say you just want to launch the process and forget about it … then …

Var sh As New Shell
sh.ExecuteMode = Shell.ExecuteModes.Synchronous
sh.timeout = 1 // Timeout shortly (milliseconds)
sh.Execute("path/to/exe --param1")
// let it go out of scope, here it should be kept running check taskmgr.exe

Try it… please you’ll be enlightened more about what you want to do with the flow.

It could be “freezing” i don’t actually know that (but since the timeout is specifically for windows you may want to use that).

Or create a subclass that just has the events you want but put the result in shared method/property so you just ignore the data etc. you may nil it later since there is no actual parent locked to the child (on windows).

Hey, thanks, I’ll give it a try later in the evening. Just for the possibility of being enlightened :slight_smile:

1 Like

I’ve got good news and bad news, but overall bad.

The good news is that the application being called does not terminate after the shell object goes out of scope, in contrast to what the documentation says.

The bad news is that the launched application is not completely independent: it terminates once the application that called it terminates.

So, I learned something new today, but I still have the problem: the “child” process cannot, in any way, depend on the “parent” process.

other ideas?

In Windows if you create a BATCH file you can launch anything from there and should be independent of who launched it.

1 Like

Just searched my test code folder (thanks arbed) and found this, it might help, launches notepad and allows it to stay running after our app has closed:

Declare Function CreateProcessW Lib "Kernel32.dll" Alias "CreateProcessW" ( _
lpApplicationName As WString, _
lpCommandLine As WString, _
lpProcessAttributes As Ptr, _
lpThreadAttributes As Ptr, _
bInheritHandles As Int32, _
dwCreationFlags As UInt32, _
lpEnvironment As Ptr, _
lpCurrentDirectory As Integer, _
lpStartupInfo As Ptr, _
lpProcessInformation As Ptr _
) As Int32

Declare Function GetLastError Lib "Kernel32.dll" () As UInt32

Dim startupInfo As MemoryBlock
Dim processInfo As MemoryBlock
startupInfo = New MemoryBlock(68)
startupInfo.Long(0) = startupInfo.Size
processInfo = New MemoryBlock((2 * COM.SIZEOF_PTR) + 4 + 4) 'two pointers and two dwords, quick and dirty

Dim i As Int32
i = CreateProcessW("C:\Windows\notepad.exe", "", Nil, Nil, 0, 0, Nil, 0, startupInfo, processInfo) 

Dim e As UInt32
e = GetLastError()

Command line goes in the empty ""

Someone else can chip in the linux help :wink:

1 Like

linux use “disown”

Did you create the application yourself that is being called, e.g. the child process?

It could be checking if the parent ended inside the application…

Hey, sorry for disappearing, had to do a bit of a context switch for a few days! Just like threads! :slight_smile:

Thanks for your input! I will try everything you suggested when I get back to the Xojo context!
@LangueR for the batch files
@JulianS for the declare
@Vigia_Lin for what I will undoubtedly find useful when I do the linux version
@DerkJ for the trick with the shell timeout!
I’m not sure what you mean on your last post though. If I’ve written the application myself?
Yes, I have. It’s just a console app that prints something on the debug log every second without any exit conditions. Just as a test.