我正在Flash Builder(Flex)中开发AIR应用程序,我需要选项与计算机上的串行端口进行通信。所以我正在使用Serproxy来帮助我。
我希望能够在我的应用程序运行时启动serproxy.exe。我尝试了两种方法,但它们都不适合我。
我已使用extendedDesktop设置supportedProfiles。
第一种方法:
var file:File = File.applicationDirectory.resolvePath("assets/serproxy.exe");
file.openWithDefaultApplication();
这会打开程序,但会立即关闭它。没有错误。
第二种方法:
var file:File = File.applicationDirectory.resolvePath("assets/serproxy.exe");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process:NativeProcess = new NativeProcess();
process.start(nativeProcessStartupInfo);
虽然通过研究发现这种方法有效,但它对我没有任何作用。不会抛出任何错误,也不会启动任何程序。
如果有任何想法请告诉我!感谢
答案 0 :(得分:4)
我已经解决了。我的问题是,由于Serproxy使用cmd.exe打开,因此在保持文件打开时存在一些问题,因为Windows喜欢自动关闭它。我通过创建文件的快捷方式并使用
预先挂起其目标来解决这个问题C:\Windows\System32\cmd.exe /K "C:\...assets\serproxy.exe"
然后我可以用
运行快捷方式var file:File = File.applicationDirectory.resolvePath("assets/serproxy.lnk");
file.openWithDefaultApplication();
窗户一直开着!
答案 1 :(得分:1)
我去年写了一个名为 Disco Desktop 的应用程序,该应用程序使用TinkerProxy允许AIR通过USB串口与Arduino进行通信。我的TinkerProxy / TinkerProxyEvent类发布在下面。
应用程序捆绑了serproxy并使用Native Process API来调用它,因此有2个不同的安装程序 - Mac OS X和Windows。 TinkerProxy.as扩展了Socket,根据用户的输入在运行时写入serproxy配置文件,并基于此配置启动serproxy作为后台进程。终端/ cmd窗口永远不可见。注意:调用open()而不是connect()。包含在安装程序中的是Arduino的简单设备原理图和草图。
它可能不是我最好的代码,但确实有效。我希望它有所帮助。
Tinker Proxy:
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;
}
}
}
修补程序代理事件:
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);
}
}
}
安装人员:Disco Desktop (Mac Installer),Disco Desktop (Windows Installer)
答案 2 :(得分:-1)
使用URLRequest使用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();