I have a simple code for FolderPicker:
var diagFolder = new FolderPicker();
diagFolder.FileTypeFilter.Add("*");
var outputFolder = await diagFolder.PickSingleFolderAsync();
if (outputFolder == null) { return; }
It works well on first launch. However, upon second call, the Select Folder button is disabled and user cannot choose the same folder although it is perfectly valid. I have to go back a level and re-enter the folder if I want to pick that same folder.
Anyone is having this problem and know a fix for it?
EDIT: as of my guess, it is not actually UWP code problem, but Windows problem, so I posted a feedback here: https://aka.ms/AA1hloz . I think voting there should help.
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!
I'm trying to Update Links of inDesign documents using ExtendScript, but whenever I open the document the dialog appear asking me if I want to update the link.
I want to do it in the background, so is there a way to prevent this or any dialog from showing?
Thanks
I have found a solution for this particular dialog. This prompt can be disabled from the UI, but also, as with other setting of the application, you can also do in the code.
So here is what I implemented.
//Save the current application setting.
var currentAppSettings = {checkLinksAtOpen: app.linkingPreferences.checkLinksAtOpen};
//Set the value to false to prevent the dialog from showing.
app.linkingPreferences.checkLinksAtOpen = false;
//do some stuff ...
//Set the value back to its original value.
app.linkingPreferences.checkLinksAtOpen = currentAppSettings.checkLinksAtOpen;
There is a setting in InDesign for checking links. What if you modified the default settings in InDesign? Perhaps if you uncheck "Check Links Before Opening Document" it will bypass the dialogue.
Using Selenium IDE with Windows7 and Firefox, an automatic click on a link may produce either a new tab or a new window.
close() closes the original window or tab, not the new one. Maybe if I had the ID of the newly created one I could select it and then close it but I don't know how to do this automatically. I've asked on the Selenium forum and read the questions here, but they focus on WebDriver, not the IDE. Any help would be appreciated!
Stig
I had same problem and found a solution:
click on link that opens the new tab
add command waitForPopUp
set focus to new tab via command selectPopUp
make your verifications or other commands regarding to your content in new tab
use command close to close tab
use command selectWindow to set focus to the old window
Screenshot of my Selenium IDE commands:
That works for me.
Use selectWindow(windowID) command to switch to new window in Se IDE. You can select new window by its windowID/name/title.
Hope this helps...
Agreed with surya use selectWindow(windowID), you can get the window title by right click on the page check the option verifyTitle and in front of that you have your Title. Hope it helps out.
selectWindow(windowID) has option to mention title of the webpage/window as a way to identify the target window.
syntax = selectWindow title=My Special Window
note: title = title of webpage that is visisble in webpage's title bar. Or right click on webpage and select menu "Page source". In source doc, select the text between ....
So if the title of webpage = My Special Window, you will see My Special Window.
Hope this will help.
Swasati Paul
You could use the iterator to iterate amongst the windows, close the new window and come back to the originalWindow. And you can put this under the try block because it will only iterate if a new window opens. Or else, it will continue executing normally in the current window.
try{
Set <Strings> ids = driver.getWindowHandles();
Iterator <String> it = ids.iterator();
String currentPage = it.next();
String newPage = it.next();
driver.switchTo().window(newPage);
driver.close(); //it will close the new window and automatically come back to the currentPage
}
finally
{
//continue with your script here
//this script will run regardless of the execution of the execution of the try block
}
When my add-on installs it needs to prompt the user to get a username or something like that. After that it stores it and shouldn't ask again. Where would I place this prompt? install.rdf? browser.xul?
There is no explicit mechanism to run code when the extension installs - you should simply do it when your extension runs for the first time. The easiest approach would be checking whether the user name is already set up. If it is not - show the prompt.
It is not recommended to show a modal dialog, those are extremely annoying to users, especially when they suddenly appear during Firefox start-up. You should instead open your page in a tab. A slight complication: Firefox might be restoring a previous session when it starts up. If you open your page too early the session restore mechanism might replace it. So you should wait for the sessionstore-windows-restored notification, something like this should work:
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
var observer = {
observe: function(subject, topic, data)
{
Services.obs.removeObserver("sessionstore-windows-restored", this);
var browser = window.getBrowser();
browser.loadOneTab("chrome://...", {inBackground: false});
},
QueryInterface: XPCOMUtils.generateQI([
Components.interfaces.nsIObserver,
Components.interfaces.nsISupportsWeakReference
])
};
Services.obs.addObserver("sessionstore-windows-restored", observer, true);
A final complication is that your code is probably running from a browser window overlay - meaning that there will be multiple instances of your code if the session restored contains more than one window. You probably want the code above to run only once however rather than opening your first-run page in every browser window. So you will have to coordinate somehow, maybe via preferences. A slightly more complicated but better solution would be having a JavaScript code module in your extension - code modules are only loaded once so you wouldn't have a coordination issue there.
Try using an addonlistener https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonListener#onInstalling%28%29
Or by using the preferences: https://stackoverflow.com/a/958944/1360985
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.