WinRT - Starting/Registering IBackgroundTask in universal application - javascript

I would like to start my IBackgroundTask when my application starts up.
I have added my task to the .appxmanifest.xml file, and my extensions tag now looks like this
<Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="CordovaApp.Library.UploadTask">
<BackgroundTasks>
<Task Type="systemEvent" />
<Task Type="timer" />
</BackgroundTasks>
</Extension>
</Extensions>
My IBackgroundTask class is called UploadTask and is held in another project which has the outtype set to Windows Runtime Component.
Here is a cut down version of the code, so you can see the namespace etc
namespace CordovaApp.Library
{
public sealed class UploadTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
// connectionProfile can be null (e.g. airplane mode)
if (connectionProfile != null && connectionProfile.IsWlanConnectionProfile)
{
// custom code here
}
}
}
}
I have added a reference to this project to my universal runtime component project.
Everything builds fine.
Now to start the application, i guess i have to use WinJs, so i have the following code.
var uploadTaskName = 'UploadTask';
var tasks = Windows.ApplicationModel.Background.BackgroundTaskRegistration.allTasks;
var uploadTaskFound = false;
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].Value.name == uploadTaskName) {
successCallback();
return;
}
}
Windows.ApplicationModel.Background.BackgroundExecutionManager.requestAccessAsync().then(function() {
var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
builder.name = "Upload Task";
builder.taskEntryPoint = "CordovaApp.Library.UploadTask";
builder.setTrigger(new Windows.ApplicationModel.Background.TimeTrigger(15, false));
return builder.register();
}).done(function () {
successCallback();
}, function(err) {
errorCallback(err);
});
Now the requestAccessAsync method always throws an exception of
0x80004005 - JavaScript runtime error: Unspecified error
WinRT information: The application is not lock-screen capable.
Have a registered everything correctly? I am running this via Visual Studio 2013 on a laptop.

Seems that because the app was already installed, the permission was not given.
By uninstalling the application, and re-running it, i was then prompted to allow/disallow the background service to run. Checked allow, and now seems to work

Related

Build version information in Application Insights telemetry (client-side)

We have a SPA hosted on ASP.NET application. We want to track the build version of the whole app.
So this telemetry initializer
public class VersionInfoTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.Component.Version =
typeof(Startup).Assembly.GetName().Version.ToString();
}
}
will be used in Gloabal.asax
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
var tc = TelemetryConfiguration.Active;
tc.InstrumentationKey = ConfigurationManager.AppSettings["AI Instrumentation Key"];
tc.TelemetryInitializers.Add(new VersionInfoTelemetryInitializer());
...
}
}
Server-side telemetry will have version information appended. But I am not able to do the same for the client-side telemetry. I have tried this
var appInsights = window.appInsights || function(config) {
// standard js snippet from azure portal
}({
instrumentationKey: '{{INSTRUMENTATIONKEY}}'
});
window.appInsights = appInsights;
window.appInsights.context.application.ver = 'some version number';
which results in following JS error
Uncaught TypeError: Cannot read property 'application' of undefined
I also tried
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(versionInfoTelemetryInitialier);
});
function versionInfoTelemetryInitialier(envelope) {
var telemetryItem = envelope.data.baseData;
telemetry.context.component.version = 'some version number';
}
which will warn with following message
AI: TelemetryInitializerFailed message:"One of telemetry initializers failed, telemetry
item will not be sent: TypeError" props:"{exception:[object Error]{ stack: 'TypeError:
Unable to get property 'component' of undefined or null reference\n at
versionInfoTelemetryInitialier (https://localhost:44301/landing/index:107:9)\n at
n.prototype._track (https://az416426.vo.msecnd.net/scripts/a/ai.0.js:1:65589)\n at
n.prototype.track...
What should I do so that client-side telemetry has version information attached.
i think your second attempt is very close. you need to do it via the queue, to make sure it occurs after all the AI scripts are actually loaded, so i think this is correct:
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(versionInfoTelemetryInitialier);
});
but in your initializer you switched from context.application.ver in your first example, to context.component.version in your second.
the javascript SDK is documented on the github repo:
https://github.com/Microsoft/ApplicationInsights-JS/blob/master/API-reference.md
and the examples there show:
context.application.ver: string
context.application.build : string
so shouldn't that initializer method be:
function versionInfoTelemetryInitialier(envelope) {
var telemetryItem = envelope.data.baseData;
telemetry.context.application.ver = 'some version number';
}

Importing JavaScript file into Swift file

I am trying to execute a JavaScript SDK from within a Swift application. I am unable to find the file however. I added the file to the project using cmd + click project -> Add files to "projectName" -> Add file and move into projectName/ folder.
I am still unable to get the file and run it inside a JSContext.
Where am I going wrong?
Here is my code (isOK is just used for a test case):
import Foundation
import JavaScriptCore
public class Wrapper {
public var isOK: Bool
var jsContext: JSContext
init (pathToSdk: String) {
let virtualMachine = JSVirtualMachine()
self.jsContext = JSContext(virtualMachine: virtualMachine)
if let sdkBundle = Bundle.main.path(forResource: pathToSdk, ofType: "js") {
let bundleString = try! String(contentsOfFile: sdkBundle)
self.jsContext.evaluateScript(bundleString)
print("Successfully initialised JavaScript context")
self.isOK = true
} else {
print("Unable to fetch SDK bundle at path: \(pathToSdk)")
self.isOK = false
}
}
}
I call it in my test:
func testIsOK() {
let wrapper = Wrapper(pathToSdk: "sdk").isOK
XCTAssertEqual(wrapper, true)
}
And my folder structure:
Thanks and sorry if this is a silly question, I'm brand new to Swift.

Access to files from extension return sometimes NS_ERROR_FILE_IS_LOCKED

Our extension (Addon SDK) looking for new files in folder C:\scan and send it to server. Every second extension look for latest file creation time and defined it as latest.(compare new file creation time and file creation time 1 sec ago.)
Files put to C:\scan from scanner Brother 7050 on Windows 7.
But sometimes into console.error we see:
Exception
message: "Component returned failure code: 0x8052000e (NS_ERROR_FILE_IS_LOCKED)
[nsIFileInputStream.init]",
result: 2152857614,
name: "NS_ERROR_FILE_IS_LOCKED"
I think Brother 7050 application have no time to unlock file before our extension can start to read it.
Q: How we can read latest file in folder true way without read file lock error?
/*
adr- folder path
array2 - array for search
mode - search or not search in array2 (0-1)
*/
function getfilelist(adr,array2, mode)
{
filelist2=[];
filelist2[0]="";
filelist2[1]=0;
var file = new FileUtils.File(adr);
var enumerator = file.directoryEntries;
while (enumerator.hasMoreElements())
{
inner = enumerator.getNext().QueryInterface(Ci.nsIFile);
if (inner.isFile())
{
namearray=inner.leafName.split(".");
r=namearray[namearray.length-1];
if (r=="jpg" || r=="jpeg")
{
if (mode==0)
{
if (inner.lastModifiedTime>filelist2[1])
{
filelist2[0]=inner.leafName;
filelist2[1]=inner.lastModifiedTime;
}
}
else if (mode==1)
{
if (inner.lastModifiedTime>array2[1] && inner.isReadable()==true)
return inner.leafName;
}
}
}
}
if (mode==0)
{
return filelist2;
}
return false;
}
The reason why you see NS_ERROR_FILE_IS_LOCKED is most likely that the file is still being written and you are trying to access it too early. However, it is also possible that some other software immediately locks the file to check it, e.g. your anti-virus.
Either way, there is no way to ignore the lock. Even if you could, you might get an incomplete file as a result. What you should do is noting that exception and remembering that you should try to read that file on next run. Something along these lines:
var {Cr} = require("chrome");
var unaccessible = null;
setInterval(checknewfiles, 1000);
function checknewfiles()
{
var files = getfilelist(...);
if (unaccessible)
{
// Add any files that we failed to read before to the end of the list
files.push.apply(files, unaccessible);
unaccessible = null;
}
for (var file of files)
{
try
{
readfile(file);
}
except(e if e.result == Cr.NS_ERROR_FILE_IS_LOCKED)
{
if (!unaccessible)
unaccessible = [];
unaccessible.push(file);
}
}
}
For reference:
Components.results
Chrome authority
Conditional catch clauses
for..of loop

How to save an image in Windows Phone 8.1 using WinJS

I am looking to migrate my Windows 8 app to Windows Phone 8.1 using WinJS. I had used picker.pickSaveFileAsync in Windows 8 which is not supported for WP 8.1.
I had then referred the official samples from http://code.msdn.microsoft.com/windowsapps/Simple-Imaging-Sample-a2dec2b0
The Javascript version in the sample does not save on Windows Phone 8.1 when the Save As button is clicked and it returns the below error when `getFileAsync is called:
0x80004005 - JavaScript runtime error: Unspecified error
When clicked on Save, it returns a Read Only error. I had tested the sample in Lumia 520 also. I get the same error in the phone.
In Windows Phone you cannot get write access to files returned from a FileOpenPicker. You have to use a FileSavePicker to do this. With the help of a coworker I was able to get a sample working that can open and then re-save a file under a new name starting from the "Blank" Windows Phone App template
Inside of your default.html create two buttons:
<button id="choose">Choose a Photo</button>
<button id="save">Save a Photo</button>
Replace default.js with the following:
(function () {
"use strict";
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var origFile = null;
function pickPhoto() {
var picker = new Windows.Storage.Pickers.FileOpenPicker();
var enumerator = Windows.Graphics.Imaging.BitmapDecoder.getDecoderInformationEnumerator();
enumerator.forEach(function (decoderInfo) {
decoderInfo.fileExtensions.forEach(function (fileExtension) {
picker.fileTypeFilter.append(fileExtension);
});
});
picker.pickSingleFileAndContinue();
}
function loadPhoto(file) {
origFile = file;
}
function savePhotoPicker(file) {
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.fileTypeChoices.insert("JPEG file", [".jpg"]);
picker.pickSaveFileAndContinue();
}
function savePhoto(src, dest) {
src.copyAndReplaceAsync(dest).done(function () {
console.log("success");
})
}
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll());
document.getElementById("choose").addEventListener("click", pickPhoto);
document.getElementById("save").addEventListener("click", savePhotoPicker);
}
if (args.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.pickFileContinuation) {
loadPhoto(args.detail.files[0]);
}
if (args.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.pickSaveFileContinuation) {
savePhoto(origFile, args.detail.file);
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your application is suspended, call
// args.setPromise().
};
app.start();
})();
If you are creating the file yourself, make sure to set the ImageProperties for it before saving.
Sorry about the broken sample, I'll get that reported to the sample owner.

MSScriptControl Issue on Windows Server 2008

So I'm using the MSScriptControl to run some javascript in my app and I want to be able to get some information about any errors the script may cause.
MSScriptControl.ScriptControlClass script = new MSScriptControl.ScriptControlClass();
try
{
script.Language = "JScript";
script.Timeout = 15000;
script.Eval(Code);
}
catch (Exception ex)
{
MSScriptControl.Error err = script.Error;
ret = new Exception("Error on line: " + err.Line + ", Description: " + err.Description);
}
The code works fine on my development machine, a Windows 7 box, and gives me a line number with an error. So I happily publish and push it to the production machine which always tells me the error occurred at line 0 and no description is provided.
I tried going to http://www.microsoft.com/download/en/details.aspx?id=1949 to download the latest version but installing it had no effect. I also set the property Embed Interop Types to false as well as copying my own msscript.ocx file into the Windows 2008 server's system32 directory but neither of these attempts resolved anything.
Anyone have any recommendations?
If you want to do it in all native c# without any 3rd party or "component" external dependencies use a CodeDomProvider with a tiny JScript bootstrap, like this:
private static readonly MethodInfo eval = CodeDomProvider
.CreateProvider("JScript")
.CompileAssemblyFromSource(new CompilerParameters(), "package e{class v{public static function e(e:String):Object{return eval(e);}}}")
.CompiledAssembly
.GetType("e.v")
.GetMethod("e");
private static object JsEval(string jscript)
{
try
{
return eval.Invoke(null, new[] { jscript });
}
catch (Exception ex)
{
return ex;
}
}
that creates a JsEval(string) method that you can use anywhere in your code to "eval" a string as JavaScript (well JScript)... So calling:
MessageBox.Show("" + JsEval("2 + 2")); // 4
MessageBox.Show("" + JsEval("(function(){ return 3+7; })();")); // 10
MessageBox.Show("" + JsEval("function yay(a) { return a + 1; } yay(2);")); // 3
depending on your use you may not want to instantiate these members statically. if you want to manipulate complex objects you will need create a wrapper to reflectively extract data (or you could cast as the appropriate JScript counterpart, but I've never tried this as you'd have to include the JScript assemblies).
here is an example of a wrapper class that does everything JavaScript will let you do natively, adding anymore high level functionality would probably be cumbersome enough so that you'd be better off either extracting the members into a dictionary / hash table OR alternatively serializing and deserializing on the other end
private class JsObjectWrapper : IEnumerable
{
public readonly object jsObject;
private static PropertyInfo itemAccessor = null;
private static MethodInfo getEnumerator = null;
public JsObjectWrapper(object jsObject)
{
this.jsObject = jsObject;
if (itemAccessor == null)
{
itemAccessor = jsObject.GetType().GetProperty("Item", new Type[] { typeof(string) });
}
if (getEnumerator == null)
{
getEnumerator = jsObject.GetType().GetInterface("IEnumerable").GetMethod("GetEnumerator");
}
}
public object this[string key]
{
get { return itemAccessor.GetValue(jsObject, new object[] { key }); }
set { itemAccessor.SetValue(jsObject, value, new object[] { key }); }
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)getEnumerator.Invoke(jsObject, null);
}
}
you can see this in action by doing this:
var jsObj = JsEval("var x = { a:7, b:9 };");
var csObj = new JsObjectWrapper(jsObj);
MessageBox.Show("a: " + csObj["a"]); // a: 7
MessageBox.Show("b: " + csObj["b"]); // b: 9
csObj["yay!"] = 69;
foreach (string key in csObj)
{
MessageBox.Show("" + key + ": " + csObj[key]); // "key": "value"
}
i personally have used code similar to this to great effect at one point or another and can vouch for it's availability and runnability inside a server environment.. I hope this helps -ck
Regarding the problem you face just some thoughts:
according to the link you provided this control neither supports Windows 7 nor Windows 2008
it might be a security issue with regards to COM/UAC etc.
it might be a problem because of bitness if you compiled for AnyCPU, try using x86
Regarding possible alternatives:
Using JScript you can build an evaluator rather easily which is supported anywhere .NET 4 runs (including Windows Server 2008).
Using JInt as a JavaScript interpreter

Categories

Resources