Copy link to clipboard
Copied
I'm using File.applicationStorageDirectory to store data of my app. Problem is when there are many windows users on one machine. One user has no access to others users data. I need to have common directory for all users.
In docs I see that all the OS-independent paths in Flex are based on spcific user directory. And the Application directory is read-only. So is there any directory which is common for all the users so I could store data there?
I know I could use explicit directory like:
var file:File = new File();
file.nativePath = "C:\\AIR Test";
But I need OS-independent, somewhat hidden (not in obvious place) directory.
Application | C:\Program Files\filename |
Application-storage | C:\Documents and settings\userName\ApplicationData\applicationID\Local Store |
Cache | C:\Documents and settings\userName\Local Settings\Temp |
Desktop | C:\Documents and settings\userName\Desktop |
Documents | C:\Documents and settings\userName\My Documents |
Temporary | C:\Documents and settings\userName\Local Settings\Temp\randomString.tmp |
User | C:\Documents and settings\userName |
variable between % are environment variables
(same for mac but they start with $)
you can access them using the NativeProcess class
here an example
...
package
{
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.system.Capabilities;
import flash.events.IOErrorEvent;
import flash.events.NativeProcessExitEvent;
import flash.events.ProgressEvent;
public class Test
{
function Test()
{
super();
_setupAnd
Copy link to clipboard
Copied
This is typically a security issue and the short answer is no you can't. Depending on admin settings in Windows or MAC users can share data or not between accounts, now that an AIR app somehow can ignore and bypass those OS security features and do whatever it wants is not likely on most system unless it was installed with admin privilege to start with.
Copy link to clipboard
Copied
"AIR app somehow can ignore and bypass those OS security features and do whatever it wants is not likely on most system unless it was installed with admin privilege to start with."
My problem started with admin who wanted to install my app for all windows users but he couldn't because I keep some important data in user specific application storage folder. So if the admin is installing the software I could bypass those security restrictions?
Copy link to clipboard
Copied
That's the idea, if a user with low privileges starts your app from his own account then likely your app won't have access to the entire system and might be blocked from using some folders. With admin privilege your app should have access to everything or at least what it needs to share across accounts.
Copy link to clipboard
Copied
A non-os-independent solution might be:
on Mac /Users/Shared can be a place to store stuff, on Windows it's C:\Users\Public, but the actual path is different on different Windows versions (and might be different on older OSX versions as well). I suggest to do some research
Copy link to clipboard
Copied
You can also try C:\ProgramData which is equivalent of C:\Users\All Users, but only exists since Windows Vista.
Here's a good read about the subject: What Is the ProgramData Folder in Windows?
Also note that "C:" might be the drive letter where Windows is running from, so do a split() on File.userDirectory to make sure you're on the system drive
Copy link to clipboard
Copied
Thanks.
I'm using windows 8 and I have C:\ProgramData and C:\Users\Public as well. So it appears I will need to detect OS version on system startup to find out which directory will keep my database. That's a problem especially that I don't know much about Mac filesystem.
Copy link to clipboard
Copied
Tracing File.userDirectory.nativePath and File.userDirectory.url on Mac shows the followings in the console:
[trace] 2/28/2018 09:28:54.094 [DEBUG] nativePath: /Users/tamas
[trace] 2/28/2018 09:28:54.096 [DEBUG] url: file:///Users/tamas
Here's the same trace on Windows
[trace] 2/28/2018 09:34:59.782 [DEBUG] native path: C:\Users\tamas
[trace] 2/28/2018 09:34:59.786 [DEBUG] url: file:///C:/Users/tamas
I think it's relatively easy to work something out from here which can work on both platforms.
Public dir on Mac is: /Users/Shared
Public dir on Windows can be: C:\Users\Public
Let me know if you need something to be tested on Mac
Copy link to clipboard
Copied
for something that can be READ and WRITE by All users
Under Windows you want to look for %ALLUSERSPROFILE%
see CSIDL (constant special item ID list)
and KNOWNFOLDERID
let's say you want to share a file foobar.txt under the same app
you will then use %ALLUSERSPROFILE%\MyApp\foobar.txt
under Windows XP it would be
C:\Documents and Settings\All Users\MyApp\foobar.txt
under Windows 10 it would be
C:\ProgramData\MyApp\foobar.txt
for Mac OS you want to look for /Library/Application Support
eg. /Library/Application Support/MyApp/foobar.txt
but this will ask for the admin password
so as a failsafe if you can't save it there
then save it here ~/Library/Application Support/MyApp/foobar.txt
but you could also uses the following
/Library/Preferences/MyApp/
~/Library/Preferences/MyApp/
and
/Library/MyApp/
~/Library/MyApp/
see macOS Library Directory Details
Now under mac if entering the admin password is a problem
but you still need to sahre the same file/path
then use /Users/Shared/
eg. /Users/Shared/MyCompany/MyApp/foobar.txt
or even /Users/Shared/Library/Application Support/MyApp/foobar.txt
Copy link to clipboard
Copied
Thanks, it's really helpfull.
But I cannot find any info about how to use KNOWNFOLDERID/CSIDL in as3/flex. I've searched different combinations in google, but couldn't find anything.
This doesn't work, show an error about invalid parameter:
f = new File('%ALLUSERSPROFILE%\MyApp\foobar.txt');
Copy link to clipboard
Copied
variable between % are environment variables
(same for mac but they start with $)
you can access them using the NativeProcess class
here an example
package
{
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.system.Capabilities;
import flash.events.IOErrorEvent;
import flash.events.NativeProcessExitEvent;
import flash.events.ProgressEvent;
public class Test
{
function Test()
{
super();
_setupAndLaunch();
}
private function onProcessOutput( event:ProgressEvent ):void
{
var data:String = _process.standardOutput.readUTFBytes( _process.standardOutput.bytesAvailable );
trace( "stdout: " + data );
}
private function onProcessError( event:ProgressEvent ):void
{
trace("stderr: " + _process.standardError.readUTFBytes( _process.standardError.bytesAvailable ) );
}
private function onProcessExit( event:NativeProcessExitEvent ):void
{
trace( "Process exited with " + event.exitCode );
}
private function onProcessIOError( event:IOErrorEvent ):void
{
trace( event.toString() );
}
private function _getPlatform():String
{
var platform:String = "";
var manufacturer:String = Capabilities.manufacturer;
if( (manufacturer != "") && (manufacturer.indexOf( " " ) > -1) )
{
var tmp:String = manufacturer.split( " " )[1];
platform = tmp.toLowerCase();
}
else
{
platform = manufacturer.toLowerCase();
}
return platform;
}
private function _setupAndLaunch():void
{
var filepath:String;
var args:Vector.<String> = new Vector.<String>();
switch( _getPlatform() )
{
case "windows":
// very weak way to do it
filepath = "C:\\Windows\\System32\\cmd.exe";
args[0] = "/C";
args[1] = "echo %USERNAME%";
break;
case "macintosh":
case "linux":
filepath = "/bin/sh";
args[0] = "-c";
args[1] = "echo $USER";
break;
}
var file:File = new File( filepath );
if( file.exists )
{
var startupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
startupInfo.executable = file;
startupInfo.arguments = args;
_process = new NativeProcess();
_process.addEventListener( ProgressEvent.STANDARD_OUTPUT_DATA, onProcessOutput );
_process.addEventListener( ProgressEvent.STANDARD_ERROR_DATA, onProcessError );
_process.addEventListener( NativeProcessExitEvent.EXIT, onProcessExit );
_process.addEventListener( IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onProcessIOError );
_process.addEventListener( IOErrorEvent.STANDARD_ERROR_IO_ERROR, onProcessIOError );
_process.start( startupInfo );
}
else
{
trace( "file '" + filepath + "' does not exists" );
}
}
}
}
Copy link to clipboard
Copied
Great, thanks!
About windows comment: "very weak way to do it" you mean that windows might be installed on different drive? In that case if I want to find cmd.exe on hard drive I should do something like this:
var sFile:File = File.desktopDirectory;
var appPath:String = File.desktopDirectory.nativePath;
var driveletter:String = appPath.substr(0,3);
sFile = sFile.resolvePath(driveletter+"WINDOWS/system32");
Also instead of
args[1] = "echo %USERNAME%";
I should use
args[1] = "echo %ALLUSERSPROFILE%";
Don't know much about mac but I think I'll use your advice and put the file in /Users/Shared/