Source code of zwamp.exe

2010-03-29
2012-09-25
  • Deepak Sathya
    Deepak Sathya
    2010-03-29

    Hi,

    Zwamp is almost what I want for PHP 5.3.x dev testing. But would like to have
    nosql (mongo/couch db) support. I would like to see if things like starting
    and stopping services could be added for these.

    Ideal way would be to have some sort of extension mechanism.

    I looked at projects svn base and nothing is there. Could you please open up
    the code. I would certainly give back any improvements that I will be able to
    make.

    TIA

     
  • Bong Cosca
    Bong Cosca
    2010-04-02

    Deepak,

    This is a sad story. The zwamp source was lost with my thumb drive before I
    even got to upload it on SourceForge. It was developed in FreePascal. I tried
    reverse-engineering my own code, but just don't have time to reconstruct it
    yet. There's a much older version written in C#. This might help you get a
    headstart. I abandoned the C# version because a stand-alone .exe is more
    favorable, and does not require .NET to be installed, but the functionality is
    the same.

    -- code for zwamp.cs --

    // Apache/MySQL Service Controller
    // Requires .NET Framework 2.0.50727
    
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Management;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using System.Resources;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    
    public class AMP {
    
        // Win32 API functions
        [DllImport("kernel32.dll")]
        static extern bool DefineDosDevice(uint dwFlags,string lpDeviceName,string lpTargetPath);
        [DllImport("kernel32.dll")]
        static extern bool SetProcessWorkingSetSize(IntPtr hProcess,int dwMinSize,int dwMaxSize);
    
        // messages
        static string appName="Apache/MySQL Controller";
        static string apacheDownText="Apache Web server is down";
        static string mysqlDownText="MySQL database server is down";
        static string allDownText="Apache/MySQL services are offline";
    
        // globals
        static string GUID="39d8c3af-1f05-4587-a217-5b6acbae4b9a";
        static Assembly assembly=Assembly.GetExecutingAssembly();
        static ResourceManager resources=new ResourceManager("AMP",assembly);
        static string exePath=Path.GetDirectoryName(assembly.Location);
    
        // path to be virtualized
        static string sourcePath=exePath+"\\vdrive";
        static string vDrive="Z";
    
        // define paths/filenames
        static string sysPath="\\.sys";
        static string apacheRoot=sysPath+"\\apache2";
        static string apacheFile="httpd.exe";
        static string mysqlRoot=sysPath+"\\mysql";
        static string mysqlFile="mysqld.exe";
    
        // semaphores and virtual host configuration
        static string vDiskFile="vdrive\\"+apacheRoot+"\\logs\\drive.txt";
        static string pidFile="vdrive\\"+apacheRoot+"\\logs\\httpd.pid";
        static string vHostsFile="vdrive\\"+apacheRoot+"\\conf\\vhosts.conf";
    
        // status check and poll interval
        static Timer timer=new Timer();
        static int freq=3000;
    
        // GUI components
        static NotifyIcon icon=new NotifyIcon();
        static Icon iconRunning=(Icon) resources.GetObject("running");
        static Icon iconPartial=(Icon) resources.GetObject("partial");
        static Icon iconStopped=(Icon) resources.GetObject("stopped");
    
        // balloon tip toggle and duration
        static bool balloonSw=false;
        static int balloonDuration=1000;
    
        // get processes associated with specified filename
        static protected List<ManagementObject> getProc(string str) {
            List<ManagementObject> pList=new List<ManagementObject>();
            ManagementClass pClass=new ManagementClass("Win32_Process");
            ManagementObjectCollection procs=pClass.GetInstances();
            foreach (ManagementObject proc in procs) {
                Regex expr=new Regex(str.Replace(".","\\."),RegexOptions.IgnoreCase);
                if (expr.IsMatch(proc["Name"].ToString()))
                    pList.Add(proc);
            }
            return pList;
        }
    
        // kill active processes associated with specified filename
        static void killProc(string str) {
            List<ManagementObject> procs=getProc(str);
            foreach (ManagementObject proc in procs)
                proc.InvokeMethod("Terminate",null);
        }
    
        // run specified process
        static void runProc(string fName,string args,ProcessWindowStyle style) {
            ProcessStartInfo info=new ProcessStartInfo();
            info.FileName=fName;
            info.Arguments=args;
            info.WindowStyle=style;
            Process.Start(info);
        }
    
        // start/stop services
        static void ctrlSvcs(string cmd) {
            // terminate Apache
            killProc(apacheFile);
            // terminate MySQL
            killProc(mysqlFile);
            // switch to executable path
            Directory.SetCurrentDirectory(exePath);
            // if httpd.pid exists, delete it
            if (File.Exists(pidFile))
                File.Delete(pidFile);
            // if virtual disk semaphore exists, delete it
            if (File.Exists(vDiskFile)) {
                StreamReader stream=new StreamReader(vDiskFile);
                vDrive=stream.ReadLine();
                stream.Close();
                // delete virtual disk
                File.Delete(vDiskFile);
            }
            if (Directory.Exists(vDrive+":\\"))
                DefineDosDevice(6,vDrive+":",sourcePath);
            if (cmd!="stop") {
                // find unused drive
                string drives="ZYXWVUTSRQPONMLKJIHGFEDC";
                for (int i=0;i<drives.Length;i++) {
                    vDrive=drives.Substring(i,1);
                    if (!Directory.Exists(vDrive+":\\")) {
                        // create virtual disk
                        DefineDosDevice(0,vDrive+":",sourcePath);
                        break;
                    }
                }
                // save virtual disk semaphore
                StreamWriter stream=new StreamWriter(vDiskFile);
                stream.WriteLine(vDrive);
                stream.Close();
                // switch to virtual disk
                Directory.SetCurrentDirectory(vDrive+":\\");
                // run Apache and MySQL
                runProc(apacheRoot+"\\bin\\"+apacheFile,"-f "+apacheRoot+"\\conf\\httpd.conf -d "+apacheRoot+"\\",ProcessWindowStyle.Hidden);
                runProc(mysqlRoot+"\\bin\\"+mysqlFile,"--defaults-file="+mysqlRoot+"\\my.cnf",ProcessWindowStyle.Hidden);
                // switch to executable path
                Directory.SetCurrentDirectory(exePath);
            }
        }
    
        // start Apache/MySQL
        static void startSvcs(object sender,EventArgs e) {
            ctrlSvcs("start");
        }
    
        // stop Apache/MySQL
        static void stopSvcs(object sender,EventArgs e) {
            ctrlSvcs("stop");
        }
    
        // open Apache configuration file
        static void apacheCfg(object sender,EventArgs e) {
            runProc("notepad.exe",vDrive+":\\"+apacheRoot+"\\conf\\httpd.conf",ProcessWindowStyle.Normal);
        }
    
        // open virtual host configuration file
        static void vHostsCfg(object sender,EventArgs e) {
            runProc("notepad.exe",vDrive+":\\"+apacheRoot+"\\conf\\vhosts.conf",ProcessWindowStyle.Normal);
        }
    
        // open MySQL configuration file
        static void mysqlCfg(object sender,EventArgs e) {
            runProc("notepad.exe",vDrive+":\\"+mysqlRoot+"\\my.cnf",ProcessWindowStyle.Normal);
        }
    
        // open Apache access.log
        static void accessLog(object sender,EventArgs e) {
            runProc("notepad.exe",vDrive+":\\"+apacheRoot+"\\logs\\access.log",ProcessWindowStyle.Normal);
        }
    
        // open Apache error.log
        static void errorLog(object sender,EventArgs e) {
            runProc("notepad.exe",vDrive+":\\"+apacheRoot+"\\logs\\error.log",ProcessWindowStyle.Normal);
        }
    
        // exit application
        static void exitApp(object sender,EventArgs e) {
            ctrlSvcs("stop");
            icon.Dispose();
            Application.Exit();
        }
    
        // reduce memory footprint
        static void trimRAM() {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,-1,-1);
        }
    
        // check status of services and change system tray icon as necessary
        static void checkSvcs(object sender,EventArgs e) {
            // check vital signs
            bool apacheUp=getProc(apacheFile).Count>0;
            bool mysqlUp=getProc(mysqlFile).Count>0;
            if (apacheUp && mysqlUp) {
                icon.ContextMenu.MenuItems[0].Enabled=false;
                icon.ContextMenu.MenuItems[1].Enabled=true;
                if (File.Exists(vHostsFile))
                    icon.ContextMenu.MenuItems[4].Enabled=true;
                icon.Icon=iconRunning;
                balloonSw=false;
            }
            else {
                icon.ContextMenu.MenuItems[0].Enabled=true;
                icon.ContextMenu.MenuItems[1].Enabled=false;
                if (!File.Exists(vHostsFile) || !apacheUp)
                    icon.ContextMenu.MenuItems[4].Enabled=false;
                icon.Icon=(apacheUp || mysqlUp)?iconPartial:iconStopped;
                if (!balloonSw) {
                    // display balloon tip
                    icon.BalloonTipTitle=appName;
                    if (apacheUp || mysqlUp)
                        icon.BalloonTipText=apacheUp?mysqlDownText:apacheDownText;
                    else
                        icon.BalloonTipText=allDownText;
                    icon.BalloonTipIcon=ToolTipIcon.Error;
                    icon.ShowBalloonTip(balloonDuration);
                    balloonSw=true;
                }
            }
            trimRAM();
        }
    
        static void launch(object sender,EventArgs e) {
            MenuItem item=(MenuItem) sender;
            runProc("[url]http://[/url]"+item.Text,"",ProcessWindowStyle.Normal);
        }
    
        [STAThread]
        static void Main() {
            // allow only one process instance to execute
            bool allowRun;
            System.Threading.Mutex mutex=new System.Threading.Mutex(true,GUID,out allowRun);
            if (allowRun) {
                // start Apache/MySQL services
                ctrlSvcs("start");
                // define system tray components
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                icon.ContextMenu=new ContextMenu();
                // main context menu
                icon.ContextMenu.MenuItems.AddRange(
                    new MenuItem[] {
                        new MenuItem("Start",new EventHandler(startSvcs)),
                        new MenuItem("Stop",new EventHandler(stopSvcs)),
                        new MenuItem("Restart",new EventHandler(startSvcs)),
                        new MenuItem("-"),
                        new MenuItem("Web Site"),
                        new MenuItem("Configuration",
                            new MenuItem[] {
                                new MenuItem("Apache",new EventHandler(apacheCfg)),
                                new MenuItem("vHosts",new EventHandler(vHostsCfg)),
                                new MenuItem("MySQL",new EventHandler(mysqlCfg))
                            }
                        ),
                        new MenuItem("Logs",
                            new MenuItem[] {
                                new MenuItem("Access Log",new EventHandler(accessLog)),
                                new MenuItem("Error Log",new EventHandler(errorLog))
                            }
                        ),
                        new MenuItem("-"),
                        new MenuItem("Exit",new EventHandler(exitApp))
                    }
                );
                if (File.Exists(vHostsFile)) {
                    StreamReader stream=new StreamReader(vHostsFile);
                    string line;
                    Regex expr=new Regex(@"ServerName\s(.*)",RegexOptions.IgnoreCase);
                    Match match;
                    while ((line=stream.ReadLine())!=null) {
                        match=expr.Match(line);
                        if (match.Success)
                            icon.ContextMenu.MenuItems[4].MenuItems.Add(
                                new MenuItem(match.Groups[1].Value,new EventHandler(launch))
                            );
                    }
                    stream.Close();
                    if (icon.ContextMenu.MenuItems[4].MenuItems.Count<1)
                        icon.ContextMenu.MenuItems[4].Enabled=false;
                }
                else
                    icon.ContextMenu.MenuItems[4].Enabled=false;
                icon.Icon=iconStopped;
                icon.Text=appName;
                icon.Visible=true;
                // activate timer for services monitoring
                timer.Interval=freq;
                timer.Tick+=new EventHandler(checkSvcs);
                timer.Start();
                Application.Run();
                // release process to allow next instance to run
                GC.KeepAlive(mutex);
                mutex.ReleaseMutex();
            }
        }
    
    }