I developed an Adobe Air App for a small intranet. All computers have been running Windows 7, but now are beginning to be replaced with Windows 10 systems. I can access the mapped drive "I" and the local "C" drive using the file class on Windows 7 machines, but only the mapped drive "I" on Windows 10.
Edit: Capabilities.localFileReadDisable returns false on both Windows 7 and Windows 10 systems.
****I could bypass the need for the local file if Air could get any specific information about the machine it is running on, serial number, mac address, computer name, etc. It really makes no difference what information I get, it just has to be unique to that computer. And using cookies isn't an option because they are volatile****
The following code accomplishes two things.
First, it displays the running version of the Air file and looks for a file on a mapped drive with the latest version available. If they are the same, the computer is running the latest version. If they aren't the same, the new version is displayed to the user, indicating the app should be updated.
Second, it grabs the name of the specific computer from a text file residing on the local drive. That name is used on reports to indicate which computer was being used. There is probably a far superior way to accomplish this, but on Windows 7, it works perfectly for me. Unfortunately, Windows 10 throws an error when trying to access the file on the local drive.
Error #2044: Unhandled ioError:. text=Error #2032: Stream Error. URL: file:///C:/machineName.txt
Any help would be greatly appreciated.
var appXML:XML = NativeApplication.nativeApplication.applicationDescriptor;
var ns:Namespace = appXML.namespace();
version_txt.text = "V"+appXML.ns::versionNumber;
// Define path to the version number
var updatePath:URLRequest = new URLRequest("file:///I:/air/update.txt");
// Define path to name of specific pc
var machineName:URLRequest = new URLRequest("file:///C:/machineName.txt");
// Define the URLLoaders
var updateLoader:URLLoader = new URLLoader();
function checkUpdate():void{
updateLoader.load(updatePath);
}
var nameLoader:URLLoader = new URLLoader();
function checkName():void{
nameLoader.load(machineName);
}
// Listen for when the file has finished loading.
updateLoader.addEventListener(Event.COMPLETE, loaderComplete);
function loaderComplete(e:Event):void
{
// The output of the text file is available via the data property
// of URLLoader.
if(Number(appXML.ns::versionNumber)<Number(updateLoader.data)){
update_txt.text = "UPDATE TO V"+updateLoader.data;
}
}
nameLoader.addEventListener(Event.COMPLETE, nameComplete);
var name_txt:String = new String;
function nameComplete(e:Event):void{
name_txt = nameLoader.data;
var holder:String = version_txt.text;
version_txt.text = name_txt+" ** "+holder;
}
Related
I am currently moving an ASP.NET application made by a third party from Windows to Linux. I read the documentation and nothing indicates this should be a problem, but sadly
var profile = new CredentialProfile(profileName, credentials) {
Region = RegionEndpoint.EUWest1
};
var netSDKFile = new NetSDKCredentialsFile();
netSDKFile.RegisterProfile(profile);
throws the following exception
Unhandled Exception: Amazon.Runtime.AmazonClientException: The encrypted store is not available. This may be due to use of a non-Windows operating system or Windows Nano Server, or the current user account may not have its profile loaded.
at Amazon.Util.Internal.SettingsManager.EnsureAvailable()
at Amazon.Runtime.CredentialManagement.NetSDKCredentialsFile..ctor()
Is the Amazon .NET SDK(or a part of it) not supported on Linux? If that is the case, is there a possible workaround?
For the most part there is very little that isn't supported on Linux that is supported on Windows. Off of the top of my head I can't think of anything besides NetSDKCredentialsFile which is due to the fact it uses Win32 API to encrypt credentials.
You can use SharedCredentialsFile to register a profile in the credentials file stored under ~/.aws/credentials. This is the same credential stored supported by all of the other AWS SDK and Tools.
Following on from Norm's answer, I found this resource that explained how to use Shared Credentials: https://medium.com/#somchat/programming-using-aws-net-sdk-9ce3f5119633
This is how I was previously using NetSDKCredentials, which won't work for Linux/Mac OS:
//Try this code on a non-Windows platform and you will see the above error
var options = new CredentialProfileOptions
{
AccessKey = "access_key",
SecretKey = "secret_key"
};
var profile = new CredentialProfile("default", options);
profile.Region = RegionEndpoint.USWest1;
NetSDKCredentialsFile file = new NetSDKCredentialsFile();
file.RegisterProfile(profile);
But I was then able to use this example to use SharedCredentials:
var credProfileStoreChain = new CredentialProfileStoreChain();
if (credProfileStoreChain.TryGetAWSCredentials("default", out AWSCredentials awsCredentials))
{
Console.WriteLine("Access Key: " + awsCredentials.GetCredentials().AccessKey);
Console.WriteLine("Secret Key: " + awsCredentials.GetCredentials().SecretKey);
}
Console.WriteLine("Hello World!");
You'll then be able to see your code is able to access the keys:
Access Key: A..................Q
Secret Key: 8.......................................p
Hello World!
I then used System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform() (as I am using this code on both Windows and Linux), to determine which credentials to use:
using System.Runtime.InteropServices;
//NETSDK Credentials only work on Windows - must use SharedCredentials on Linux
bool isLinux = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
if (isLinux) {
//Use SharedCredentials
} else {
//Use NetSDKCredentials
}
You may find this section of the AWS documentation helpful, too: https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html#creds-locate
I'm trying to help out a client with an Adobe AIR application that suddenly stopped working on Mac OS Sierra. I haven't developed the app myself, so I am trying to do my best to solve the problem. It's essentially a Flex application written in Actionscript 3. When I was debugging I can see that I am getting the following error:
[ERROR] Error #2032: Stream Error.
The way the application works is that it first makes a web request to the server and gets an XML with a number of songs. No problem there.
After that the application downloads the first song in the XML result and starts playing.
When the first song starts playing the application then downloads the second song in the XML-list, when that download is finished it starts downloading the next one and so forth. The files being downloaded seems to be rather large, a couple of MB's.
So the first download works just fine, but all the other track downloads fails with Stream Error #2032. It seems I dont get any response headers from the failed requests, only the first one. I have a crossdomain.xml on the server.
This app works just fine on Mac OS X El Capitan and Windows, but with Sierra I am getting this error. The code is not that complex, it makes an API URL Request with an URLLoader and saves the file to disk. I have also tried using URLStream instead, same issue.
This is some of the code for example:
public function downloadTrack(track:Object, storeName:String, apiKey:String):void {
this.setCurrentTrack(track);
this.urlParameters.storeName = storeName;
this.urlParameters.keystring = apiKey;
this.urlLoader = new URLLoader();
this.urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
this.urlRequest = new URLRequest("/api/" + 'download/' +
this.currentTrack.id + "?time=" + new Date().getTime());
this.urlRequest.method = URLRequestMethod.POST;
this.urlRequest.data = this.urlParameters;
this.addEventListeners();
this.urlLoader.load(this.urlRequest);
}
private function loaded(e:Event):void {
this.fileData = e.target.data;
writeFile();
}
private function writeFile():void {
var filePath:String = this.currentTrack.md5 + '.ogg';
var cacheFile:File = this.downloadDirectory.resolvePath('.' + filePath);
this.fileStream.addEventListener(Event.CLOSE, saveReady);
this.fileStream.openAsync(cacheFile, FileMode.WRITE);
this.fileStream.writeBytes(fileData,0,fileData.length);
this.fileStream.close();
}
In the addEventListeners()-method, event-listeners for the URLLoader is added, and it's the urlloader that fires the IOError.
A weird thing that has happened twice is that the app suddenly starts to work as normal and downloads all of the files successively. Then after a couple of minutes it starts acting up again and nothing works. I am really having a hard time to understand where the error lies. I am no Adobe AIR/Flex-expert, so maybe you can point me in the right direction? I am pretty close to giving up on this one.
Thanks!
Try to change the destination, probably you don't have permissions to
write there.
Use the latest AIR SDK
Would be much better if you will share the project where it reproduced so I could check on my machine
I'm having trouble getting the "file save picker" contract working in Windows Phone 10 for my Universal Windows App. I've added both "File Save Picker" and "Cached File Updater" declarations to the app manifest.
It works fine for me on a full Windows 10 computer (tested Mail and Mobile Word).
When I try it on a phone running WP10, I get a native exception A heap has been corrupted (parameters: 0x77344270) with error code 0xc0000374. No part of the stacktrace leads into my app.
My TargetFileRequested listener:
private async void FileSavePickerUI_TargetFileRequested(
FileSavePickerUI sender,
TargetFileRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
var filePath = GetSelectedFilePath();
args.Request.TargetFile = await StorageFile.GetFileFromPathAsync(filePath);
CachedFileUpdater.SetUpdateInformation(
args.Request.TargetFile,
CachedFileListener.CreateContentId(contentId, destination),
ReadActivationMode.NotNeeded,
WriteActivationMode.AfterWrite,
CachedFileOptions.None);
deferral.Complete();
}
I'm overriding OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs args), but it never gets called (app crashes before here).
Again, it only crashes in WP10. Win10 works fine.
Note: sometimes it doesn't appear to crash, but the updater method is still never called.
I have also tried this sample here:
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/FilePickerContracts
And I get similar results in that OnCachedFileUpdaterActivated is only ever called on desktop not phone.
I am trying to write a line of text to a text file. On the emulator or running from VS on the device, it works perfectly but when downloaded from the store, this code emits the error:
System.UnauthorizedAccessException: Access to the path
'C:\Data\Programs\{XXXXXX-XXXXX-XXX-XXXXX}\Install\Data\results.csv' is denied.
Here is my code:
var path = "Data/results.csv";
var uri = new Uri(path, UriKind.RelativeOrAbsolute).ToString();
using (var rd = new StreamWriter(uri, true))
{
var line = String.Format("{0};{1}", field1, field2);
rd.WriteLine(line);
rd.Close();
}
Am I doing something wrong? How can the code work on development?
Use:
var iso = IsolatedStorageFile.GetUserStoreForApplication();
It gets the storage that your app can use on users phone. You can then create directories (or files) for example:
iso.CreateDirectory("Data");
Why it works in emulator or on your device? I'd guess because MS does not care about access rights here.
I know it is possible to open files with their default application using the openWithDefaultApplication method of the file class. However, when you try to open an un-associated file (perhaps a proprietary or custom extension) using this method, a runtime error is thrown.
Is there anyway to prompt the user to open a file with a particular application like Windows does with it's "Open with..." dialog?
If not using the AIR the framework, via the NativeProcessAPI?
SOLUTION - using Pixel Elephants answer below as a foundation:
var processInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
processInfo.workingDirectory = file.parent;
processInfo.executable = new File("C:\\WINDOWS\\system32\\cmd.exe");
var args:Vector.<String> = new Vector.<String>();
args.push("/c");
args.push(file.name);
processInfo.arguments = args;
var process:NativeProcess = new NativeProcess();
try
{
process.start(processInfo);
}
catch(e:Error)
{
//give up - open the folder
file.parent.openWithDefaultApplication();
}
The "Open with..." dialog on Windows shows whenever you try to launch an application that does not have an associate file type. Launch the application with NativeProcess.start() and Windows will take care of either opening it with the correct program, or presenting a selection screen if there is no file type associated.
Alternatively, depending on what you are trying to do, you may be interested in associating file types with your AIR application. For instance, you can associate PNG files with your AIR app so that they will by default open in your AIR app (e.g. double-clicking a PNG file will launch your app with an INVOKE event specifying the PNG file that was opened). See http://livedocs.adobe.com/flex/3/html/help.html?content=File_formats_1.html under "Declaring file type associations" for more information.
Of course, your AIR app may have no capabilities to handle opening whatever file you are trying to open and you want a different program to handle it, in which case you can just use the first method which will let the operating system take care of launching the application with the correct program.
EDIT :
I got confused as to what Native Process actually does. NativeProcess launches executables - NOT files, so the method above won't work.
Instead of trying to open the file directly with NativeProcess, try opening the program that you want to open the file with and pass the file in as an argument. For instance, if you want to open a PNG file with some special image program, you would do something like this:
var imageEditorProgram:File = new File("C:/Path/To/Program.exe");
var args:Vector.<String> = new Vector.<String>();
args.push("C:/Path/To/Image.png");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = imageEditorProgram;
nativeProcessStartupInfo.arguments = args;
var nativeProcess:NativeProcess = new NativeProcess();
nativeProcess.start(nativeProcessStartupInfo);
This should open the image editing program with the image file passed in.
However, the downside with this method is that you can't just let the operating system determine which program to open the file with. You should be able to open a file browse dialog and allow the user to select the program to open the file with (similar to how the operating system does it). So, hopefully the following would do what you want:
var file:File = File.userDirectory;
file.addEventListener(Event.SELECT, selectHandler);
file.browse();
private function selectHandler(e:Event):void{
file.removeEventListener(Event.SELECT, selectHandler);
var filePath:String= file.nativePath;
var imageEditorProgram:File = new File(filePath);
var args:Vector.<String> = new Vector.<String>();
args.push("C:/Path/To/Image.png");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = imageEditorProgram;
nativeProcessStartupInfo.arguments = args;
var nativeProcess:NativeProcess = new NativeProcess();
nativeProcess.start(nativeProcessStartupInfo);
}
I haven't tested the above code, but it should open a file browse dialog allowing the user to select a program to open the file with (perhaps you should add a FileFilter to restrict the user to selecting only .exe), and then launch that program using NativeProcess.
For user-friendliness you should consider saving user preferences for filetypes (so instead of forcing them to go through the file browser every time they want to open a PNG, just remember that they like to open PNG's with AwesomeImageEditor.exe).