Setting NSUserAutomatorTask variables without requiring Automator Workflows to declare that variable
Asked Answered
A

1

6

I'm using NSUserAutomatorTask to launch a .workflow file, created via the Automator app in macOS 10.13.

I'm passing variables to the workflow via the variables property:

https://developer.apple.com/documentation/foundation/nsuserautomatortask/1418099-variables

The parent app is sandboxed. The script is located in the .applicationScriptsDirectory and runs successfully when variables are not set, or when the same variables are set from the app and declared in the workflow.

if let workflow = try? NSUserAutomatorTask(url: url) {

    workflow.variables = ["randomVariable": "value"] // NOTE

    workflow.execute(withInput: nil) { (value, error) in
        if let error = error {
            print(error) // No variable named "randomVariable"
        }
    }
}

The workflow fails to run with the error:

No variable named "randomVariable"

However, if I edit the workflow and add a Variable to match the one set in code, everything is fine.

Add var to workflow

I no longer get the error, and the workflow executes correctly:

Execute workflow

This is an issue because I want to pass multiple pieces of information as variables to any potential workflow, and for each workflow to individually decide to handle each needed parameter.

I do not want to require that every workflow declare the variables that my app will optionally provide.

Note that in my sample workflow the variable is never used. I do not want the additional requirement that it be declared.

Is there any way to avoid each workflow declaring the variables that my app passes when executing the workflow?

Or, is there a way to inspect which variables a workflow has declared? I could then only pass the ones actually used by the workflow.

Apthorp answered 25/9, 2018 at 22:48 Comment(3)
Also added as rdar://44799791Apthorp
Posted to Apple Developer Forum: forums.developer.apple.com/message/333610#333610Apthorp
It's hacky but inside the package contents of the workflow is a property list document.wflow which contains the variables.Teetotal
A
0

The AMWorkFlow methods setValue(_:forVariableWithName:) and valueForVariable(withName:) both safely determine if that variable is set in the workflow file.

So, construct an AMWorkFlow alongside your NSUserAutomatorTask. Only set the variables that the script is using, as indicated by the AMWorkFlow:

if let automatorTask = try? NSUserAutomatorTask(url: url) {
    if let varChecker = try? AMWorkflow(contentsOf: url) {
        automatorTask.variables = POSSIBLE_VARIABLES.filter {
            return varChecker.setValue($0.value, forVariableWithName: $0.key)
            // -or- //
            return varChecker.valueForVariable(withName: $0.key) != nil
        }
    }
        
    automatorTask.execute(withInput: nil, completionHandler: nil)
}

AMWorkFlow does not execute at all in the Sandbox, so you must use NSUserAutomatorTask to actually run the workflow.

do {
    try AMWorkflow.run(at: url, withInput: nil)
} catch let error {
    print(error)
}

Automator encountered an error running this workflow:

Sandboxed applications can not use Automator.framework to run workflows.

Error Domain=com.apple.Automator Code=0 "Automator encountered an error running this workflow: “Sandboxed applications can not use Automator.framework to run workflows.”" UserInfo={NSUnderlyingError=0x604000e498a0 {Error Domain=com.apple.Automator Code=0 "Sandboxed applications can not use Automator.framework to run workflows." UserInfo={NSLocalizedDescription=Sandboxed applications can not use Automator.framework to run workflows.}}, NSLocalizedDescription=Automator encountered an error running this workflow: “Sandboxed applications can not use Automator.framework to run workflows.”, NSLocalizedFailureReason=Sandboxed applications can not use Automator.framework to run workflows.}

Apthorp answered 26/9, 2018 at 1:41 Comment(1)
Use valueForVariable(withName:) of AMWorkflow to check the variables, run with NSUserAutomatorTask.Teetotal

© 2022 - 2024 — McMap. All rights reserved.