I have finally managed to program what i described/asked for. The following .onInit function will check if the newly launched installer (if mutex fails) is a subprocess (the language has been chosen in UMUI) or if it is a new process (another instance of the installer has been launched).
Function .onInit
!insertmacro UMUI_MULTILANG_GET
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "MutexA") ?e'
Pop $R0
${IfNot} 0 = $R0
# MutexA already exists!
# Now the choice has to be made:
# 1) another installer lauch (new process)
# 2) language selection in UMUI (subprocess)
# First get the process id of the current process and store it in $R0
System::Call "kernel32::GetCurrentProcessId() i .R0"
# Then create a snapshot of all running processes
System::Call "kernel32::CreateToolhelp32Snapshot(i 0x00000002, i 0) i .r0"
# And prepare the PROCESSENTRY32 structure
System::Call "*(i, i, i, i, i, i, i, i, i, &t1024) i .r1"
# Get the size of the PROCESSENTRY32 structure
System::Call "*$1(_, &l0 .r2)"
# Set the size of the PROCESSENTRY32 structure in its first member (as required)
System::Call "*$1(i r2, i, i, i, i, i, i, i, i, &t1024)"
# Retrieve the information about the first process
System::Call "kernel32::Process32First(i r0, i r1) i .r2"
# Loop as long as the call is successful (TRUE)
${DoWhile} 1 = $2
# Retrieve the members "process id" in $R1 and "parent process id" in $R2
System::Call "*$1(i, i, i .R1, i, i, i, i .R2, i, i, &t1024)"
# Check if the current process and the one just looking at in the snapshot have the same id
${If} $R0 = $R1
# If they so exit the loop
${Break}
${EndIf}
# If they do not retrieve the information about the next process
System::Call "kernel32::Process32Next(i r0, i r1) i .r2"
${Loop}
# Free the created structure
System::Free $1
# Release the snapshot
System::Call "kernel32::CloseHandle(i r0)"
# Now we have stored:
# $R0: the current process id
# $R1: the process id of the process we last looked at in the snapshot
# $R2: the parent process id of the process we last looked at in the snapshot
# If $R0 = $R1 (what we hope for) than $R2 is the process id of the parent process of the current one
# Inistialisations
StrCpy $0 0
StrCpy $1 0
# Loop until we find some exist condition in the loop code
${Do}
# Get the first/next NSIS window handle
FindWindow $0 "#32770" "" 0 $0
# If the found handle is 0 or if $R0 != $R1 we have to abort
${If} 0 = $0
${OrIfNot} $R0 = $R1
# If we didn't find the main installer window, we show an error message
${If} 0 = $1
MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running!"
# If we did find the main installer window, we make it the foreground window
${Else}
System::Call "user32::ShowWindow(i r1, i 9)"
System::Call "user32::SetForegroundWindow(i r1)"
${EndIf}
Abort
# We found an NSIS installer
${Else}
# We get its window title
System::Call "user32::GetWindowText(i r0, t .r2, i 1024) i .r3"
# We strip the NULL character at the end
IntOp $3 $3 - 1
StrCpy $2 $2 $3
# If it is the same as the one of this installer, we might have found the parent
# or we discover its a new one
# Here you need to change "$(^Name) Setup" if you changed the caption of the installer
${If} "$(^Name) Setup" == $2
# Get the process id from the window handle
System::Call "user32::GetWindowThreadProcessId(i r0, *i .r2)"
# If it is the same as the one of our parent, than the language was chosen and we break the loop
${If} $2 = $R2
${Break}
# If it is not the same, than we store the window handle (of the first one discovered;
# normally there is only one) to be used later on to set that window to the foreground
${ElseIf} 0 = $1
StrCpy $1 $0
${EndIf}
${EndIf}
${EndIf}
${Loop}
${EndIf}
FunctionEnd
Best Regards,
Yves