Or maybe you can choose something more elegant: a private desktop for your app!
Check this:
LOCAL cMainPath, cMainFile
m.cMainPath = ADDBS (JUSTPATH (SYS (16,0)))
SET DEFAULT TO (m.cMainPath)
*! * // m.cMainFile = m.cMainPath + 'main.exe'
m.cMainFile = GETFILE ( 'EXE' , 'File (& F):' , 'OK' , 0, 'Please specify the program to run in the new desktop' )
IF !EMPTY(m.cMainFile)
RunInNewDesktop (m.cMainFile)
ENDIF
RETURN
FUNCTION RunInNewDesktop
LPARAMETERS tcMainFile AS String
#define GENERIC_ALL 0x10000000
#define DESKTOP_SWITCHDESKTOP 0x0100
#define NORMAL_PRIORITY_CLASS 0x00000020
#define INFINITE 0xFFFFFFFF
#define GMEM_FIXED 0x0000
#define GMEM_ZEROINIT 0x0040
DECLARE Long CreateDesktop IN WIN32API;
String lpszDesktop,; && // name of the new Desktop
Long lpszDevice,; && // Reserved; MUST be NULL.
Long pDevMode,; && // Reserved; MUST be NULL.
Long dwFlags,; && // flags to Control Interaction with other Applications
Long dwDesiredAccess,; && // specifies Access of returned handle
Long lpsa && // specifies Security Attributes of the Desktop
DECLARE Long GetThreadDesktop IN WIN32API Long dwThreadId
DECLARE Long SetThreadDesktop IN WIN32API Long hDesktop
DECLARE Long OpenInputDesktop IN WIN32API;
Long dwFlags,; && // flags to Control Interaction with other Applications
Long fInherit,; && // specifies WHETHER returned handle is inheritable
Long dwDesiredAccess && // specifies Access of returned handle
DECLARE Long SwitchDesktop IN WIN32API Long hDesktop
DECLARE Long CloseDesktop IN WIN32API Long hDesktop
DECLARE Long CreateProcess IN WIN32API;
Long lpApplicationName,; && // pointer to name of Executable module
String lpCommandLine,; && // pointer to command line String
Long lpProcessAttributes,; && // Process Security Attributes
Long lpThreadAttributes,; && // Thread Security Attributes
Long bInheritHandles,; && // handle inheritance Flag
Long dwCreationFlags,; && // Creation flags
Long lpEnvironment,; && // pointer to new Environment Block
Long lpCurrentDirectory,; && // pointer to current Directory name
String @ lpStartupInfo,; && // pointer to STARTUPINFO
String @ lpProcessInformation && // pointer to PROCESS_INFORMATION
DECLARE Long WaitForSingleObject IN WIN32API;
Long hHandle,; && // handle to Object to wait for
Long dwMilliseconds && // time-out interval in milliseconds
DECLARE Long CloseHandle IN WIN32API Long hObject
DECLARE Long GlobalAlloc IN WIN32API Long uFlags, Long dwBytes
DECLARE Long GlobalFree IN WIN32API Long hMem
DECLARE Long GetLastError IN WIN32API
LOCAL hOrgDesktop, hOrgInput, cNewdesktop, hNewDesktop, pDesktopName, cSI, cPI
* @ save the original desktop handle
m.hOrgDesktop = GetThreadDesktop (Application.ThreadId)
m.hOrgInput = OpenInputDesktop (0, 0, DESKTOP_SWITCHDESKTOP)
* @ Create and switch to a new desktop
m.cNewdesktop = 'desktop_' + SYS (2015)
m.hNewDesktop = CreateDesktop (cNewDesktop, 0, 0, 0, GENERIC_ALL, 0)
SetThreadDesktop (m.hNewDesktop)
SwitchDesktop (m.hNewDesktop)
* @ constructor CreateProcess structural parameters needed
*! * // typedef struct {// Si _STARTUPINFO
! * * // DWORD cb;
! * * // LPTSTR lpReserved;
! * * // LPTSTR lpDesktop;
! * * // LPTSTR lpTitle;
! * * // DWORD dwx;
! * * // DWORD DWY;
! * * // DWORD dwXSize;
! * * // DWORD dwYSize;
! * * // DWORD dwXCountChars;
! * * // DWORD dwYCountChars;
! * * // DWORD dwFillAttribute;
! * * // DWORD dwFlags;
! * * // WORD wShowWindow;
! * * // WORD cbReserved2;
! * * // LPBYTE lpReserved2;
! * * // HANDLE hStdInput;
! * * // HANDLE hStdOutput;
! * * // HANDLE hStdError;
*! * //} STARTUPINFO
m.pDesktopName = GlobalAlloc (GMEM_FIXED + GMEM_ZEROINIT, LEN (m.cNewdesktop) + 1)
SYS (2600, m.pDesktopName, LEN (m.cNewdesktop), m.cNewdesktop)
m.cSI = BINTOC (0, '4RS' ) + BINTOC (m.pDesktopName, '4RS' ) + REPLICATE (CHR (0), 14 * 4)
m.cSI = BINTOC (LEN (m.cSI) + 4, '4RS' ) + m.cSI
*! * // typedef struct {// PI _PROCESS_INFORMATION
! * * // HANDLE hProcess;
! * * // HANDLE hThread;
! * * // DWORD dwProcessId;
! * * // DWORD dwThreadId;
*! * //} PROCESS_INFORMATION
m.cPI = REPLICATE (CHR (0), 4 * 4)
* @ create a new process running in the new desktop, start the main thread of the new process
IF (0 == CreateProcess (;
0, m.tcMainFile + CHR (0), 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0,;
@ M.cSi, @ m.cPi))
MESSAGEBOX ( 'failed with error code execution' + TRANSFORM (GetLastError ()), 16, 'error message' )
ELSE
m.hProcess = CTOBIN (SUBSTR (m.cPI, 1, 4), '4RS' ) && // new process handle
m.hThread = CTOBIN (SUBSTR (m.cPI, 5, 4), '4RS' ) && // main thread handle
CloseHandle (m.hThread)
WaitForSingleObject (m.hProcess, INFINITE) && // wait until the process exits
CloseHandle (m.hProcess)
ENDIF
* @ clean up the environment
GlobalFree (m.pDesktopName) && // release allocated memory block
SwitchDesktop (m.hOrgInput) && // switch back to the original desktop
SetThreadDesktop (m.hOrgDesktop)
CloseDesktop (m.hNewDesktop)
ENDFUNC