Skip to main content
Inspiring
February 27, 2018
Answered

Best flex directory for all users

  • February 27, 2018
  • 4 replies
  • 1548 views

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

This topic has been closed for replies.
Correct answer zwetan_uk

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" );

            }           

        }

    }

}

4 replies

Inspiring
February 28, 2018

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

IbarimAuthor
Inspiring
March 1, 2018

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');

zwetan_ukCorrect answer
Inspiring
March 1, 2018

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" );

            }           

        }

    }

}

IGZN
Inspiring
February 27, 2018

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

IbarimAuthor
Inspiring
February 28, 2018

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.

IGZN
Inspiring
February 28, 2018

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

IGZN
Inspiring
February 27, 2018

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

Inspiring
February 27, 2018

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.

IbarimAuthor
Inspiring
February 28, 2018

"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?

Inspiring
February 28, 2018

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.