<?xml version="1.0" encoding="utf-8"?>
<Application>
	<AppTitle>Untitled Application</AppTitle>
	<AppShortName>MyApp</AppShortName>
	<Author>Author name</Author>
	<Version>1.0</Version>
	<DesignDeviceName>Desktop</DesignDeviceName>
	<VariablesScanned>False</VariablesScanned>
	<PageWidth>800</PageWidth>
	<PageHeight>600</PageHeight>
	<AutoSizeWidth>False</AutoSizeWidth>
	<AutoSizeHeight>False</AutoSizeHeight>
	<HideScrollbars>False</HideScrollbars>
	<ResponsiveSize>False</ResponsiveSize>
	<PublishPlatform>WebApp</PublishPlatform>
	<EmptyBuildFolder>False</EmptyBuildFolder>
	<WebBuildTarget>C:\Users\EDO\Documents\Desktop\nwjs-sdk-v0.88.0-win-x64\package.nw</WebBuildTarget>
	<AppIcon>C:\Users\EDO\Documents\VisualNeoWeb\Libraries\img\default-icon.png</AppIcon>
	<LanguageCode>en</LanguageCode>
	<DisplayMode>standalone</DisplayMode>
	<ServiceWorker>Offline page</ServiceWorker>
	<IsNWJS>True</IsNWJS>
	<ThemeColor>#000000</ThemeColor>
	<PwaScope>/</PwaScope>
	<MobileOSTypes>[AndroidOS,iOS,WindowsPhoneOS]</MobileOSTypes>
	<WindowState>normal</WindowState>
	<TitleBar>True</TitleBar>
	<Sizeable>True</Sizeable>
	<MaximizeBtn>False</MaximizeBtn>
	<MinimizeBtn>True</MinimizeBtn>
	<SystemMenu>True</SystemMenu>
	<ContextMenu>False</ContextMenu>
	<AlwaysOnTop>False</AlwaysOnTop>
	<ShowInTaskbar>True</ShowInTaskbar>
	<SingleInstance>False</SingleInstance>
	<ChromeKioskMode>False</ChromeKioskMode>
	<Components>
		<FunctionList name="Subroutines">
			<Components>
				<Function name="starter">
					<Code>BeginJS
const { spawn, execSync } = require(&apos;child_process&apos;);
const path = require(&apos;path&apos;);
const fs = require(&apos;fs&apos;);

const currentDir = process.cwd();

function isProcessRunning(pid) {
    try {
        process.kill(pid, 0);
        return true;
    } catch (err) {
        return false;
    }
}

function terminateProcess(pid) {
    try {
        process.kill(pid, &apos;SIGTERM&apos;);
    } catch (err) {
        console.error(&apos;Error terminating process with PID&apos;, pid, &apos;:&apos;, err.message);
    }
}

function startPhpCgi() {
    const phpDir = path.join(currentDir, &apos;php&apos;);
    if (!fs.existsSync(phpDir)) {
        console.log(&apos;PHP directory does not exist. Skipping PHP-CGI startup.&apos;);
        return;
    }

    const phpPidFile = path.join(phpDir, &apos;php.pid&apos;);
    if (fs.existsSync(phpPidFile)) {
        const phpPid = parseInt(fs.readFileSync(phpPidFile, &apos;utf8&apos;).trim(), 10);
        if (phpPid &amp;&amp; Number.isInteger(phpPid) &amp;&amp; isProcessRunning(phpPid)) {
            console.log(&apos;PHP-CGI process is already running with PID&apos;, phpPid);
            return;
        } else {
            fs.unlinkSync(phpPidFile);
        }
    }

    const phpCgiPath = path.join(phpDir, &apos;php-cgi&apos;);
    const phpCgiProcess = spawn(phpCgiPath, [&apos;-b&apos;, &apos;127.0.0.1:9000&apos;, &apos;-c&apos;, path.join(phpDir, &apos;php.ini&apos;)]);
    fs.writeFileSync(phpPidFile, phpCgiProcess.pid.toString());

    phpCgiProcess.on(&apos;exit&apos;, (code, signal) =&gt; {
        console.log(`PHP-CGI process exited with code ${code} and signal ${signal}`);
    });

    phpCgiProcess.on(&apos;error&apos;, (err) =&gt; {
        console.error(&apos;Error spawning PHP-CGI process:&apos;, err);
    });
}

function startNginx() {
    const nginxDir = path.join(currentDir, &apos;nginx&apos;);
    if (!fs.existsSync(nginxDir)) {
        console.log(&apos;Nginx directory does not exist. Skipping Nginx startup.&apos;);
        return;
    }

    const nginxPidFile = path.join(nginxDir, &apos;logs&apos;, &apos;nginx.pid&apos;);
    if (fs.existsSync(nginxPidFile)) {
        const nginxPid = parseInt(fs.readFileSync(nginxPidFile, &apos;utf8&apos;).trim(), 10);
        if (nginxPid &amp;&amp; Number.isInteger(nginxPid) &amp;&amp; isProcessRunning(nginxPid)) {
            console.log(&apos;Nginx master process is already running with PID&apos;, nginxPid);
            startPhpCgi();
            return;
        } else {
            fs.unlinkSync(nginxPidFile);
        }
    }

    const nginxPath = path.join(nginxDir, &apos;nginx&apos;);
    const nginxProcess = spawn(nginxPath, [&apos;-p&apos;, &apos;./nginx&apos;, &apos;-c&apos;, path.join(nginxDir, &apos;conf&apos;, &apos;nginx.conf&apos;)]);

    nginxProcess.on(&apos;exit&apos;, (code, signal) =&gt; {
        console.log(`Nginx process exited with code ${code} and signal ${signal}`);
    });

    nginxProcess.on(&apos;error&apos;, (err) =&gt; {
        console.error(&apos;Error spawning Nginx process:&apos;, err);
    });

    startPhpCgi();
}

startNginx();
EndJS</Code>
				</Function>
				<Function name="ender">
					<Code>BeginJS
const { execSync } = require(&apos;child_process&apos;);
const path = require(&apos;path&apos;);
const fs = require(&apos;fs&apos;);

const currentDir = process.cwd();

function isProcessRunning(pid) {
    try {
        process.kill(pid, 0);
        return true;
    } catch (err) {
        return false;
    }
}

function terminateProcess(pid) {
    try {
        process.kill(pid, &apos;SIGTERM&apos;);
    } catch (err) {
        console.error(&apos;Error terminating process with PID&apos;, pid, &apos;:&apos;, err.message);
    }
}

function stopPhpCgi() {
    const phpDir = path.join(currentDir, &apos;php&apos;);
    if (!fs.existsSync(phpDir)) {
        console.log(&apos;PHP directory does not exist. Skipping PHP-CGI termination.&apos;);
        return;
    }

    const phpPidFile = path.join(phpDir, &apos;php.pid&apos;);
    if (fs.existsSync(phpPidFile)) {
        const phpPid = parseInt(fs.readFileSync(phpPidFile, &apos;utf8&apos;).trim(), 10);
        if (phpPid &amp;&amp; Number.isInteger(phpPid) &amp;&amp; isProcessRunning(phpPid)) {
            console.log(&apos;Terminating PHP-CGI process with PID&apos;, phpPid);
            terminateProcess(phpPid);
        } else {
            console.log(&apos;PHP-CGI process is not running.&apos;);
        }
    } else {
        console.log(&apos;PHP-CGI PID file does not exist.&apos;);
    }
}

function stopNginx() {
    const nginxDir = path.join(currentDir, &apos;nginx&apos;);
    if (!fs.existsSync(nginxDir)) {
        console.log(&apos;Nginx directory does not exist. Skipping Nginx termination.&apos;);
        return;
    }

    const nginxPidFile = path.join(nginxDir, &apos;logs&apos;, &apos;nginx.pid&apos;);
    if (fs.existsSync(nginxPidFile)) {
        const nginxPid = parseInt(fs.readFileSync(nginxPidFile, &apos;utf8&apos;).trim(), 10);
        if (nginxPid &amp;&amp; Number.isInteger(nginxPid) &amp;&amp; isProcessRunning(nginxPid)) {
            console.log(&apos;Stopping Nginx process with PID&apos;, nginxPid);
            try {
                execSync(`${path.join(nginxDir, &apos;nginx&apos;)} -s stop -p ${nginxDir}`);
            } catch (err) {
                console.error(&apos;Error stopping Nginx process:&apos;, err.message);
            }
        } else {
            console.log(&apos;Nginx master process is not running.&apos;);
        }
    } else {
        console.log(&apos;Nginx PID file does not exist.&apos;);
    }
}

stopNginx();
stopPhpCgi();
EndJS</Code>
				</Function>
			</Components>
		</FunctionList>
		<LibraryList name="Libraries"/>
		<PageList name="Main">
			<Components>
				<Page id="NewPage">
					<style>background-color:#1F425E</style>
					<Components>
						<PushButton id="PushButton1">
							<left>248px</left>
							<top>536px</top>
							<width>136px</width>
							<height>48px</height>
							<caption>starter</caption>
							<click>starter</click>
						</PushButton>
						<PushButton id="PushButton2">
							<left>400px</left>
							<top>536px</top>
							<width>136px</width>
							<height>48px</height>
							<caption>ender</caption>
							<click>ender</click>
						</PushButton>
						<Paragraph id="Paragraph1">
							<left>0px</left>
							<top>0px</top>
							<width>800px</width>
							<height>504px</height>
							<style>color:#FFFFFF;font-size:11pt;padding-bottom:8px;padding-left:16px;padding-right:16px;padding-top:8px</style>
							<text>I assume you have a &lt;strong&gt;&apos;myApp&apos;&lt;/strong&gt; folder with any other name...&lt;br&gt;It&apos;s folder of downloaded and extracted &apos;&lt;strong&gt;nwjs&apos;&lt;/strong&gt; from nwjs.io&lt;br&gt;inside that, there is a &lt;strong&gt;&apos;package.nw&apos;&lt;/strong&gt; folder.&lt;br&gt;your published VisualNEO Web files are there... &lt;strong&gt;index.html, package.json and folders...&lt;/strong&gt;&lt;br&gt;and don&apos;t forget to check &lt;strong&gt;&apos;include neoEdge and NWjs compatibility&apos;&lt;/strong&gt; option in your VisualNEO project.&lt;br&gt;there are 2 more folders in package.nw:&lt;br&gt;&lt;strong&gt;&apos;php&apos; - &apos;nginx&apos;&lt;/strong&gt;&lt;br&gt;which you downloaded from their websites...&lt;br&gt;and&amp;nbsp;set their config files for your needs.&lt;br&gt;&lt;br&gt;now on this sample app there is 2 subroutines, which they are 2 javascript codes:&lt;br&gt;&lt;strong&gt;starter - ender&lt;/strong&gt;&lt;br&gt;&lt;br&gt;publish this project to &lt;strong&gt;&apos;package.nw&apos;&lt;/strong&gt; folder of your NWjs app.&lt;br&gt;then click on buttons below, to run &lt;strong&gt;nginx+php&lt;/strong&gt; or stop them.&lt;br&gt;&lt;br&gt;this codes, will not end or conflict with other php or nginx process on user&apos;s machine.&lt;br&gt;anyways I used &lt;strong&gt;chatGPT&lt;/strong&gt; to write starter and ender, so test it before use on any projects.&lt;br&gt;&lt;br&gt;This way you can build cross platform desktop apps (+php and sqlite databases +nodejs) easily by VisualNEO Web.&lt;br&gt;Output size is huge, ~200mb zipped ~400mb unzipped but it gives you lot of power!&lt;br&gt;&lt;strong&gt;php+nginx+nodejs+chrome! woha! MAYBE WE ADD MYSQL TO MAKE IT 1Gb???&lt;/strong&gt; lol</text>
						</Paragraph>
					</Components>
				</Page>
			</Components>
		</PageList>
		<PageList name="Master">
			<Components>
				<Page id="MasterPage"/>
			</Components>
		</PageList>
		<PageList name="Dialog">
			<Components>
				<Page id="NewDialog">
					<Components>
						<DialogContainer id="DialogContainer1">
							<left>0px</left>
							<top>0px</top>
							<width>640px</width>
							<height>480px</height>
							<close_button>False</close_button>
							<kind>custom</kind>
						</DialogContainer>
					</Components>
				</Page>
			</Components>
		</PageList>
	</Components>
</Application>
