I'm building an AIR application with Flash CC, so that I can use Native Processes. Before I even got to integrating it into my full project, I created a small test project to see if it would work. I tried it in Windows and it didn't work. I switched over to Mac and got it to work there, though.
The Native Process is triggered by a key press. The file is published as a Windows installer, not an Air package. I have made sure to include extendedDesktop in the xml file. I have double checked the file paths. Are there any other reasons this wouldn't work?
package {
import flash.display.MovieClip;
import flash.filesystem.File;
import flash.events.KeyboardEvent;
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
public class Main extends MovieClip {
var exe:File = new File("C:\Windows\System32\notepad.exe");
var nativeProcess:NativeProcess = new NativeProcess();
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var args:Vector.<String> = new Vector.<String>();
public function startProcess(event:KeyboardEvent):void
{
if (event.keyCode == 65) {
nativeProcessStartupInfo.executable = exe;
args.push("C:/Users/Tristan/Documents/TVCR/airTestFile.rtf");
nativeProcessStartupInfo.arguments = args;
nativeProcess.start(nativeProcessStartupInfo);
}
}
}
}
How to output some debug information. The following code will show some messages if the keyboard events really trigger the handler method.
public function startProcess(event:KeyboardEvent):void
{
// LogText:TextField
LogText.appendText("\n\nKey Pressed: " + event.keyCode);
}
How to output and diagnose an exception:
try
{
nativeProcess.start(nativeProcessStartupInfo);
LogText.appendText("\n\nThe process has been started without exceptions.");
}
catch (fail:Error)
{
// LogText:TextField
LogText.appendText("\n\n" + fail.getStackTrace());
}
It seems that the file path I was using wasn't in the correct format.
C:\Windows\System32\notepad.exe
should be
C:\\Windows\\System32\\notepad.exe
The file path for Windows has to use a double backslash "\" since a single backslash gets interpreted as an escape.
Something that's handy, especially if you need to build a path to an executable or your making something that's going to be Windows and Mac is to use File.separator since it will do "\" for Windows and "/" for Mac/Linux
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/filesystem/File.html#separator
Related
After my program installed I need installer to add program path to Windows system variable PATH. How to make this?
Installer must do this not me.
UPD:
And program path must be removed with uninstallation too.
UPD2:
Now I'm trying to do like this:
function Component()
{
installer.installationFinished.connect(this, Component.prototype.installationFinishedPageIsShown);
installer.uninstallationFinished.connect(this, Component.prototype.uninstallationFinishedPageIsShown);
}
Component.prototype.installationFinishedPageIsShown = function()
{
try {
if (installer.isInstaller() && installer.status == QInstaller.Success) {
installer.executeDetached("set", "PATH=%PATH%;#TargetDir#");
}
} catch(e) {
console.log(e);
}
}
Component.prototype.uninstallationFinishedPageIsShown = function()
{
try {
if (installer.isUninstaller() && installer.status == QInstaller.Success) {
installer.executeDetached("set", "PATH=%PATH:;#TargetDir#=%");
}
} catch(e) {
console.log(e);
}
}
but it doesn't work :(
I just also struggled a lot with the arguments to the executeDetached function (OS X environment).
Because, apparently, characters are escaped when using a string 'inline'.
For me it worked by moving the arguments to a separate javascript variable, like:
var args = "PATH=%PATH:;#TargetDir#=%"
installer.executeDetached("set", args);
or even
var args = ["PATH=%PATH:;#TargetDir#=%"]
installer.executeDetached("set", args);
Did not validate, but hopefully it could point you, or others, in the right direction.
Also, wrapping the executeDetached in a console.log() helped me debugging a lot!
From the desktop, right click the Computer icon.
Choose Properties from the context menu.
Click the Advanced system settings link.
Click Environment Variables. ...
In the Edit System Variable (or New System Variable) window, specify the value of the PATH environment variable.
I am making a game engine in haxe/openfl. so far it's just supposed to display the image that belongs to the thing object. what I have built so far runs perfectly on when deployed as a flash application, but closes instantly when I deploy it as a windows application. It just creates a blank screen in html5. I have not tested other targets. I am using HIDE, and every time it crashes, HIDE brings up the message: "File c:\Users\Adu\Documents\HaxeProjects\Downloaded\Export\windows\cpp\bin\Downloaded.exe was changed. Reload?" and gives me the options yes or no. My answer doesn't seem to change the situation. when I manually go into the export directory and run the application, it gives the error: "Error Custom([file_write,stderr]). Here is my code:
Main:
package;
import openfl.display.Graphics;
import openfl.Assets;
import openfl.display.Bitmap;
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.Lib;
import openfl.text.TextField;
import openfl.text.TextFormat;
import openfl.ui.Keyboard;
import openfl.events.*;
class Main
{
static var obj(default,default):ObjectManager; //contains the list that all gameobjects add themselves to
static var stage = Lib.current.stage;
public static function main() // this is the gameloop
{
// static entry point
startUp();
var running = true; // gives me a way to exit the gameloop
while (running)
{
logic();
render();
Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event)
{
if (event.keyCode == Keyboard.ESCAPE)
{
running=false;
}
});
}
}
static function startUp() // runs once, when the game is started
{
obj= new ObjectManager();
stage.align = openfl.display.StageAlign.TOP_LEFT;
stage.scaleMode = openfl.display.StageScaleMode.NO_SCALE;
}
static function logic() // loops, this handles the logic
{
var thing = new GameObject("assets/pixel_thing.png", 1, obj);
var mech = new GameObject("assets/mechwarrior.png", 0, obj);
}
static function render() // runs right after logic and draws everything to the screen
{
for (i in obj.objects) //iterates through a list of gabeobjects and draws them, it is 2 dimensional so that I can draw objects in blocks
{
for (j in i)
{
Lib.current.addChild(j);
}
}
}
}
GameObject:
package ;
import openfl.display.BitmapData;
import openfl.Assets;
import openfl.display.Bitmap;
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.Lib;
import openfl.text.TextField;
import openfl.text.TextFormat;
class GameObject extends Sprite
{
public function new(?image:String, zOrder:Int, objectManager:ObjectManager) // image is the image, zorder is which layer it's drawn on, lower layers are drawn on top objectmanager is just there to help me pass the list to the object
{
super();
var data = Assets.getBitmapData(image);//this is the image data
var bitmap:Bitmap = new Bitmap(data);//this is the actual image
Lib.current.stage.addChild(bitmap);//this sraws the image when the object is instantiated
objectManager.objects[zOrder].push(this);// this adds it to the list of objects
}
}
ObjectManager:
package ;
class ObjectManager
{
public var objects = new Array<Array<GameObject>>();
}
why is it that it works on flash but not windows? How do I fix this?
First off - this doesn't work fine on flash either. Are you running this in the flash debug player? If you don't, which I assume is the case, you won't see any exceptions.
There's a null reference error at this line:
objectManager.objects[zOrder].push(this);// this adds it to the list of objects
You are accessing the array at index zOrder, which doesn't exist. objects is being initialized to [], which does not include the "inner arrays" (it can't, really, how would it know how many of them there should be?).
Now, Windows builds don't give you very helpful debug information by default. A simple way around is to use neko (which mostly behaves the same as hxcpp builds, except it compiles faster and performs worse) for debugging, where you get a stacktrace by default on crashes.
Sure enough, it's the same issue as in flash, the only difference is that native builds crash while flash just "ignores it" and tries to carry on.
Invalid field access : objects
Called from GameObject::new line 92
Called from GameObject::$init line 83
Called from Main::logic line 61
Called from Main::main line 38
Called from Reflect::callMethod line 58
Called from ApplicationMain::main line 91
Called from openfl.Lib::create line 113
For better hxcpp build debug info, you might want to have a look at the crashdumper lib.
First of all, I'm NOT talking about if the player is a debugger or not. (EDIT: it IS actually related to the debugger player)
I use mxmlc to compile a very simple swf file with -debug=false:
mac-108:tmp admin$ "/Applications/Adobe Flash Builder 4.7/sdks/4.6.0/bin/mxmlc" +configname flex -debug=true -static-link-runtime-shared-libraries=true Main.as
Loading configuration file /Applications/Adobe Flash Builder 4.7/sdks/4.6.0/frameworks/flex-config.xml
/Users/admin/tmp/Main.swf (987 bytes)
mac-108:tmp admin$
The Main.as:
package {
import flash.display.MovieClip;
import flash.text.*;
public class Main extends MovieClip {
public function Main() {
// Reference: http://stackoverflow.com/questions/185477/determine-if-swf-is-in-a-debug-player-or-mode
var st:String = new Error().getStackTrace();
var isDebugBuild:Boolean = (st && st.search(/:[0-9]+]$/m) > -1);
var my_st:String = "st: " + (st == null ? 'Null' : st);
var my_DR:String = isDebugBuild?"Debug":"Release";
var obj:TextField = new TextField();
obj.text = my_st + "\n" + my_DR;
this.addChild(obj);
}
}
}
Then I open Main.swf in my Chrome browser, but I see:
st:Null
Release
Which is so weird that, apparently, I have set -debug=true, why does NOT the popular method to determine if an swf is in Debug or Release work.
However, if I move my code to the Flash Builder 4.7, it will give me the Debug output (instead of Release).
It turns out that when the SWF is built in Debug mode, in order to test if it's in debug mode, the Flash Player must also be a debugger using Capabilities.isDebugger.
Could you please help me to retrieve file version property from Groovy script (in Windows platform)?
I mean the Version property available in Windows (7) in Details tab of file Properties window opened by right-click on file name.
I found to do it with WSH only.
Thanks In Advance!
First I tried to find a solution with and "More New I/O APIs for the Java™ Platform" (NIO.2) but didn't succeed. When I looked closer at your WSH-example I realized it is COM scripting.
So there are 2 possiblities to solve this:
Com4j
Java Native Access (JNA)
An example for accessing Word from Java can be found here.
Update
I tried to solve your problem, but run into an exception within the Namespace-function:
#Grab(group='net.java.dev.jna', module='platform', version='3.5.2')
import com.sun.jna.platform.win32.COM.COMException
import com.sun.jna.platform.win32.COM.COMObject
import com.sun.jna.platform.win32.OleAuto;
import com.sun.jna.platform.win32.Variant;
import com.sun.jna.platform.win32.Variant.VARIANT;
import com.sun.jna.platform.win32.WTypes.BSTR;
import com.sun.jna.platform.win32.WinNT.HRESULT;
public class Shell extends COMObject {
public Shell() throws COMException {
super("Shell.Application", false);
}
public HRESULT Namespace(String dir) throws COMException
{
def bstrDir = OleAuto.INSTANCE.SysAllocString(dir)
def varDir = new VARIANT(bstrDir)
def result = new VARIANT.ByReference()
HRESULT hr = oleMethod(OleAuto.DISPATCH_METHOD, result, this.iDispatch, "Namespace", varDir);
}
}
def shell = new Shell()
shell.Namespace("C:\\Temp")
I have a C# project that contains 1 EXE and about 7 DLLs. What I would like to have is a folder beside the EXE called "Library" (or something similar) that contains all the DLLs so that it is a bit more organized and looks better for the end user.
I know this can be done using an AppConfig but the I don't want another file beside the EXE. All I want is the main EXE and the folder.
Is it possible to use AppConfig and embed it or load the DLLs without using a AppConfig that won't change how I currently use my DLLs? I know you can load a DLL at run time but I don't think that is what I am looking for.
Thanks!
EDIT
I know the pros and cons to doing this, so please only answers on how to do this and no advice as to why I should or should not do this.
Use System.Reflection.Assembly.LoadFrom(path).
LoadFrom will allow it to look in the same folder as the targetted dll for any dependencies. If you use Load, then it will not consider dlls that are sitting in the same folder as the dll you Load.
I know this doesn't directly answer your question, but manually calling LoadFrom on the DLLs early in your process startup should do the trick if you want an "xcopy" installable .net app or something.
PrettyBin is your solution. It does this beautifully!
SetDllDirectory() + carefully coded AssemblyResolve. Works for me in a nontrivial project, with no DLL hell.
https://github.com/TASVideos/BizHawk/blob/d05ddabf5f22debf47369f94868462a75ea0b466/BizHawk.Client.EmuHawk/Program.cs
I created new console application-launcher. In app folder contains my EXE file - MyApp.exe and all DLLs.
static void Main(string[] args)
{
var process = new Process
{
StartInfo =
{
FileName = "app\\MyApp.exe",
}
};
process.Start();
}
If you want the application to be launched when you drag certain files onto the EXE:
class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
String FileName = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location )
+ "\\app\\MyApp.exe";
ProcessStartInfo startInfo = new ProcessStartInfo(FileName);
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.Arguments = args[0].ToString();
Process.Start(startInfo);
}
else {
var process = new Process
{
StartInfo =
{
FileName = "app\\MyApp.exe",
}
};
process.Start();
}
}
}