Is there a way generate a shortcut file with adobe air? - actionscript-3

Good afternoon,
I would like create a application that can can create folders and short cuts to folders in the file system. The user will click a button and it will put a folder on there desktop that has short cuts to files like //server/folder1/folder2 Can you create a desktop shortcut with code in adobe air? How would you do that? How do you create a folder? I keep thinking this should be easy but i keep missing it.
Thank you for your help sorry for the trouble,
Justin

If your deployment profile is Extended Desktop, you may be able to use NativeProcess and some simple scripts that you could package with your app. This approach would entail handling the functionality on a per OS basis, which would take some work and extensive testing. However, I wanted to at least share a scenario that I verified does work. Below is a test case that I threw together:
Test Case: Windows 7
Even though the Adobe documentation says that it prevents execution of .bat files, apparently it doesn't prevent one from executing the Windows Scripting Host: wscript.exe. This means you can execute any JScript or VBScript files. And this is what you would use to write a command to create a shortcut in Windows (since Windows doesn't have a commandline command to create shortcuts otherwise).
Here's a simple script to create a shortcut command, which I found on giannistsakiris.com, (converted to JScript):
// File: mkshortcut.js
var WshShell = new ActiveXObject("WScript.Shell");
var oShellLink = WshShell.CreateShortcut(WScript.Arguments.Named("shortcut") + ".lnk");
oShellLink.TargetPath = WScript.Arguments.Named("target");
oShellLink.WindowStyle = 1;
oShellLink.Save();
If you package this in your application in a folder named utils, you could write a function to create a shortcut like so:
public function createShortcut(target:File, shortcut:File):void {
if (NativeProcess.isSupported) { // Note: this is only true under extendedDesktop profile
var shortcutInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
// Location of the Windows Scripting Host executable
shortcutInfo.executable = new File("C:/Windows/System32/wscript.exe");
// Argument 1: script to execute
shortcutInfo.arguments.push( File.applicationDirectory.resolvePath("utils/mkshortcut.js").nativePath);
// Argument 2: target
shortcutInfo.arguments.push("/target:" + target.nativePath);
// Argument 3: shortcut
shortcutInfo.arguments.push("/shortcut:" + shortcut.nativePath);
var mkShortcutProcess = new NativeProcess();
mkShortcutProcess.start(shortcutInfo);
}
}
If one wanted to create a shortcut to the Application Storage Directory on the Desktop, the following would suffice:
var targetLocation:File = File.applicationStorageDirectory;
var shortcutLocation:File = File.desktopDirectory.resolvePath("Shortcut to My AIR App Storage");
createShortcut(targetLocation, shortcutLocation);
Obviously there's a lot of work to be done to handle different OS environments, but this is at least a step.

As far as I know, File class does not allow the creation of symbolic links. But you can create directories with createDirectory(): http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/filesystem/File.html#createDirectory%28%29
Check if this can be useful: http://www.mikechambers.com/blog/2008/01/17/commandproxy-net-air-integration-proof-of-concept/

Air doesnt let you create shortcuts natively. Here's a workaround that works with Windows [may work on Mac but I don't have a machine to test].
Using Air, create a file that contains the following plain text
[InternetShortcut]
URL=C:\path-to-folder-or-file
Replace path-to-folder-or-file with your folder/file name
Save the file as test.url
Windows recognizes this file as a shortcut.

It is possible to coerce Adobe Air into creating symbolic links, other useful things, on a Mac. Here's how I did it:
You will need AIRAliases.js - Revision: 2.5
In the application.xml add:
<!-- Enables NativeProcess -->
<supportedProfiles>extendedDesktop desktop</supportedProfiles>
In the Air app JavaScript:
// A familiar console logger
var console = {
'log' : function(msg){air.Introspector.Console.log(msg)}
};
if (air.NativeProcess.isSupported) {
var cmdFile = air.File.documentsDirectory.resolvePath("/bin/ln");
if (cmdFile.exists) {
var nativeProcessStartupInfo = new air.NativeProcessStartupInfo();
var processArgs = new air.Vector["<String>"]();
nativeProcessStartupInfo.executable = cmdFile;
processArgs.push("-s");
processArgs.push("< source file path >");
processArgs.push("< link file path >");
nativeProcessStartupInfo.arguments = processArgs;
nativeProcess = new air.NativeProcess();
nativeProcess.addEventListener(air.NativeProcessExitEvent.EXIT, onProcessExit);
nativeProcess.addEventListener(air.ProgressEvent.STANDARD_OUTPUT_DATA, onProcessOutput);
nativeProcess.addEventListener(air.ProgressEvent.STANDARD_ERROR_DATA, onProcessError);
nativeProcess.start(nativeProcessStartupInfo);
} else {
console.log("Can't find cmdFile");
}
} else {
console.log("Not Supported");
}
function onProcessExit(event) {
var result = event.exitCode;
console.log("Exit Code: "+result);
};
function onProcessOutput() {
console.log("Output: "+nativeProcess.standardOutput.readUTFBytes(nativeProcess.standardOutput.bytesAvailable));
};
function onProcessError() {
console.log("Error: "+nativeProcess.standardError.readUTFBytes(nativeProcess.standardError.bytesAvailable));
};
Altering the syntax of the command and parameters passed to NativeProcess you should be able to get real shortcuts on Windows too.

Related

AS3 SharedObject read/write file location change

I’m using the following AS3 code to write and read data in two arrays to a local file, using Animate CC 2019 on Windows 10 and AIR 30.0 for Desktop/Flash (.swf) publishing settings. I use two input text boxes, input1 & input2, to add new data to the arrays.
When I test the FLA, the data file created has a .sol extension and is placed in a folder path:
C:\Users\username\AppData\Roaming\FLA filename\Local Store#SharedObjects\FLA filename.swf\
If I publish and install the program using an .air installer package, the exact same file, in the same folder path, is also accessed by the installed version of the program. Same location is used if I install on another computer running Windows 7, so the file location seems pretty consistent.
Question:
How can I force the code to save to a different location on the local hard drive on Windows? For example, in the documents folder or to create a new folder on the system drive and save the file there? Or, even better, prompt the user to choose the folder and file himself?
Please consider I’m looking for an answer using SharedObject, if possible, and not alternative methods like URLLoader, File, FileStream, FileMode. The reason is this way I can store multiple array contents in a file, without having to deal with the in-file data arrangement. So, I can read back the data for each array easily as shown below.
Thanks in advance
This is the code I use to access the local file:
var datavariable:SharedObject = SharedObject.getLocal("filiename");
var data1:Array = new Array ();
var data2:Array = new Array ();
btn_read.addEventListener(MouseEvent.CLICK, readfromfile);
btn_write.addEventListener(MouseEvent.CLICK, writetofile);
btn_new.addEventListener(MouseEvent.CLICK, newentry);
//To add new data from input text boxes to the arrays:
function newentry(e:Event):void
{
data1.push(input1.text);
data2.push(input2.text);
}
//To write to the local file:
function readfromfile(e:Event):void
{
data1 = datavariable.data.d1
data2 = datavariable.data.d2
}
//To read from the local file:
function writetofile(e:Event):void
{
datavariable.data.d1 = data1
datavariable.data.d2 = data2
datavariable.flush();
}
I don't know of a way of changing the shared object storage location. That mechanism is designed to be abstracted out from the developer.
Since you are using AIR, you can actually forget shared objects, and just write your own files anywhere your app has permission to do so. You can do this using the same format as shared object and don't have to worry about in file data arrangement (you save an object, you read back an object - just like Shared Object does), the only difference is you load/save the file where you choose.
Here is an example:
function writetofile(e:Event):void
{
//create an object that holds your data, this will act the same as the 'data' value of a shared object
var saveObject = {
d1: data1,
d2: data2
}
//using the File and FileStream classes to read/save files
var file:File = File.applicationStorageDirectory.resolvePath("saveData.data"); //or where and whatever you want to store and call the save file
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeObject(saveObject); //write the object to this file
fileStream.close(); //close the File Stream
}
function readfromfile(e:Event):void
{
var file:File = File.applicationStorageDirectory.resolvePath("saveData.data");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var savedObject = fileStream.readObject();
fileStream.close();
data1 = savedObject.d1;
data2 = savedObject.d2;
}
If you want to save complex objects (objects that aren't primitives), you need to register the class first. This goes for shared objects as well. See this answer for example of that.

Embarcadero C++ : How to notify user if new update is available?

I am beginner in Embarcadero C++, If my application is developed in Embarcadero C++ and installed in client machine then how my application notify user if new update is available? If user clicked on yes button then it will first download the application then install it.
Please let me know if anybody have any Idea.
Here is how I check if new version of program is available on the server, using
Indy Client component TIdHTTP.
Let's say you have uploaded a new version of your application. Besides installation or zip file containing you application, upload a one line text file (applicationBuildData.txt) which contains build value (integer), delimiter (;) and optionally some other data (version number, program name, etc...). For example:
20170215; ProgamName rel. 1.2.
This is the only line in applicationBuildData.txt file. Here is the code sample (I've modified my original code a bit):
void __fastcall TfrmDialog::Button1Click(TObject *Sender)
{
TIdHTTP *IdHTTP1 = new TIdHTTP(this);
// let's say this is current app build (on user's side)
int currAppBuild = 20170101;
int prodBuildNew = 0;
UnicodeString prodVersionNew;
UnicodeString version_str;
try {
// get content of applicationBuildData.txt into string
version_str = IdHTTP1->Get("http://www.your-site.com/applicationBuildData.txt");
prodBuildNew = StrToInt(version_str.SubString(1, version_str.Pos(";") - 1).Trim());
prodVersionNew = version_str.SubString(version_str.Pos(";") + 1, 100).Trim();
}
catch (...)
{
prodBuildNew = 0;
prodVersionNew = "???";
}
if (prodBuildNew == 0) {
// ...faild to get data from server...
// display message
}
else if (prodBuildNew > currAppBuild) {
// new version is available
// display message
}
else {
// application version is up to date
// display message
}
delete IdHTTP1;
}
In this example, current build number is smaller then uploaded build number and it will indicate user that new version is available.
Note: currAppBuild is usually some global constant, or global variable that presents build version. After new version on the server is detected, you can either download installation/zip or simply display message and let the user go to your site and download new version manually.
Edit: How to download the file to your local disk using TIdHTTP component, check the following video:
https://www.youtube.com/watch?v=fcN8K3R4iZE

Action script, NativeProcess , resolvePath and swf does not work

I will expose my problem but first I have to show you my configuration to give you all the details.
I have 2 Virtual Machines, 2 windows 7. The first one, it is where I developp all my Action Scripts, where there is my Development Environment(IDE) and second one there is nothing special installed. On both there is Adobe AIR and Adobe Flash Player.
Ok, here is my problem. I develop (on first one) a script that uses NativeProcess to run a CMD.exe that load in command line a dll.
And when I Build&Run the project everything is ok, I check and the dll is loaded. But the problem is when the second Windows connected into my localhost website (to the first windows that play as a server) and run the file "myProgram.swf" (the ActionScript program) that do not load my dll.
Now I print you all my code :
This is the script that loads the dll "myProgram.swf" :
public class NativeProcessExample extends Sprite
{
public var process:NativeProcess;
public function NativeProcessExample()
{
if(NativeProcess.isSupported)
{
setupAndLaunch();
}
else
{
trace("NativeProcess not supported.");
}
}
public function setupAndLaunch():void
{
var fmt:TextFormat = new TextFormat();
var txt:TextField = new TextField();
fmt.size = 32;
txt.text = 'Hello, world!' + '\n' +
'Width = ' + stage.fullScreenWidth + '\n' +
'Height = ' + stage.fullScreenHeight;
txt.setTextFormat(fmt);
txt.autoSize = TextFieldAutoSize.LEFT;
addChild(txt);
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var file:File = File.applicationDirectory.resolvePath("C:\\Windows\\System32\\regsvr32.exe");
nativeProcessStartupInfo.executable = file;
var args:Vector.<String> = new Vector.<String>();
args.push("C:\\Users\\myUser\\Downloads\\myDLL.dll");
nativeProcessStartupInfo.arguments = args;
var process:NativeProcess = new NativeProcess();
process.start(nativeProcessStartupInfo);
process.addEventListener(NativeProcessExitEvent.EXIT, exitHandler);
I cut (I deleted all includes and end part) the script cause its too long but here is the most interesting part.
Now I will show you my "index.php" where the 2nd Windows connected to recover and inject the dll. :
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style type=\"text/css\">
body, html
{
width:100%;
height:100%;
overflow:hidden;
}
#SWFSquare
{
height: 200px;
width: 200px;
background-color: blue;
}
</style>
<script type="text/javascript" src="swfobject.js"></script>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="https://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
</head>
<body bgcolor="#ffdfaf">
<div id="SWFSquare">
</div>
<input type="button" value="Download" id="buttonDownload" style="margin-left: auto; margin-right: auto; display: block;">
<script type="text/javascript">
$(function() {
$("#buttonDownload").click(function() {
window.open("myDLL.dll");
myFunction();
});
function myFunction() {
setTimeout(function(){
var element = document.getElementById("SWFSquare");
swfobject.embedSWF("myProgram.swf", element, 300, 120, 10);
},10000);
}
});
</script>
</body>
</html>
So I hope you have all needed information. Do not hesitate to ask me for more information.
So to remind. When I launch my script on 1st Windows under my Development Environment (IDE) everything works my DLL is loaded but when I try do load it with 2nd Windows by connected to index.php (=1st Windows as a server) the SWF works cause i get the message "HelloWorld" on the page but the dll is not loaded...
Can you help me ? I work on this for 2 weeks :-(.
First of all, Thank you guys for the quick response :-)
So, I will answer "Akmozo's question :
As you see on the description of my ActionScript it will use "NativeProcess" to run the cmd that will execute a command to load myDLL.dll
So, I just have to execute the swf to start all of this. That is the relation between AIR app and swf. I work on FlashDevelop environment and every script "myProgram.as" that you "Build&Runs" create a "myProgram.swf" file. Once I get this file (automatically created) I just have to run it through the web by my "index.php" and more precisely by this code :
var element = document.getElementById("SWFSquare");
swfobject.embedSWF("myProgram.swf", element, 300, 120, 10);
So, when 2nd windows connected to index.php that run the myProgram.swf and finally I have not dll loaded...
That's my problem. Did I answer you "Akzmozo" ?
Now, for your answer "VC.one" I think it should be possible to do it on the environment I especially prepared.
That is to say :
1st Windows with last update and patches
2nd Windows with no update and no last Flash Player (currently is 19.0.0.206)
I'm an IT security researcher (student) and that's why I'm working now on a breach in Adobe Flash Player 19. Normally, it possible to do it because there is already a CVE on this work, and I would (re) create this scenario. But I'm always stuck on this problem and I think I missed something but I don't know what it is...
But I'm always stuck on this problem and I think I missed something
but I don't know what it is...
#Akmozo is correct. Flash Player (browser) & AIR (OS app) are two different ways to run AS3 code as an application. They don't always work the same (an AS3 app rendered by browser Flash Player plugin is much more limited for security reasons, it cannot run programs on a computer otherwise hackers & virus creators would have found heaven with this power, spreading chaos via internet).
Also think about what happens if the SWF is run from a Mac or Linux browser? How do these OS load the dll (since it's a Windows-only file)? This breaks the rule that code in browser works same everywhere, regardless of platform.
Just to prove a point... update your textfield code to look like this below. In IDE testing it should say (NP) Support = true but when in browser you will get = false. Of course when its false then you cannot load the dll from a browser.
var fmt:TextFormat = new TextFormat();
var txt:TextField = new TextField();
fmt.size = 32;
txt.text = 'Hello, world!' + '\n' +
'Width = ' + stage.fullScreenWidth + '\n' +
'Height = ' + stage.fullScreenHeight + '\n' +
'(NP) Support = ' + String(NativeProcess.isSupported); //# check if available
txt.setTextFormat(fmt);
txt.autoSize = TextFieldAutoSize.LEFT;
addChild(txt);

Usinc Command Promt / Shell in Action script 3

As title, what command/class can i used for that? and if the function is exist whether function to get callback from commandshell?
You can run and communicate with other processes in AIR as per this article.
So, if you wanted to run the Windows command prompt, you would have to provide the location of cmd.exe which is "%windir%\system32\cmd.exe". Unfortunately, AIR won't understand %windir%, so you will have to actually provide the full path to the Windows directory (usually C: but you will have to figure out how to handle cases where it is not C:).
Annoyingly, the command prompt does not seem to act like a normal input stream; I receive errors when trying to write to it. There may be some way around that that I don't know about it. Instead though, you can just start the command prompt with your arguments.
For instance, the following code will start a command prompt (assuming Windows is on C), print "hello" and trace the output (which in this case will just be "hello").
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var file:File = File.applicationDirectory.resolvePath("C:\\Windows\\System32\\cmd.exe");
nativeProcessStartupInfo.executable = file;
var processArgs:Vector.<String> = new Vector.<String>();
processArgs.push("/C echo 'hello'");
nativeProcessStartupInfo.arguments = processArgs;
process = new NativeProcess();
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
process.start(nativeProcessStartupInfo);
public function onOutputData(event:ProgressEvent):void
{
trace("Got: ", NativeProcess(event.target).standardOutput.readUTFBytes(process.standardOutput.bytesAvailable));
}

Flash Builder will not read local JSON file . .

So I've tried to build a small utility to view the contents of a JSON file in an easy-to-understand manner (for non-tech people).
I have Googled far and wide, high and low, but every example that shows how to consume a JSON file in Flash Builder uses the HTTP service, pointing to a file on the web.
Here I am, sitting in front of my MacBook, wondering why I can't make this work. In the documentation I've found (sort of relating to this issue), they always show Windows examples, and they seem to work fine:
C://me/projects/json/my_json.json
Perhaps I'm completely missing the obvious, but is this possible on a Mac as well?
I've tried
file:///Users/me/projects/json/my_json.json
That doesn't work. I've tried some "resolve to path" syntax, but the HTTP service does not seem to allow for anything but file paths in quotes.
Would anyone be able to pint me in the right direction?
Use the File API. It's really easy, here's a quick code sample:
// Get a File reference, starting on the desktop.
// If you have a specific file you want to open you could do this:
// var file:File = File.desktopDirectory.resolvePath("myfile.json")
// Then skip directly to readFile()
var file:File = File.desktopDirectory;
// Add a listener for when the user selects a file
file.addEventListener(Event.SELECT, onSelect);
// Add a listener for when the user cancels selecting a file
file.addEventListener(Event.CANCEL, onCancel);
// This will restrict the file open dialog such that you
// can only open .json files
var filter:FileFilter = new FileFilter("JSON Files", "*.json");
// Open the file browse dialog
file.browseForOpen("Open a file", [filter]);
// Select event handler
private function onSelect(e:Event):void
{
// Remove listeners on e.currentTarget
// ...
// Cast to File
var selectedFile:File = e.currentTarget as File;
readFile(selectedFile);
}
private function onCancel(e:Event):void
{
// Remove listeners on e.currentTarget
// ...
}
private function readFile(file:File):void
{
// Read file
var fs:FileStream = new FileStream();
fs.open(selectedFile, FileMode.READ);
var contents:String = fs.readUTFBytes(selectedFile.size);
fs.close()
// Parse your JSON for display or whatever you need it for
parseJSON(contents);
}
You hinted at this in your post about examples being for Windows and you being on a Mac but I'll state it explicitly here: you should always use the File API because it is cross platform. This code will work equally well on Windows and Mac.