Call a function in another script when executing using 'Run With PowerShell' - function

I have functions in a 'library' file to be called from my 'worker' script.
Library File
function ShowMessage($AValue)
{
$a = new-object -comobject wscript.shell
$b = $a.popup( $AValue )
}
Worker File
. {c:\scratch\b.ps1}
ShowMessage "Hello"
Running the 'worker' script works fine when in the PowerShell IDE but when I right-click the worker file and choose 'Run with PowerShell' it cannot find the function 'ShowMessage'. Both files are in the same folder. What might be happening?

In the worker file change to this:
. "c:\scratch\b.ps1"
ShowMessage "Hello"
As #RoiDanton mentioned below:
Attention when using relative pathing: Don't forget to prepend a dot
before the path . ".\b.ps1".
The first dot is an operator used to modify the scope and in that context it has nothing to do with paths. See Dot Source Notation.

In your worker file, dot-source the library file, this will load all content (functions, variables, etc) to the global scope, and then you'll be able to call functions from the library file.
=================== Worker file ==========================
# dot-source library script
# notice that you need to have a space
# between the dot and the path of the script
. c:\library.ps1
ShowMessage -AValue Hello
=================== End Worker file ======================

Related

How to tell PhpStorm that function argument is file path

In PhpStorm (and other JetBrains IDE), is it possible to make function attributes as file / resource path?
E.g. in this function:
function mix($file): string
{
// check mix maninfest for $file and return path from mix manifest
return $fire_path_with_cachebuster;
}
I'd like PHP to suggest files in the project as I define $file attribute when calling mix function.
Only manually for the moment, when calling that function 😒. And it's a temp injection (for a session) so it's not convenient:
mix('')
Place caret inside the string parameter
Use Alt + Enter (or via light bulb icon) to bring the Quick Fix / Intentions menu (on some Keymaps it might be different one)
Use "Inject language or reference" option
Then choose "File Reference" entry there (just start typing to filter the list).
The result:
Hopefully they will implement the following tickets for a permanent solution:
Using #[Language] PHP attribute at the function declaration: https://youtrack.jetbrains.com/issue/WI-56996
Or in-place via PHPDoc-like comment (before the parameter when calling that function): https://youtrack.jetbrains.com/issue/WI-20028
Watch those tickets (star/vote/comment) to get notified on any progress (and hopefully speed it up by bringing dev's attention).
Like LazyOne stated, there is currently no way to declare a parameter as being a file reference.
However, you can get a more permanent File Reference "injection" by [mis]using __DIR__.
PhpStorm considers a string mixed with the __DIR__ constant to be a file path:
It isn't perfect as it depends on what directory you are currently located in. If you only want the filename passed to your method, you can wrap the string in basename, or handle that from within your method.
echo mix(basename(__DIR__ . '/slack_bot.php'));

How to properly set function scope within a powershell module?

Background
I'd like all of my scripts and modules to be based on a template script which takes care of some common "housekeeping" tasks.
Some of my modules are interdependent, and so I might load a module within another module, even if temporarily.
However, because the code is templated, the basic initialization functions have the same name.
In my mind, this shouldn't be an issue as long as I scope things properly, but it turns out it is an issue.
Demonstrating the issue
The demo below will have 1 script, which loads a module, which in turn loads another module.
Each module has initialization code that runs when loading he module.
Update: updated the code to demonstrate a bit better why it's structured the way it is, although answer was already accepted.
module.level2.psm1
# module.level2.psm1
# list of modules loaded by template code
$script:LoadModule = $null
# module housekeeping code - called from template code
function ModuleSpecificInitCode {
Write-Host "Level 2 Code"
}
function Level2ModuleFunction {
Write-Host "This is why I imported Level 2 module"
}
# module housekeeping code - template code
function TemplateInitCode {
Write-Host "Level 2 Init"
$LoadModule | % { Import-Module ".\$_.psm1" }
}
TemplateInitCode
try {
ModuleSpecificInitCode
} catch {
# Error handling
}
module.level1.psm1
# module.level1.psm1
# list of modules loaded by template code
$script:LoadModule = "module.level2"
# module housekeeping code - called from template code
function ModuleSpecificInitCode {
Write-Host "Level 1 Code"
}
function Level1ModuleFunction {
Write-Host "This is why I imported Level 1 module"
}
# module housekeeping code - template code
function TemplateInitCode {
Write-Host "Level 1 Init"
$LoadModule | % { Import-Module ".\$_.psm1" }
}
TemplateInitCode
try {
ModuleSpecificInitCode
} catch {
# Error handling
}
test.ps1
# test.ps1
Remove-Module module.level*
Import-Module .\module.level1.psm1
When running test.ps1, the output I receive is:
PS>.\test.ps1
Level 1 Init
Level 2 Init
Level 2 Code
Level 2 Code
The Issue / My Question
The issue is the last line. Level 2 code is running instead of level 1 code.
I've tried local, private and script as the <scope>: but whatever I do the Level 1 Code never runs.
What am I missing here, why do all the modules seem to be running in the same namespace?
If you don't explicitly export anything from the module, it all gets exported.
If you want a function to be available only within the module (think of it as a private function, though it's not actually related to the Private: scope in PowerShell), then just export every function except the ones that are internal.
Export-ModuleMember is how you define what you want to be exported. It accepts wildcards, so if you can describe what's public with a pattern, you could do it in one call, but it's ok to call it as many times as you need.
Once the functions are no longer exported, they are not available to code outside the module.
Your examples are a little strange to me, in that you seem to want access to some of the module code outside the module, but want it to be the same name, but I'm not certain.
In that case, for example if Level1 init was supposed to call code in Level2 module, you might consider adding -Scope Local to the Import-Module call itself, but I'm not certain this would help your situation.

To undefine in .bbappend shell function defined in .bb file

One .inc file included in some image-.bb file defines shell function for Bitbake task.
Let's concentrate here merely on this shell function, asigned Bitbake task is out of scope.
I wonder how to undefine this shell function in .bbappend file (other layer).
unset -f <shell-function-name>
is not working
ERROR: ParseError at .......-image.bbappend:89: unparsed line: 'unset -f do_thisandthat'
Does it need be said Bitbake explicitely "unset -f < shell-function-name>" is a shell script?
Me consulted for this question Bitbake Manual and Yocto Project Reference Manual with outcome of zero findings.
There is no direct API for it however you can do something like:
python () {
d.delVar("shell function name")
}
which will delete the shell function since functions are simply variables.
Just deleting a function may well cause other problems but that does answer your specific question.
This is an 'anonymous python' fragment and will be executed by bitbake at the end of parsing a recipe (or bbappend to a recipe).

Why aren't namespace autoload classes loading in phpunit tests?

To compliment an existing smorgasbord of arrangements between phpunit,autoload and namespace is this:
I have created a simple test project that runs PhpUnit tests and uses namespace autoloading. I register the autoloading in the bootstrap file like so:
set_include_path(get_include_path() . PATH_SEPARATOR . "/path/to/classes/folder");
spl_autoload_register();
and inside a unit test I load and test my class like so:
$obj = new \some\space\someClass(); // which is in the classes/some/space folder
$this->assertTrue($obj->foo()=='bar');
And I get an error
Fatal error: Class '\some\space\someClass' not found in testSomeClass.php...
While this is not phpunit specific you need to change:
spl_autoload_register();
to
spl_autoload_register('spl_autoload');
Any other component that registers an autoloader unregisters the default __autoload().
If your code has an existing __autoload function then this function must be explicitly registered on the __autoload stack. This is because spl_autoload_register() will effectively replace the engine cache for the __autoload function by either spl_autoload() or spl_autoload_call().
So this is how spl-autoload works together with anything else that uses autoloading.
Make sure your path to classes folder is made relative to script which is run for tests execution. If the script is in subfolder of your projects (for example tests/) then your path should be ../path/to/classes/folder
That's what I have in my tests/bootstrap.php
set_include_path(dirname(__FILE__).'/../classes'.PATH_SEPARATOR.get_include_path());
spl_autoload_extensions('.php');
spl_autoload_register('spl_autoload');

grails base.dir system property

I have a simple grails file upload app.
I am using transferTo to save the file to the file system.
To get the base path in my controller I am using
def basePath = System.properties['base.dir'] // HERE IS HOW I GET IT
println "Getting new file"
println "copying file to "+basePath+"/files"
def f = request.getFile('file')
def okcontents = ['application/zip','application/x-zip-compressed']
if (! okcontents.contains(f.getContentType())) {
flash.message = "File must be of a valid zip archive"
render(view:'create', model:[zone:create])
return;
}
if(!f.empty) {
f.transferTo( new File(basePath+"/files/"+zoneInstance.title+".zip") )
}
else
{
flash.message = 'file cannot be empty'
redirect(action:'upload')
}
println "Done getting new file"
For some reason this is always null when deployed to my WAS 6.1 server.
Why does it work when running dev but not in prod on the WAS server? Should I be accessing this information in a different way?
Thanks j,
I found the best dynamic solution possible. As a rule I never like to code absolute paths into any piece of software. Property file or no.
So here is how it is done:
def basePath = grailsAttributes.getApplicationContext().getResource("/files/").getFile().toString()
grailsAttributes is available in any controller.
getResource(some relative dir) will look for anything inside of the web-app folder.
So for example in my dev system it will toString out to "C:\WORKSPACEFOLDER\PROJECTFOLDER\web-app\ with the relative dir concated to the end
like so in my example above
C:\WORKSPACEFOLDER\PROJECTFOLDER\web-app\files
I tried it in WAS 6.1 and it worked in the container no problems.
You have to toString it or it will try to return the object.
mugafuga
There's a definitive way...
grailsApplication.parentContext.getResource("dir/or/file").file.toString()
Out of controllers (ex. bootstrap)? Just inject..
def grailsApplication
Best regards!
Grails, when it's run in dev mode, provides a whole host of environment properties to its Gant scripts and the app in turn, including basedir.
Take a look at the grails.bat or grails.sh script and you will find these lines:
Unix: -Dbase.dir="." \
Windows: set JAVA_OPTS=%JAVA_OPTS% -Dbase.dir="."
When these scripts start your environment in dev mode you get these thrown in for free.
When you take the WAR and deploy you no longer use these scripts and therefore you need to solve the problem another way; you can either
Specify the property yourself to the startup script for the app server, eg: -Dbase.dir=./some/dir .. however
... it usually makes more sense to use the Grails Config object which allows for per-environment properties
Another option:
def basePath = BuildSettingsHolder.settings.baseDir