I have a PowerPoint content app that runs well in the desktop version of PowerPoint 2013 and 2016, but in PowerPoint Online it crashes (I believe) sometime during the execution of Office.context.document.settings.saveAsync() with this error:
I've traced it through this code:
var saveSelected = function (selected) {
if (Office.context && Office.context.document) {
Office.context.document.settings.set("selected", selected);
Office.context.document.settings.saveAsync();
}
else {
localStorage.setItem("selected", JSON.stringify(selected));
}
}
and can see the code run through this block as well as pop out of it to the parent function and finish execution, but a moment later it crashes and on a reload the setting hasn't been saved, so I'm assuming the crash happens somewhere inside the asynchronous save. The data I'm trying to save is an object that looks something like this:
{
siteUrl: "https://modtenant160315b.sharepoint.com",
type: "chart",
url:"/drives('b%21H9_EgioNdUWL9Etpw0KgzkCIo4W1XPBCt7YkrAyP0lx8OUvBlEQvQ52j2Fg2P-a0')/items('01DLGLVOTPCNS67WMCPBG22JL3VR4SOUWE')/workbook/worksheets(%27%7B00000000-0001-0000-0400-000000000000%7D%27)/charts(%27%7B00000000-0008-0000-0400-000002000000%7D%27)"
}
Any thoughts?
edit: I just added this to my app's landing page and it also causes the crash in PPT online, so it doesn't seem to take much:
Office.context.document.settings.set("dummySetting", "this is my setting");
Office.context.document.settings.saveAsync(function () {
var x = Office.context.document.settings.get("dummySetting");
$scope.sharepointUrl = x;
});
Turns out it was due to an outdated Office.js file. Switching from a local version to a hosted copy resolved the crash.
Related
I'm really confused about how to properly copy files and grant permission to execute e.g. an AppleScript file from a sandboxed application. I've read several articles and threads but the more I read, the more it confuses me.
The Task
My app needs to run a very simple AppleScript from an .scpt file. To do so (if I got this right), I need to copy this file into Users/thisUser/Library/Application \Scripts/.com.developerName.appName/. Before I can interact with this folder the user needs to grant access to that folder. This can be done by showing the user an NSOpenPanel where he can select the path. After confirmation the app has access to that path and I can copy the file and later run the script (App Sandbox User Selected File must be read/write). So far so good.
The Problem(s)
I find presenting a Finder window with an empty folder to select very user unfriendly, so I was wondering if there is anything else I can do. The closest what I have found regarding this problem is drag & drop the folder "into the app" - details can be found here.
I guess I'm not the only person ever who created a (sandboxed) app which needs to run specific scripts and I can't believe that the above approach is the only possible solution!? Therefore,
can I not just have a single window with an OK button and some information above that the app needs permission to write into that folder without showing an entire Finder window?
When I was looking around for solutions I also came across several settings for the app itself. Unfortunately, the docs are very limited here and I could not really find out what the specific settings actually do and how I could test them (admittedly this is because this is my first ever app for OSX and I have basically no clue what I'm doing). One of which is the Copy Files option in the Build Phase settings of the app:
This did sound promising to me since I thought that if I install the app it will automatically copy the file to the Scripts destination (probably with some sort of user prompt) and I can use it. But it does nothing. There is no copy happening at any time, even if I deselect the Copy only when installing setting. I have also tried the different destination folders which are available in the dropdown
and unfortunately also here I
could not find out what the destinations are
nor the file has been copied to any of the destination folders on build.
I know that people here don't really like to answer questions like this in much detail since it is probably more a lack of knowledge on my side but I would really appreciate it if someone could at least help me getting into the right direction and direct me to some resources which tackle my problem!
Thanks!
Well, it seems like I have found a solution which (at least for me) seems to be more or less user friendly and within Apple's sandbox guidelines.
Again, I'm very new to app development using Xcode and SwiftUI so I'm not sure if this solution is 100% "the right way of doing it". But since it took me ages to find this out, maybe someone else can use it and speed up development!
Solution
Like I have mentioned in my question above, I was trying to get rid of the (in my opinion) pretty annoying NSOpenPanel Finder prompt, where the user is supposed to select the folder. I further asked about the Copy Files setting in the app's Build Phase tab - it turned out that this was the solution! Unfortunately, I still don't have any clue about the list of destination which are presented in the dropdown but choosing Absolute Path and inserting
Users/$USER/Library/Application Scripts/$PRODUCT_BUNDLE_IDENTIFIER
did the job! The file gets copied on every build into the app's Application Scripts directory, from which I can run scripts outside the sandbox. 🙌
The next step was to create a class which executes the script using NSUserScriptTask
import Foundation
class ExecuteAppleScript {
var status = ""
private let scriptfileUrl : URL?
init() {
do {
let destinationURL = try FileManager().url(
for: FileManager.SearchPathDirectory.applicationScriptsDirectory,
in: FileManager.SearchPathDomainMask.userDomainMask,
appropriateFor:nil,
create: true)
self.scriptfileUrl = destinationURL.appendingPathComponent("CreateMailSignature.scpt")
self.status = "Linking of scriptfile successful!"
} catch {
self.status = error.localizedDescription
self.scriptfileUrl = nil
}
}
func execute() -> String {
do {
let _: Void = try NSUserScriptTask(url: self.scriptfileUrl!).execute()
self.status = "Execution of AppleScript successful!"
} catch {
self.status = error.localizedDescription
}
return self.status
}
}
Then I have created a Button View which handles the request
import SwiftUI
struct GenerateSignatureButtonView: View {
#State var status = ""
var body: some View {
VStack(alignment: .center) {
Button(action: {
self.status = ExecuteAppleScript().execute()
})
{
Text("Generate Signature")
}
Text("\(self.status)")
}
}
}
struct GenerateSignatureButtonView_Previews: PreviewProvider {
static var previews: some View {
GenerateSignatureButtonView()
}
}
When clicking the button a window pops up that the app wants access to control (in my case) the Mail app.
This user prompt repeats every time the user closes the app, reopens it and clicks the button again. I guess this can be somehow managed with Security-Scoped-Bookmarks but I'm not yet sure how. Furthermore, the error handling is not really working in this example since the popup appears after the successful message appears in the status field. This is probably another big thing to figure out... Asynchronous?
Well, hope this helps!
in my windows cordova application I try to download a file, with the following function (I just copied the code from here):
var uri = Windows.Foundation.Uri(contentUrl);
var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
var download = downloader.createDownload(uri, file);
download.startAsync().then(function () {
console.log("FOOO DONE !");
}, function(error) {
console.log("Error while downloading file ", error);
});
The contentURL and the file are valid and the files are generated as well. But the download is not starting at all, the file, which was created has just the size of 0kb.
And also no error and success is printed.
What could be wrong ? Thanks in advance.
I had the same problem using the exact same code; what fixed it for me is changing the name of the package name (in the package.appxmanifest file) and/or the build number. For some reason I have to do this procedure every day since the downloads don't seem to work when i boot the pc.
I came to the conclusion that it's either a hardware problem or a Visual Studio issue, the code works just fine (once it starts working).
I've developed a simple task pane add-in for testing Cyrillic characters, but when using body.getAsync() the Cyrillic characters appear to be encoding incorrectly.
Is there a workaround for getting Cyrillic html from an email body? Here’s the code I’m using:
var message = Office.context.mailbox.item;
message.body.getAsync(Office.CoercionType.Html, function (result) {
if (result.status === Office.AsyncResultStatus.Succeeded) {
$("#gridResult").html(result.value);
}
});
Here’s the result I get. All the Cyrillic characters are messed up.
Edit
I ran the code through the Visual Studio debugger and set a break point on the result.value prior to invoking .html(). The corrupted values are visible. The same thing happens when attaching to the IE Process using F12 developer tools:
This has been discovered to be a bug. It will be fixed in an upcoming update for C2R builds. Tentatively, if the build is AFTER 16.0.7117.1000, it should be fixed. This build number is not the exact number that will come up, but when a update comes out, if the number is AFTER that build, the fix should be in.
I can't confirm that this fix will make it until the actual patch comes out though.
The fixes for MSI Outlook 2016 and MSI Outlook 2013 will come afterward. I will update with the KB's and Patches for those updates once they are scheduled to be released.
Thanks for reporting this issue. It was a regression in Outlook Desktop and the fix will get to clients in about two months.
In the meantime the workarounds are calling the API with Office.CoercionType.Text
var message = Office.context.mailbox.item;
message.body.getAsync(Office.CoercionType.Text, function (result) {
if (result.status === Office.AsyncResultStatus.Succeeded) {
$("#gridResult").html(result.value);
}
});
Or using your addin in OWA (Outlook on Web).
I'm trying to use System.AppDomain.CurentDomain.ApplicationExit += new System.EventHandler(SomeFunction); to call the function SomeFunction when the application closes. In this case Unity 3D. But it doesn't work. I have no idea why. It is an editor script and is not an instance (static). What do you think I'm doing wrong?
There is no OnApplicationQuit method for Windows. According to the official documentation:
On Windows Store Apps and Windows Phone 8.1 there is no application quit event. Consider using OnApplicationFocus event when focusStatus equals false.
Therefore, instead of checking whether or not the application closed, you'll want to check whether or not the application obtained or lost focus.
In C#:
void OnApplicationFocus(bool focus)
{
if (!focus)
{
//Do something
}
}
The documentation does not explicitly mention it, but it can be assumed OnApplicationQuit is intended for Android only as iOS also does not support it.
You could use
function OnApplicationQuit() {
//put script in here
}
So that before the application quits it calls that function and does what ever is in the { and }
I have an firefox extension with the name myjavascriptfile.js,As I am new to this addon concepts,just I want to debug this script.So I am using the following statements in this file like
function LOG(text)
{
var consoleService = Components.classes["#mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
consoleService.logStringMessage(text);
}
observe: function(subject, topic, data)
{
LOG("observe called ");
}
I know this observe is getting called but I dont know where to see my log message.can some one tell me Where it is printing?
Please help.
That text goes to the Error Console. You might need to go to about:config and change devtools.errorconsole.enabled preference to true - the Error Console was removed from the menus by default while ago (strangely enough, I could still see it even without this pref). I think that on OS X you can still open the Error Console via Tools / Web Developer menu, on Windows you have to click the Firefox button and choose Web Developer menu there. Alternatively, Command-Shift-J should do as well.