开发者

Launch EXE (Serproxy) with Adobe AIR

I'm developing an AIR application in Flash Builder (Flex) and I needed the option to communicate with a serial port on the computer. So I'm using Serproxy to help me with that.

I want to be able to launch serproxy.exe when my application runs. I've tried two methods, and neither of them are working for me.

I have set supportedProfiles with extendedDesktop.


First method:

var file:File = File.applicationDirectory.resolvePath("assets/serproxy.exe");
file.openWithDefaultApplication();

This proceeds to open the program, but then immediately closes it. No errors are thrown.


Second method:

var file:File = File.applicationDirectory.resolvePath("assets/serproxy.exe");

var nativeProcessStartupInfo:NativeProcessStartupInfo开发者_如何学Go = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process:NativeProcess = new NativeProcess();

process.start(nativeProcessStartupInfo);

Although through research this method has been found to work, it simply does nothing for me. No errors are thrown, and no program is launched.


If anyone has any ideas please let me know! Thanks


I've solved it. My issue was that since Serproxy opens with cmd.exe, there were some issues keeping the file open, as Windows likes to automatically close it. I got around this by creating a shortcut to the file, and pre-pending its target with

C:\Windows\System32\cmd.exe /K "C:\...assets\serproxy.exe"

Then I could run the shortcut with

var file:File = File.applicationDirectory.resolvePath("assets/serproxy.lnk");
file.openWithDefaultApplication();

And the window stayed open!


I wrote an application last year called Disco Desktop which uses TinkerProxy to allow AIR to communicated with Arduino over USB serial port. My TinkerProxy and TinkerProxyEvent classes is posted below.

The application bundles serproxy and uses Native Process API to call it so there are 2 different installers - Mac OS X and Windows. TinkerProxy.as extends Socket, writes the serproxy configuration file at runtime according to the users' input and launches serproxy based on this configuration as a background process. The terminal/cmd window is never visible.

Note: call open() instead of connect(). Included in the installers are a simple device schematic and sketch for Arduino.

TinkerProxy:

package com.mattie.net
{
//Imports
import com.mattie.events.TinkerProxyEvent;
import flash.desktop.NativeApplication;
import flash.desktop.NativeProcessStartupInfo;
import flash.desktop.NativeProcess;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.filesystem.File;
import flash.net.Socket;
import flash.system.Capabilities;
import flash.utils.Timer;
import flash.utils.Endian;

//Class
public class TinkerProxy extends Socket
    {
    //Properties
    private var systemIsWindowsProperty:Boolean;
    private var openingProperty:Boolean;
    private var connectedProperty:Boolean;

    //Variables
    private var windowsProxyFile:String;
    private var macProxyFile:String;
    private var tinkerProxyApplication:File;
    private var tinkerProxyConfigurationFile:File;
    private var serialPort:String;
    private var baudRate:uint;
    private var networkAddress:String;
    private var networkPort:uint;
    private var loadDelay:uint;
    private var loadDelayTimer:Timer;
    private var initializeDelay:uint;
    private var initializeDelayTimer:Timer;
    private var comDatabits:uint;
    private var comStopbits:uint;
    private var proxyTimeout:uint;
    private var writeConfigStream:FileStream;
    private var tinkerProxyProcess:NativeProcess;

    //Constructor
    public function TinkerProxy(windowsProxyFile:String = "serproxy.exe", macProxyFile:String = "serproxy.osx", endian:String = Endian.LITTLE_ENDIAN)
        {
        //Set Included File Proxy Names
        this.windowsProxyFile = windowsProxyFile;
        this.macProxyFile = macProxyFile;

        super();
        super.endian = endian;

        init();
        }

    //Resolve The Operating System
    private function init():void
        {
        //Check If Source Tinker Proxy Files Are Included In Application Directory
        if  (!File.applicationDirectory.resolvePath(windowsProxyFile).exists && !File.applicationDirectory.resolvePath(macProxyFile).exists)
            throw new Error("Tinker Proxy source files \"" + windowsProxyFile + "\" (Windows) and/or \"" + macProxyFile + "\" (Mac) cannot be found in application directory (Included Files)");

        //Resoslve Operating System
        if  (Capabilities.os.toLowerCase().indexOf("windows") > -1)
            {
            systemIsWindowsProperty = true;
            tinkerProxyApplication = File.applicationDirectory.resolvePath(windowsProxyFile);
            tinkerProxyConfigurationFile = File.applicationStorageDirectory.resolvePath(windowsProxyFile.substring(0, windowsProxyFile.lastIndexOf(".exe")) + ".cfg");  
            }
            else if (Capabilities.os.toLowerCase().indexOf("mac") > -1)
            {
            systemIsWindowsProperty = false;
            tinkerProxyApplication = File.applicationDirectory.resolvePath(macProxyFile);
            tinkerProxyConfigurationFile = File.applicationStorageDirectory.resolvePath(macProxyFile + ".cfg");
            }
            else
            {
            throw new Error("TinkerProxy Error:  Operating System Is Not Supported");
            }
        }

    //Open Tinker Proxy Socket Connection
    public function open(
                        serialPort:String,
                        baudRate:uint,
                        networkAddress:String = "127.0.0.1",
                        networkPort:uint = 5331,
                        loadDelay:uint = 1000,
                        initializeDelay:uint = 2000,
                        comDatabits:uint = 8,
                        comStopbits:uint = 1,
                        proxyTimeout:uint = 63115200
                        )
        {
        //Disable Opening Socket If Currently Opening
        if  (!openingProperty)
            {
            //Set Accessor
            openingProperty = true;

            //Dispatch Event
            dispatchEvent(new TinkerProxyEvent(TinkerProxyEvent.LOADING));

            //Check If Connection Parameters For Configuration File Have Changed
            if  (
                this.serialPort == serialPort   &&
                this.baudRate == baudRate                           &&
                this.networkAddress == networkAddress               &&
                this.networkPort == networkPort                     &&
                this.comDatabits == comDatabits                     &&
                this.comStopbits == comStopbits                     &&
                this.proxyTimeout == proxyTimeout
                )
                    {
                    //Assign Timer Variables
                    this.loadDelay = loadDelay;
                    this.initializeDelay = initializeDelay;

                    //Launch Tinker Proxy Application If Connection Parameters Have Not Changed
                    launchTinkerProxyApplication(null);
                    return;
                    }

            //Assign Variables
            this.serialPort = serialPort;
            this.baudRate = baudRate;
            this.networkAddress = networkAddress;
            this.networkPort = networkPort;
            this.loadDelay = loadDelay;
            this.initializeDelay = initializeDelay;
            this.comDatabits = comDatabits;
            this.comStopbits = comStopbits;
            this.proxyTimeout = proxyTimeout;

            //Add Event Listeners To New File Stream
            writeConfigStream = new FileStream();
            writeConfigStream.addEventListener(Event.CLOSE, launchTinkerProxyApplication);
            writeConfigStream.addEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);

            //Write Tinker Proxy Configuration File
            writeConfigStream.openAsync(tinkerProxyConfigurationFile, FileMode.WRITE);

            writeConfigStream.writeUTFBytes("serial_device1=" + serialPort + File.lineEnding);
            writeConfigStream.writeUTFBytes("comm_ports=1" + File.lineEnding);
            writeConfigStream.writeUTFBytes("net_port1=" + networkPort + File.lineEnding);              
            writeConfigStream.writeUTFBytes("newlines_to_nils=false" + File.lineEnding);
            writeConfigStream.writeUTFBytes("comm_baud=" + baudRate + File.lineEnding);
            writeConfigStream.writeUTFBytes("comm_databits=" + comDatabits + File.lineEnding);
            writeConfigStream.writeUTFBytes("comm_stopbits=" + comStopbits+ File.lineEnding);
            writeConfigStream.writeUTFBytes("comm_parity=none" + File.lineEnding);
            writeConfigStream.writeUTFBytes("timeout=" + proxyTimeout + File.lineEnding);

            writeConfigStream.close();
            }
        }

    //Launch Tinker Proxy Application
    private function launchTinkerProxyApplication(evt:Event):void
        {
        if  (evt)
            {
            //Remove File Stream Event Listeners
            writeConfigStream.removeEventListener(Event.CLOSE, launchTinkerProxyApplication);
            writeConfigStream.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);
            }

        //Start Tinker Proxy Application As Native Process
        var tinkerProxyProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
        tinkerProxyProcessStartupInfo.executable = tinkerProxyApplication;

        var processArguments:Vector.<String> = new Vector.<String>();
        processArguments[0] = tinkerProxyConfigurationFile.nativePath;
        tinkerProxyProcessStartupInfo.arguments = processArguments;

        tinkerProxyProcess = new NativeProcess();
        tinkerProxyProcess.start(tinkerProxyProcessStartupInfo);

        //Delay Process To Allow Tinker Proxy Application To Initialize
        loadDelayTimer = new Timer(loadDelay, 1);
        loadDelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, connectTinkerProxy);
        loadDelayTimer.start();
        }

    //Initialize Tinker Proxy Socket Connection
    private function connectTinkerProxy(evt:TimerEvent):void
        {
        //Dispatch Event
        dispatchEvent(new TinkerProxyEvent(TinkerProxyEvent.INITIALIZING));

        //Remove Tinker Proxy Application Initilization Timer
        loadDelayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, connectTinkerProxy);
        loadDelayTimer = null;

        //Add Connection Error Event Listeners
        addEventListener(Event.CONNECT, initializeDelayTimerHandler);
        addEventListener(Event.CLOSE, connectionErrorEventHandler);
        addEventListener(IOErrorEvent.IO_ERROR, connectionErrorEventHandler);
        addEventListener(SecurityErrorEvent.SECURITY_ERROR, connectionErrorEventHandler);

        //Connect Socket (Super)
        try {
            super.connect(networkAddress, networkPort);
            }
            catch(error:IOError)        {connectionErrorEventHandler(null);}
            catch(error:SecurityError)  {connectionErrorEventHandler(null);}
        }

    //Delay Process To Allow Device To Initialize
    private function initializeDelayTimerHandler(evt:Event):void
        {
        removeEventListener(Event.CONNECT, initializeDelayTimerHandler);

        initializeDelayTimer = new Timer(initializeDelay, 1);
        initializeDelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, tinkerProxyConnectionComplete);
        initializeDelayTimer.start();
        }

    //Tinker Proxy Socket Has Been Successfully Connected
    private function tinkerProxyConnectionComplete(evt:TimerEvent):void
        {
        //Set Accessors
        openingProperty = false;
        connectedProperty = true;

        //Dispatch Event
        dispatchEvent(new TinkerProxyEvent(TinkerProxyEvent.CONNECT));

        //Remove Device Initilization Timer
        initializeDelayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, tinkerProxyConnectionComplete);
        initializeDelayTimer = null;
        }

    //Throw Error If Stock Connect Method Is Explicitly Called
    override public function connect(host:String, port:int):void
        {
        throw new Error("Cannot call connect() method on TinkerProxy instance.  Call open() method instead."); 
        }

    //Close Tinker Proxy Application
    override public function close():void
        {
        //Stop Configuration File And Timers If Socket Is Currently Opening
        if  (openingProperty)
            {
            //Set Accessor
            openingProperty = false;

            //Stop File Stream
            if  (writeConfigStream.hasEventListener(Event.CLOSE))
                {
                writeConfigStream.close();
                writeConfigStream.removeEventListener(Event.CLOSE, launchTinkerProxyApplication);
                writeConfigStream.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);
                }

            //Stop Process Initialization Timer
            if  (loadDelayTimer.running)
                {
                loadDelayTimer.stop();
                loadDelayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, connectTinkerProxy);
                loadDelayTimer = null;
                }

            //Stop Device Initialization Timer
            if  (initializeDelayTimer.running)
                {
                initializeDelayTimer.stop();
                initializeDelayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, connectTinkerProxy);
                initializeDelayTimer = null;
                }
            }

        //Close Socket (Super)
        super.close();

        //Close Tinker Proxy Application
        tinkerProxyProcess.exit(true);
        tinkerProxyProcess = null;

        //Dispatch Event
        dispatchEvent(new TinkerProxyEvent(TinkerProxyEvent.DISCONNECT));

        //Set Accessor
        connectedProperty = false;

        //Remove Connection Error Event Listeners 
        removeEventListener(Event.CLOSE, connectionErrorEventHandler);
        removeEventListener(IOErrorEvent.IO_ERROR, connectionErrorEventHandler);
        removeEventListener(SecurityErrorEvent.SECURITY_ERROR, connectionErrorEventHandler);
        }

    //Server Automatically Closed The Socket Due To A Connection Error
    private function connectionErrorEventHandler(evt:*):void
        {
        //Set Accessors
        openingProperty = false;
        connectedProperty = false;

        //Dispatch Event
        dispatchEvent(new TinkerProxyEvent(TinkerProxyEvent.ERROR));

        //Remove Device Initilization Timer
        if  (initializeDelayTimer != null)
            {
            if  (initializeDelayTimer.running)
                initializeDelayTimer.stop();

            initializeDelayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, tinkerProxyConnectionComplete);
            initializeDelayTimer = null;
            }

        //Remove Connection Error Event Listeners 
        removeEventListener(Event.CLOSE, connectionErrorEventHandler);
        removeEventListener(IOErrorEvent.IO_ERROR, connectionErrorEventHandler);
        removeEventListener(SecurityErrorEvent.SECURITY_ERROR, connectionErrorEventHandler);

        //Close Tinker Proxy Application
        tinkerProxyProcess.exit(true);
        tinkerProxyProcess = null;
        }

    //IO Error Event Handler 
    private function IOErrorEventHandler(evt:IOErrorEvent):void
        {
        throw new Error("TinkerProxy IOError: " + evt);
        }

    //Accessors
    public function get systemIsWindows():Boolean
        {
        return systemIsWindowsProperty;
        }

    public function get opening():Boolean
        {
        return openingProperty;
        }

    override public function get connected():Boolean
        {
        return connectedProperty;
        }
    }
}

TinkerProxyEvent:

package com.mattie.events
{
//Imports
import flash.events.Event;

//Class
public class TinkerProxyEvent extends Event
    {
    //Constants
    public static const LOADING:String = "Loading";
    public static const INITIALIZING:String = "Initializing";
    public static const CONNECT:String = "Connect";
    public static const DISCONNECT:String = "Disconnect";
    public static const ERROR:String = "Error";

    //Constructor
    public function TinkerProxyEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
        {
        super(type, bubbles, cancelable);
        }
    }
}


Use URLRequest to launch apps using AIR

public function clickButton():void{
var request : URLRequest = new URLRequest('C:\\path to serproxy\serproxy.exe');
navigateToURL(request)

also here are the paths to default folders
var appDir:File    = File.applicationDirectory;
var appStoreDir:File= File.applicationStorageDirectory;
var desktopDir:File = File.desktopDirectory;
var docDir:File    = File.documentsDirectory;
var userDir:File    = File.userDirectory;
var rootDirArr:Array = File.getRootDirectories();  
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜