Call a Powershell script function from CMD with parameters - function

Maybe i need a pair of fresh eyes on that:
i use the following code in a .bat file in order to call a Powershell script which accepts 2 parameters.And i want to pass the same parameters in a function which is the Powershell script.The problem is that i cannot seperate the 2 parameters inside the function.Here is the code inside the .bat file :
#ECHO OFf
Set OUTFILE="C:\users\XXX\desktop\newchangepass\log.txt"
echo user='%1' pass='%2' >> %OUTFILE%
echo %1 %2
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -File "C:\ps\CallMeWithParams.ps1" %1 %2
That's what i give to the command line:
c:\PS>CallMeWithParams.bat Alpha Beta
and here is the code inside the Powershell script:
param ([Parameter (Mandatory)]$param1, [Parameter(Mandatory)]$param2 )
function foo{
param ($fusername,$fpassword)
write-output $fusername
}
foo($param1,$param2)
The output which i receive obviously in CMD is:
c:\PS>CallMeWithParams.bat Alpha Beta
Alpha Beta
Alpha
Beta
i should get only the first parameter....
The code inside the PS script is there for test reasons.I want to be sure that i get the two parameters and that i can seperate them in order to use the second one in an update statement.
Any suggestion would be greatly appreciated.
PS1: Yes the CMD arguments will be enclosed in double quotes
PS2: atm there is no control on variable types etc. I wanted to keep it simple for debugging reasons.

Related

Run Octave function with one argument from batch

I am trying to run an octave function from a batch file. The function is well written given how it works when launched from within the Octave GUI.
The batch file, other than pointing to the octave function, defines the only argument needed by it.
A while back this was not a function but a simple Octave script and the commands used were ok.
The only issue I am encountering now is being able to pass the variable calculated by the batch file onto the octave function.
I have recently written an octave function to do some file management. It requires only one input from the user:
function replace_TMM (file_base)
where file_base is a string to specify what directory I am working on. So it has to be something like "Z:" or "I:" or so on.
I am quite sure that the function is well written since I am able to use it from Octave GUI without any issues.
The fact is that I would like to run this function from a batch file. Inside this batch file I wrote:
SET a=%cd:~0,2%
This command is able to identify the working directory so "a" will be equal to "Z:" or similars.
Now my issue is telling the batch file to evaluate the octave function using "a" as its input argument.
I tried stuff like:
"C:\Program Files\GNU Octave\Octave-7.3.0\mingw64\bin\octave-cli.exe" -q --eval _03_REPLACE_V04("'%cd:~0,2%'")
which does not seem to work. This kind of solution gives a syntax error at batch level, it is not even able to enter the octave file.
If I instead try something like:
"C:\Program Files\GNU Octave\Octave-7.3.0\mingw64\bin\octave-cli.exe" -q _03_REPLACE_V04.m Z:
It is able to enter the octave file but it does not process the function, just skips over it to get to the end of the script.
Same goes if I try the following:
"C:\Program Files\GNU Octave\Octave-7.3.0\mingw64\bin\octave-cli.exe" _03_REPLACE_V04.m -"Z:"
In brief I bvelieve that the function itself works, it is only a matter of passing a variable from the batch to the octave.
Would really appreciate some help, thanks in advance.
UPDATE 1
I have done what was suggested by #Dariush Gavari and used the following syntax:
"C:\Program Files\GNU Octave\Octave-7.3.0\mingw64\bin\octave-cli.exe" -q --eval "replace_TMM('%a%')"
This gets me the following error message:
error: 'replace_TMM' undefined near line 1, column 1
I believed that it was because it was not ablòe to find the script containing the function. This is saved in a file called _03_REPLACE_V04.m
For this reason I have tried with
"C:\Program Files\GNU Octave\Octave-7.3.0\mingw64\bin\octave-cli.exe" -q --eval _03_REPLACE_V04.m "replace_TMM('%a%')"
Leading to the following error:
error: --eval "CODE" and script file are mutually exclusive options
usage: octave [-HVWdfhiqvx] [--debug] [--doc-cache-file file] [--echo-commands]
[--eval CODE] [--exec-path path] [--experimental-terminal-widget]
[--gui] [--help] [--image-path path] [--info-file file]
[--info-program prog] [--interactive] [--line-editing] [--no-gui]
[--no-history] [--no-init-file] [--no-init-path] [--no-line-editing]
[--no-site-file] [--no-window-system] [--norc] [-p path]
[--path path] [--persist] [--server] [--silent] [--traditional]
[--verbose] [--version] [file]
I believed that the problem could also have been having the functional nd the file with two different names. To solve this I have kept the same file name but changed the function to match it:
function _03_REPLACE_V04 (file_base)
Then in the batch:
"C:\Program Files\GNU Octave\Octave-7.3.0\mingw64\bin\octave-cli.exe" -q --eval "_03_REPLACE_V04('%a%')"
Leading to:
warning: function '_03_REPLACE_V04' defined within script file '\99_TOOLS\OCTAVE_FILES\_03_REPLACE_V04.m'
error: invalid call to script \99_TOOLS\OCTAVE_FILES\_03_REPLACE_V04.m
error: called from
_03_REPLACE_V04
In other words still no way of making it work. :)
Octave provides the argv function, which returns a cellstring array of all arguments passed to the octave executable at the time of launch, or in the case where it was used to launch a script, then this is the script's arguments.
So presumably all you have to do to get your directory from within octave is argv(){1}
If you would like to convert your filename to an absolute filename, you could also do this from within octave via the make_absolute_filename function.
Incidentally, a very useful command you should know of in octave is the lookfor command. Writing lookfor arguments in the terminal returns a list with all functions which have the word "arguments" in their description; argv is at the top of that list.
You can then do help argv to see more details on that command.

Generate an HTML file with variables in shell (Automator)

Basically, I have this "workflow" that I find myself doing frequently and would love to automate:
create a folder with a new name in a specific folder (the path doesn't change)
create an index.html file in that folder
edit the index.html with 2 key variables (A web title and an https: link)
run a script
Here's how far I've gotten in Automator:
Ask for new folder name
Save as variable
Ask for web title name
Save as variable
Ask for link
Save as variable
Run shell script to cd to the right folder and "touch index.html"
Now I'm stuck. How would I edit the index.html while using the two other variables mentioned. Is there a way to edit or "replace" the file's contents while using Automator variable?
TIA!
Try adding the following to 'Run Shell Script' in the Automator workflow:
for var in $#
do
echo $var >> /path/to/index.html
done
and then setting "Pass input:" above the "Run Shell Script" module to: 'as arguments'
What this loop does is run the commands between do and done for every single variable you set in your Automator script. Alternatively, you can just replace for var in $# to for var, as an empty for will automatically collect the variables.
> and >> are bash shell operators. >> appends to a file or creates the file if it doesn't exist. The > overwrites the file if it exists or creates it if it doesn't exist. You may remove the touch command, unless you wish to create an empty file no matter if any variables are supplied.
If you need to differentiate between your variables, you don't even need a for loop, and can simply run:
echo $1 >> /path/to/index.html
echo $2 >> "/path to/index.html" # *or* /path\ to/index.html
# ^ if the directory of the file contains spaces
echo "The third supplied variable is: ${3}" >> /path/to/index.html
# ^ if you wish to add additional text to the variable
and so on, following the order in which you set your automator variables. Just make sure "Pass input:" is still set to 'as arguments'.

Local variable in makefile is not expanded correctly

I have the following function in makefile:
define INSTALL_SCRIPT
SRC_DIR = $(ROOT)\src
cd $(SRC_DIR)
$(SRC_DIR)\stage.bat
endef
I also echo the steps, so here's the output of the above snippet:
$SRC_DIR = C:\project_root\src
'SRC_DIR' is not recognized as an internal or external command,
operable program or batch file.
$cd
C:\project_root
\stage.bat
'\stage.bat' is not recognized as an internal or external command,
operable program or batch file.
It seems that in assignment statement the value is expanded correctly but then $(SRC_DIR) gives an error. Then cd goes to one directory up (and not src), then when I need to execute the batch file, $(SRC_DIR)'s value seems to be empty.
Assuming you're trying to do this from a recipe context, you would need to do it as follows:
define INSTALL_SCRIPT
set SRC_DIR=$(ROOT)\\src & \
cd %SRC_DIR% & \
%SRC_DIR%\\stage.bat
endef
sometarget:
#$(INSTALL_SCRIPT)
You need the \ at the end of each line to concatinate them into a single recipe line (other wise the variable you set will fall out of context when the first recipe line's shell terminates). You seem to be using windows so I believe you need to use the %varname% syntax to refer to the variables. Notice that $(ROOT) is a makefile variable in this case, so it still uses the $ syntax. (Note that if you were in bash you would need to use $$ to refer to shell variables). You also need to double the \\ in directory names, as make will interpret the first slash as an escape, and then pass a single slash to cmd.
Note that my windows machine doesn't have make installed on it, so I couldn't test the above, so it's quite possible I missed something.

GNU make call function with multiple arguments and multiple commands

I am trying to write a GNU make call function (example below) which has multiple shell commands to execute, such that it can be called with different arguments.
shell_commands = $(shell echo $(1); ls -ltr $(2))
try:
$(call shell_commands,$(FILE1),$(FILE2))
1) Is above the correct way to write a call function with multiple commands? By using a semi-colon to separate them? To make it readable, I write my targets as shown below. Is there a similar way to write a call function?
shell_commands:
echo $(1)
ls -ltr $(2)
2) I get this error from make when I execute make -B try. It looks like it is trying to execute /home/user/file1. But why?
make: execvp: /home/user/file1: Permission denied
make: *** [try] Error 127
3) Is it possible to pass variable number of parameters to a call function? Like pass in just the second parameter and not the first one.
$(call shell_commands,,$(FILE2))
I tried google-ing, searching on SO, and looking on gnu.org but I did not get any solutions. Will appreciate any answers or pointers to any resources which document call function with multiple optional arguments and commands.
Question 1: No, this is not right. The shell make function should NEVER be used inside a recipe: the recipe is already running in the shell, so why would you run another shell? It's just confusing. Second, it's generally recommended to use && between multiple commands in a recipe, so that if the first command fails the entire command will immediately fail, rather than continuing on and perhaps succeeding. Of course, that is not always correct either, it depends on what you're trying to do.
Question 2: This happens because the shell make function is like backticks in the shell: it expands to the output printed by the shell command it runs. Your shell command that make runs is:
echo $(1); ls -ltr $(2)
(where, one assumes, $1 expands to /home/user/file1) which prints the string /home/user/file1. After the expansion, that string is substituted into the recipe and make tries to run that recipe, giving the error you see above.
You want this, most likely:
shell_commands = echo $(1) && ls -ltr $(2)
try:
$(call shell_commands,$(FILE1),$(FILE2))
Now the call expands to the actual text, not an invocation of make's shell function, and then that text is run as the recipe.
Question 3: Sure, just using empty parameters means that the variable $1 (in this case) expands to the empty string.

Directing output to stdout in a function without the calling code seeing it

I wrote several Powershell scripts which deploy software for a client. I used Write-Host to output a lot of information so that the progress of the deploy can be watched and they call this from one of their deploy application using Start-Transcript to capture this output.
However, they also need to be able to call some of these scripts from another application which can only capture output from stdout. This means that Write-Host won't work there since it outputs only to the console or host and doesn't get directed to stdout (correct?)
My thought was that I could change the code to use Write-Out instead, except that this causes another problem. Since I use functions and since functions in Powershell "return" everything that goes to stdout to the caller that would likely screw up any of my code that retrieves output from a function.
Is there a way to direct output to stdout from a function without it going to the calling code as the output of the function itself? Here is an example of the problem:
function Test-Output ([int]$number) {
Write-Output "This is a string"
return $number
}
[int]$someNumber = Test-Output 10
$someNumber
If you run the code above you'll see an error because Powershell is trying to assign "This is a string" to the integer $someNumber. If you change the variable to a string then it will capture the full output of the function (This is a string 10) and assign it to the variable.
Thanks for any suggestions that you can give!
Function output and stdout are the same thing so the calling code is going to see anything output to the stdout stream. In this case I would suggest using the Write-Progress cmdlet to report progress to the end user and leave actual function output alone.
Try this.
function Add-Numbers {
param (
[double] $FirstNumber,
[double] $SecondNumber
)
Write-Host "Hello World"
return ($FirstNumber + $SecondNumber)
}
$result = Add-Numbers 1 2
#Write-Host "Result is $result"