locked
How to write to storage from a background task

    Question

  • I am trying to write into a text file inside the MyDocuments folder from within the a backgroundTask - IU am using this code

     

     function writeToFile(inputStr) {

      Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("sample.txt",
                Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
                sampleFile = file;
                if (sampleFile != null && inputStr != null) {
                    sampleFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
                        var outputStream = stream.getOutputStreamAt(stream.size);
                        var writer = new Windows.Storage.Streams.DataWriter(outputStream);
                        writer.writeString(inputStr);
                        writer.storeAsync().then(function () {
                            outputStream.flushAsync().then(function () {
                                console.log("Channel Uri Saved to file");
                            });
                        },
                        function (error) {
                            console.log("error" + error);
                        }
                        );
                    });
                }
            });

    }

    It writes it the first time but I expect that each time the task is triggered (and it does get triggered), the file gets overwritten with the contents of inputStr. However, I am getting this message

    "This file came from another computer and might be blocked to help protect this computer." and then it goes into  the error handler where error = "Access is Denied"

    Any idea why this could be happening?

     

    Thanks!

    Tuesday, December 06, 2011 11:41 PM

Answers

  • Thank you very much! I believe that was it - I was calling the close() outside the promise of some of the functions that I was doing in the background task because of which the task was either exiting abnormally or not exiting at all!
    • Marked as answer by optimus_p Tuesday, December 13, 2011 9:58 PM
    Tuesday, December 13, 2011 5:32 PM

All replies

  • Optimus,

    I would think you should get the same error if this was in your main program.  As a simple test, take this same code and put it in a new blank project and see if the problem reproduces to verify this has no bearing on the fact that this is in a background task.  If it does repro we can troubleshoot the simpler case first!

    -Jeff


    Jeff Sanders (MSFT)
    Friday, December 09, 2011 2:51 PM
    Moderator
  • OK - I just did that - I moved the file creation code into a new app that calls this function each time the app is launched - I see the file being created the first time and over-written (I append a timestamp to each write, using Javascript's date in millis) with the new string. So this is definitely not an issue when i have this operation in the main program.

    Thanks!

    Friday, December 09, 2011 6:31 PM
  • Thanks Opti!

    I will try and repro this problem with your code locally from a background task.  I will update you later on what I find!

    -Jeff


    Jeff Sanders (MSFT)
    Friday, December 09, 2011 6:40 PM
    Moderator
  • ..and just a FYI, I believe that there is a problem with any code that is run as an Async operation in the backgroundTask, be it file writing or anything else. The string I am writing is obtained from another Async operation which is failing. I am putting tileNotifications in various stages of my code as "debug points" to see where it is failing and I notice its any Async call. Stepping through in debug is not proof of working because then we are are halting the regular execution flow and things seem to work slightly more consistently

     

    Thanks!

    Friday, December 09, 2011 7:00 PM
  • You must have a problem with your code,
    I took the javascript version of the Background Task Sample and put this code in program.js and backgroundtask.js (note that I do NOT have a global file object but use the file object passed to the completion function:
     function writeToFile(inputStr) {
    
            Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("sample.txt",
                Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
                file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
                    var outputStream = stream.getOutputStreamAt(stream.size);
                    var writer = new Windows.Storage.Streams.DataWriter(outputStream);
                    writer.writeString(inputStr);
                    writer.storeAsync().then(function () {
                        outputStream.flushAsync().then(function () {
                            // stream contents have been saved.
                 
                        });
                    });
                });
            });
    
            
        }
    

    Then in program.js:
     function registerSampleJavaScriptBackgroundTask() {
            //
            // Prepare to create the background task.
            //
    
            try {
    
                var s = "RegisterTask - Time is: ";
    
                // Create a date object.
                var dt = new Date();
                s += dt.getTime().toString();
    
                writeToFile(s);
    
    

    and in backgroundtask.js:
    (function() {
        "use strict";
    
        // 
        // The background task instance's activation parameters are available via Windows.UI.WebUI.WebUIApplication.backgroundTask
        //
        var cancel = false,
            progress = 0,
            backgroundTask = Windows.UI.WebUI.WebUIApplication.backgroundTask;
    
        console.log("Background " + backgroundTask.taskInstance.task.name + " Starting...");
    
        function writeToFile(inputStr) {
    
            Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("sample.txt",
                Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
                file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
                    var outputStream = stream.getOutputStreamAt(stream.size);
                    var writer = new Windows.Storage.Streams.DataWriter(outputStream);
                    writer.writeString(inputStr);
                    writer.storeAsync().then(function () {
                        outputStream.flushAsync().then(function () {
                            // stream contents have been saved.
    
                        });
                    });
                });
            });
    
    
        }
           
                var s = "Time is: ";
    
            // Create a date object.
                var dt = new Date();
                s += dt.getTime().toString();
    
                writeToFile(s);
    
    

    In the manifest: I added capability to access the Document Library and Declaration for File Type Association for .txt files (otherwise you would get access denied trying to write to the documents folder).
    I built and deployed the project.
    Then I ran BackgroundTaskSample from the Start screen, selected scenario 2 and registered the task.
    I verified the file was created and text was written to the file.
    I unplugged the network cable two times and verified I had a different time stamp each time.
     
    Try the same steps with that sample and see if you are successful.  If you are, then you can compare the settings and code in that sample to your code.
    -Jeff

    Jeff Sanders (MSFT)
    Friday, December 09, 2011 8:55 PM
    Moderator
  •  

    Ok - so I uninstalled my version of the background task app and took a fresh start/copy with the sdk sample and is what I did to the backgroundtask.js file inside the BackgroundTaskSample.

    I havent touched program.js and all I want to achieve here is to have the backgroundTask triggered when I disconnected my internet cable and reconnect - and when the task triggers, I expect it create a file and write a unique timestamp on each trigger.  I have modified the manifest to access the document library and added the extension node for txt.

    I don't need to modify anything in program.js, I need all the work to be done in the backgroundTask which is what this code is doing below. Then, I built the App and Ran it in VS 2011 and it launches the main screen where I register th BackgroundTask in Javascript. I then disconnect and reconnect the internet - I see that the sample.txt file gets created with a line "Time is: 1323471048656" - As expected.

    However, every subsequent trigger (disconnect and reconnect of internet) does nothing to the file. I will now put break points to see where it is stalling, though like I said, thats not the real flow. I have code where I am sending "debug" notifications to the tile to see what messages I am getting, I will put that in to this code as well now..

     

    (function() {
        "use strict";
    
        // 
        // The background task instance's activation parameters are available via Windows.UI.WebUI.WebUIApplication.backgroundTask
        //
        var cancel = false,
            progress = 0,
            backgroundTask = Windows.UI.WebUI.WebUIApplication.backgroundTask;
    
        console.log("Background " + backgroundTask.taskInstance.task.name + " Starting...");
    
        //
        // Associate a cancellation handler with the background task.
        //
        function onCanceled(cancelSender, cancelReason) {
            cancel = true;
        }
        backgroundTask.taskInstance.addEventListener("canceled", onCanceled);
    
        function writeToFile(inputStr) {
    
            Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("sample.txt",
                Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
                file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
                    var outputStream = stream.getOutputStreamAt(stream.size);
                    var writer = new Windows.Storage.Streams.DataWriter(outputStream);
                    writer.writeString(inputStr);
                    writer.storeAsync().then(function () {
                        outputStream.flushAsync().then(function () {
                            // stream contents have been saved.
    
                        });
                    });
                });
            });
        }
    
        var s = "Time is: ";
        // Create a date object.
        var dt = new Date();
        s += dt.getTime().toString();
    
        writeToFile(s)
    
    
    })();
    


    Friday, December 09, 2011 11:02 PM
  • ..and here's what else I just discovered - when I run the app the first time, I see an instance of the sample app task in task manager. I see an instance of BackgroundTaskSample running there. Now, unless that instance is removed/killed, the task will not run again and so the file is never updated! Each time i go to the task manager and end the task and then do the disconnect/reconnect trigger - the file is overwritten successfully!
    Friday, December 09, 2011 11:55 PM
  • I believe I have narrowed the problem to having to explicitly kill the existing/older task before being sure that the file is over-written with a new value. I tried this multiple times and consistently found that each time I kill the task and trigger it again (just trigger, not re-launch the app), I get a successful overwrite. However, if I apply the trigger when there is an existing task running (seen in task manager, even when the app is not in the foreground or open in the background), the file is NOT over-written.

    Can you please verify if you are seeing the same issue and suggest something for this?

    Thanks!

    Tuesday, December 13, 2011 4:01 AM
  • Hi Opti,

    Aha!!!! Thanks for sharing your code.

    That is a lot different from my code.  I kept that loop and timer in there to keep the thread alive.  Also you are not calling close(); when you are done which would close the background task (that is why you have to kill it).  I will try your code today.

    -Jeff


    Jeff Sanders (MSFT)
    Tuesday, December 13, 2011 3:18 PM
    Moderator
  • Thank you very much! I believe that was it - I was calling the close() outside the promise of some of the functions that I was doing in the background task because of which the task was either exiting abnormally or not exiting at all!
    • Marked as answer by optimus_p Tuesday, December 13, 2011 9:58 PM
    Tuesday, December 13, 2011 5:32 PM
  • OK great,

    Let me know how your testing goes!

     


    Jeff Sanders (MSFT)
    Tuesday, December 13, 2011 7:25 PM
    Moderator
  • It is working as expected now that I have the close call in the correct place (that's inside the promise complete of my last Async operation) - I am seeing the file being over-written each time the task is triggered.

    Thanks!

    Tuesday, December 13, 2011 9:58 PM