B4J Question How to set process name with B4JPackager11? [SOLVED]

jmon

Well-Known Member
Licensed User
Hello,

With the previous version of B4JPackager (Java8), the process name had the same name as the executable (i.e. my executable was named MyGame.exe, the process in Windows process manager was named MyGame.exe).

With B4JPackager11, the process is named javaw.exe, regardless of my executable name. Is there a way to change the name of the process?

Thank you for the support!

Edit: for info, the problem that this causes, is that I cannot use this function anymore:
https://www.b4x.com/android/forum/threads/singleton-and-process-functions.61381/#content
And setting the searched process name to javaw.exe would be too broad I guess

Edit: Solved HERE
 
Last edited:

jmon

Well-Known Member
Licensed User
At the moment, I haven't found how to change the application process name, but I found a solution that fits my needs (Singleton) and works with B4JPackager11:

EDIT2: See the next solution POST #3 for a correct answer (This one always return false since it counts this process as existing)
B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
 
    Wait For(SingleInstance("")) Complete (Singleton As Boolean)
    Log($"Is my app already running: "$ & Singleton)
 
End Sub

'Returns true if the provided package name is not found.
'PackageName: If empty, the function with use the current package name.
Sub SingleInstance(PackageName As String) As ResumableSub
    If PackageName = "" Then
        Dim joPKG As JavaObject
        joPKG.InitializeStatic("anywheresoftware.b4a.BA")
        PackageName = joPKG.GetField("packageName")
    End If
    Dim wmic As Shell
    wmic.InitializeDoNotHandleQuotes("wmic", "wmic.exe", Array As String("PROCESS"))
    wmic.Run(20000)
    Wait For wmic_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success Then
        Return Not(StdOut.ToLowerCase.Contains(PackageName.ToLowerCase))
    Else
        Return True
    End If
End Sub
That works because with B4JPackager11 the app appears to be ran via command line and appear like this in wmic.exe:
javaw.exe "C:\Program Files\MyApp\bin\javaw.exe" @release_java_modules.txt -m b4j/b4j.example.main ...
You can leave the package name empty if you want, the function will determine this app package name automatically, or you can pass another package name.

EDIT: Note that this will ONLY work when the application is compiled with B4JPackager, it will not work in the IDE!
 
Last edited:

jmon

Well-Known Member
Licensed User
Update:
This is better for what I need, this function counts the number of app with my package name running and close if there is more than 1:
B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show

    Wait For(PackageCount("")) Complete (Count As Int)
    Log($"Count of my app running: "$ & Count)
    If Count > 1 then ExitApplication
   
End Sub

'Returns the number of packages found.
'PackageName: If empty, the function with use the current package name.
Sub PackageCount(PackageName As String) As ResumableSub
    Dim Count As Int = 0
    If PackageName = "" Then
        Dim joPKG As JavaObject
        joPKG.InitializeStatic("anywheresoftware.b4a.BA")
        PackageName = joPKG.GetField("packageName")
    End If
    Dim wmic As Shell
    wmic.InitializeDoNotHandleQuotes("wmic", "wmic.exe", Array As String("PROCESS"))
    wmic.Run(20000)
    Wait For wmic_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success Then
        Dim Match As Matcher  = Regex.Matcher2(PackageName, Regex.CASE_INSENSITIVE, StdOut)
        Do While Match.Find
            Count = Count + 1
        Loop
        Return Count
    Else
        Return 0
    End If   
End Sub
 

jmon

Well-Known Member
Licensed User
It shouldn't be too difficult to change the process name. Change the value of FileName in BuildRunner sub and then change the name of javaw.exe under the bin folder.
That works very well, and it was easy to do. This is the updated BuildRunner to make the application process name correct in windows:
B4X:
Private Sub BuildRunner As ResumableSub
    If Windows Then  
        Dim FileName As String = ExeName
        Dim target As String = "winexe"
        Dim output As String = ExeName
        File.WriteString(TempFolder, "runner.cs", $"
   
using System;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
namespace B4JRunner
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();
            p.StartInfo.FileName = "${FileName}";
            p.StartInfo.WorkingDirectory = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
            p.StartInfo.Arguments = "@release_java_modules.txt -m ${TargetModule}/${PackageName}.main";
            foreach (string a in args)
                p.StartInfo.Arguments += " " + "\"" + Regex.Replace(a, @"(\\+)$", @"${"$1$1"}") + "\"";
            p.Start();
        }
    }
}"$)
        If IconFile = "" Then
            File.Copy(File.DirAssets, "icon.ico", TempFolder, "icon.ico")
        Else
            File.Copy(IconFile, "", TempFolder, "icon.ico")
        End If
        Wait For (RunShell(True, NetFrameworkCSC , Array($"/target:${target}"$, "/win32icon:icon.ico", $"/out:build\${output}"$, "runner.cs"))) complete (output As String)
        File.WriteString(TempFolder, "build\run_debug.bat", $"
    cd bin
java.exe @release_java_modules.txt -m ${TargetModule}/${PackageName}.main
pause
"$)
        File.Copy(File.Combine(TempFolder, "build/bin"), "javaw.exe", File.Combine(TempFolder, "build/bin"), ExeName)

    Else
        File.WriteString(TempFolder, "build/run.command", $"#!/bin/bash
cd -- "${"$"}(dirname -- "${"$"}BASH_SOURCE")"
cd bin
./java @release_java_modules.txt -m ${TargetModule}/${PackageName}.main
exit 0
 "$)
        Dim jo As JavaObject
        jo.InitializeNewInstance("java.io.File", Array As String(File.Combine(TempFolder, "build/run.command")))
        jo.RunMethod("setExecutable", Array As Object(True, False))      
    End If
    Return True
End Sub
(Note: I didn't rename javaw.exe to the Exename, I just copied it. I figured one could need javaw.exe for other purposes.)
That could be a permanent addition to B4JPackager11.
 
Top