I have an AppleScript file that I'm passing two values to and it is giving me this error:
execution error: {"file2"} doesn’t match the parameters {fileName, fileName2} for run. (-1721)
Here is the AppleScript:
on run {fileName, fileName2}
set output to fileName & "|" & fileName2
end run
UPDATE:
On further testing if I add more parameters it seems to work. Is there an arguments array or parameters array that I can use instead?
Your handlers requires two parameters and you are only passing one. Post your handler call.
You can use
on run argv
repeat with aParameter in argv
display dialog aParameter as string
end repeat
end run
The on run-argument (here called argv) is an Applescript list that contains the parameters.
Enjoy, Michael / Hamburg
Related
I'm trying to run the npm-script from the Jenkins pipeline via the SAP Project Piper's npmExecuteScripts:
npmExecuteScripts:
runScripts: ["testScript"]
That works! Now, I want to pass some arguments to my script.
According to the Project Piper documentation, there is a property scriptOptions, which cares about passing arguments to the called script:
Options are passed to all runScripts calls separated by a --. ./piper npmExecuteScripts --runScripts ci-e2e --scriptOptions --tag1 will correspond to npm run ci-e2e -- --tag1
Unfortunately, I can't figure out what is the proper syntax for that command.
I've tried several combinations of using scriptOptions, e.g.:
scriptOptions: ["myArg"]
scriptOptions: ["myArg=myVal"]
and many others, but still no desired outcome!
How can I call an npm-script and pass arguments / parameters to the script using the Project Piper's npmExecuteScripts?
To solve the issue, it's important to bear in mind that in contrast to the regular argument-value mapping via the npm_config_-prefix, the SAP Project Piper scriptOptions doesn't perform a mapping and passes an array of argument-value pairs «as is» instead, and then this array can be picked up via process.argv.
The Jenkins pipeline configuration:
npmExecuteScripts:
runScripts: ["testScript"]
scriptOptions: ["arg1=Val1", "arg2=Val2"]
package.json:
"scripts": {
"testScript": "node ./testScript.mjs"
}
The server-side script:
/**
* #param {Array.<String>} args - array of console input arguments to be parsed
*/
const testScript = function testScript(args) {…}
testScript(process.argv.slice(2));
P.S. Just to compare, the regular way to pass an argument's value to the npm-script looks like:
npm run testScript --arg=Val
and the server-side script:
"testScript": "echo \"*** My argument's value: ${npm_config_arg} ***\""
The output:
*** My argument's value: Val ***
The npm-script engine performs an argument-value mapping under the hood by using the npm_config_-prefix.
I have a helperScript which has a few basic functions that I frequently use.
My Current script’s flow goes like this:
on SubA()
Set HelperScript to load…..
tell HelperScript
: :
: :
end tell
end SubA
on SubB()
Set HelperScript to load…..
tell HelperScript
::
::
end tell
end SubB
on run paravlist
Set HelperScript to load…..
tell HelperScript
SubA()
SubB()
end tell
end run
I am unable to call SubA() and SubB() as the helper script is being set and used from each of subroutines. If I comment out the usage of helperScript. I am able to call subroutines from one another. What is the best way to deal with a problem like this? I want to use the helperScript in every subroutine.
After reading your question a few more times, I think I've figured out what you're asking. You're trying to load a script within your method and then you want to call a method that is within that script?
If that is the case, I think what you're looking for is this...
set HelperScript to load script...
set theResult to someMethod() of HelperScript
EDIT :
I'm still not clear if you have two scripts or one, so i've updated the answer to reflect both cases.
Dual script example...
property HelperScript : null
on run
try
if not loadScript() then error "Unable to load script"
set rslt1 to SubA() of HelperScript -- This approach assumes HelperScript.scpt is a different script and it contains a method called SubA
set rslt2 to SubB() of HelperScript -- This approach assumes HelperScript.scpt is a different script and it contains a method called SubB
on error errMsg
activate
display dialog "Error: " & errMsg buttons {"OK"} default button 1 giving up after 10
end try
end run
on loadScript()
try
set HelperScript to load script (POSIX file "/Path/To/HelperScript.scpt")
return true
on error
return false
end try
end loadScript
Single script example...
on run
try
set rslt1 to SubA() -- This approach assumes your HelperScript is THIS script
set rslt2 to SubB() -- This approach assumes your HelperScript is THIS script
on error errMsg
activate
display dialog "Error: " & errMsg buttons {"OK"} default button 1 giving up after 10
end try
end run
on SubA()
try
-- Do something here
return true -- or some other value
on error
return false -- or some other value
end try
end SubA
on SubB()
try
-- Do something here
return true -- or some other value
on error
return false -- or some other value
end try
end SubB
AppleScript has included a library loading system since 10.9. It's not great (e.g. avoid the SDEF garbage as it's 1. make-work and 2. bug-injector) but it generally does the job. I recommend you adopt that.
new to applescript and this small check is driving me nuts.
I want to check if the input to the script has the substring of "mob".
If i create a varible with mob1234, It works and returns true.
on run {input, parameters}
set testString to "mob1234"
display dialog {"MOB" is in testString}
return input
end run
If i change it to use the input, and set the input to mob1234, it fails and gives me false
on run {input, parameters}
set testString to input
display dialog {"MOB" is in testString}
return input
end run
I have no idea.
You don't say how you're invoking your script. If you're calling the script via Automator, be aware that in this mode input is a list, not a string, so this should work:
set testString to item 1 of input
Since the answer given by iayork seems to be right, here some follow up:
-- When this is saved as compiled script one can call it from Terminal like:
-- `osascript scriptName.scpt MOBstringArg1 arg2`
on run {input, parameters}
if (input's class is list) then set input to (item 1 of input) as text
if "MOB" is in input then
display notification "FOUND MOB" with title "In: " & input
end if
return input
end run
See comment from iayork about calling a script with osascript.
You can also just coerce the input to text directly when you assign it to testString: set testString to input as text, that is, if you aren't going to use any other list item of input.
I'm trying to process/filter input within a VBscript, but only if the input has been piped into the script. I don't want the script processing user/keyboard input. I'd like to code this as something like this:
stdin_is_tty = ...
if not stdin_is_tty then
...
input = WScript.StdIn.ReadAll
end if
Otherwise, the script will hang, waiting on user input when it executes WScript.StdIn.ReadAll (or even earlier if I test the stream with WScript.StdIn.AtEndOfStream).
In C#, I'd use:
stdin_is_tty = not System.Console.IsInputRedirected // NET 4.5+
The accepted answer for Q: "How to detect if Console.In (stdin) has been redirected?" shows how to build that result using Win32 calls via P/Invoke, for versions of NET earlier than NET 4.5. But I don't know of any way to translate that method into VBscript.
I've constructed a clumsy, partial solution using SendKeys to send an end-of-stream sequence into the scripts' keyboard buffer. But the solution leaves keys in the buffer if STDIN is redirected, which I can't clean up unless I know that STDIN was redirected... so, same problem.
I'd prefer to keep the script in one packaged piece, so I'd rather avoid a separate wrapping script or anything not available on a generic Windows 7+ installation.
Any brilliant ideas or workarounds?
EDIT: added copy of initial solution
I've added a copy of my improved initial solution here (admittedly, a "hack"), which now cleans up after itself but still has several negatives:
input = ""
stdin_is_tty = False
test_string_length = 5 ' arbitrary N (coder determined to minimize collision with possible inputs)
sendkey_string = ""
test_string = ""
for i = 1 to test_string_size
sendkey_string = sendkey_string & "{TAB}"
test_string = test_string & CHR(9)
next
sendkey_string = sendkey_string & "{ENTER}"
wsh.sendkeys sendkey_string ' send keyboard string signal to self
set stdin = WScript.StdIn
do while not stdin.AtEndOfStream
input = input & stdin.ReadLine
if input = test_string then
stdin_is_tty = True
else
input = input & stdin.ReadAll
end if
exit do
loop
stdin.Close
if not stdin_is_tty then
set stdin = fso.OpenTextFile( "CON:", 1 )
text = stdin.ReadLine
stdin.Close
end if
This solution suffers from the three problems:
leaving a visible trace at the command line (though now, just a single blank line which is low visibility)
possible collision of the test string (a set series of N [coder determined] TABs followed by a NEWLINE) with the first line of any redirected input causing a false positive redirection determination. Since the number of TABs can be modified, this possibility can be made arbitrarily low by the coder.
a race condition that if another window receives focus before the SendKeys portion is executed, the wrong window will receive the code string, leading to a false negative redirection determination. My estimate is that the possibility of this circumstance occurring is very low.
In short, no, but ...
I've tested everything i could think of and have not found a reasonable way to do it.
None of the properties/methods exposed by the TextStream wrappers retrieved with WScript.StdIn or fso.GetStdStream give enough information to determine if the input is redirected/piped.
Trying to obtain information from the behaviour/environment of a spawned process (how to create the executable is other story) is also unlikely to be useful because
WshShell.Execute always spawns the process with its input and output handles redirected
WshShell.Run creates a new process that does not inherit the handles of the current one
Shell.Application.ShellExecute has the same problem as WshShell.Run
So, none of these methods allow the spawned process to inherit the handles of the current process to check if they are redirected or not.
Using WMI to retrieve information from the running process does not return anything usable (well, HandleCount property for the process differs when there is a redirection, but it is not reliable)
So, not being able to determine from vbs code if there is a redirection, the remaining options are
Don't detect it: If the piped input must be present, behave as the more command and in all cases try to retrieve it
Indicate it: If the pipe input is not always required, use an argument to determine if the stdin stream needs to be read.
In my case, I usually use a single slash / as argument (for coherence with some of the findstr arguments that also use a slash to indicate stdin input). Then in the vbs code
If WScript.Arguments.Named.Exists("") Then
' here the stdin read part
End If
Check before: Determine if there is redirection before starting the script. A wrapper .cmd is needed, but with some tricks both files (.cmd and .vbs) can be combined into one
To be saved as .cmd
<?xml : version="1.0" encoding="UTF-8" ?> ^<!------------------------- cmd ----
#echo off
setlocal enableextensions disabledelayedexpansion
timeout 1 >nul 2>nul && set "arg=" || set "arg=/"
endlocal & cscript //nologo "%~f0?.wsf" //job:mainJob %arg% %*
exit /b
---------------------------------------------------------------------- wsf --->
<package>
<job id="mainJob">
<script language="VBScript"><![CDATA[
If WScript.Arguments.Named.Exists("") Then
Do Until WScript.StdIn.AtEndOfStream
WScript.StdOut.WriteLine WScript.StdIn.ReadLine
Loop
Else
WScript.StdOut.WriteLine "Input is not redirected"
End If
]]></script>
</job>
</package>
It is a .wsf file stored inside a .cmd. The batch part determines if the input is redirected (timeout command fails to get a console handle on redirected input) and pass the argument to the script part.
Then, the process can be invoked as
< inputfile.txt scriptwrapper.cmd input redirected
type inputfile.txt | scriptwrapper.cmd input piped
scriptwapper.cmd no redirection
While this is a convenient way to handle it, the invocation of the .wsf part from the .cmd, while being stable and working without problems, relies in an undocumented behaviour of the script host / cmd combination.
Of course you can do the same but with two separate files. Not as clean, but the behaviour is documented.
I want my program to launch another desktop application.
Tried shell execute (open appname) but it does not work.
Is there another way ?
Thank you in advance.
Another possibility is use the standard Xojo FolderItem and use the Launch method.
Dim f as folderitem = specialfolder.applications.child("AppName")
if f <> nil and f.exists then
f.launch
end
Reference Documentation:
http://docs.xojo.com/index.php/SpecialFolder
http://docs.xojo.com/index.php/FolderItem.Launch
dim s as new Shell
s.Execute("open -a ""Finder""")
' Check error code and do something about it...
if s.ErrorCode <> 0 then
MsgBox("Error code: " + Str(s.ErrorCode) + EndOfLine + "Output: " + s.Result)
end if
Change "Finder" to whichever application you need, or build a string and pass that to s.Execute(). Be sure to include escaped quotes, especially if the application has spaces in its name.
I'm not familiar with Xojo, however "launching" an application on OS X is complicated. There are many things you need to consider, especially if it's already running.
I recommend you look into two possible options, either use Xojo's ability to launch call native C code to run one of the three -[NSWorkspace launchApplication...] methods: https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSWorkspace_Class/Reference/Reference.html#//apple_ref/doc/uid/20000391-SW23
Alternatively, use Apple's open command line tool:
/usr/bin/open -a "App Name"
/usr/bin/open -a "/Applications/App Name.app"