Powershell - getting the scriptname of calling script in dot-sourced function - powershell

is there any way to get the scriptname of the calling script into a dot-sourced ps1 script?
This would be awsome for logging.
eg: script test1.ps1 is calling a function from dot-sourced log.ps1.
The String "test.ps1" is needed in log.ps1. Is this possible?
Thanks in advance

If you are dot sourcing log.ps1 then the execution is still occurring within Test.ps1.
To get the name of the executing script use:
$ExecutingScript = $MyInvocation.MyCommand.Name
# Test.ps1
You can then use $ExecutingScript in whatever logging functions provided by the dot sourced script.
If you need the entire path to the executing script, you would use:
$MyInvocation.InvocationName
# C:\Whereever\Test.ps1

You can try :
$a = Split-Path $PSCommandPath -Leaf

I was trying to solve similar or maybe same problem - how to generate log file name based on script name. Solution from #SomeShinyObject is nice but when you have your logging script sourced from file, that is sourced from another file, then you have problem. I have arrived at following solution. In case anyone is interested.
$scriptFileName = Get-Item (Get-PSCallStack)[(Get-PSCallStack).length-1].ScriptName
$log = "$($scriptFileName.DirectoryName)\log\$($scriptFileName.Basename).log"
It basically gets highest frame from the call stack by first getting stack depth using (Get-PSCallStack).length then it uses this value in obtaining the frame itself and gets ScriptName from there, which is uppermost script in calling hierarchy.

Related

Shorter execution of powershell script

Say I have a script to be executed in a single call, how do I do it?
Like, say I have a powershell script saved at E:\Fldr\scrpt.ps1.
Now if I have to normally execute that script is PowerShell ISE then I would have to use:
& "E:\Fldr\scrpt.ps1"
and the scrpt.ps1 gets executed.
But whatI want is, when I write a word, say "exeScrpt" instead of & "E:\Fldr\scrpt.ps1" then I want scrpt.ps1 to get executed.
Is there a way to do this?
Thank you for checking in..
You can wrap your call to the script in a function:
function Invoke-Script
{
E:\Fldr\scrpt.ps1
}
Then you can run your script by executing a single command anywhere after the definition:
Invoke-Script
Note that it is good practice to name your functions according to the Verb-Noun cmdlet naming standard, so something like Invoke-Script instead of exeScrpt. If you really want a single word as the name, then you can additionally create an alias for your function:
New-Alias -Name exeScrpt -Value Invoke-Script

mIRC .txt timer based script

trying to make a timer delayed based script for mIRC for a scenario based game. everything is put together and should run but when I actually go to start the script it just says unknown command.
SCRIPT {
/TIMER1 1 1 /query #mircroom THIS IS WHAT I WANT IT TO SAY
/TIMER2 1 4 /query #mircroom2 THIS IS WHAT I WANT IT TO SAY
}
I put it into alias's so in theory I should just have to type /SCRIPT and it would run right? I also threw it into it's own .txt file and it did not recognize starting the script.
Any and all help would be greatly appreciated.
$script is a built-in identifier
$script can be used to return the filename of the Nth loaded script file. If you specify a filename, it returns $null if the file is not loaded; otherwise it returns the file's name.
Try to give it another name and it should work

How to load custom powershell profile with single command

I have a shared computer for which I want to create a custom PowerShell profile that I can load with a simple command but which otherwise never gets sourced.
I tried adding a function like this to the main $profile:
function custom() {. C:\Users\[username]\Documents\WindowsPowerShell\custom_profile.ps1}
The idea was that I could just type the command custom and it would load my custom profile.
This doesn't work, because it does the sourcing inside the function scope, and all of the functions and aliases are lost when I leave that scope.
I could just execute the entire . C:\Users\[username]\Documents\WindowsPowerShell\custom_profile.ps1 command, but I am looking for a way to do this with a single command.
If I were in bash, I'd just use something like alias custom=". C:\Users\[username]\Documents\WindowsPowerShell\custom_profile.ps1", but Powershell's alias doesn't work that way.
How can I do this in PowerShell?
Or, change the file to a psm1 (a powershell module) and then :
Function custom {
if(-not Get-Module custom_profile){
Import-Module 'C:\Users\[username]\Documents\WindowsPowerShell\custom_profile.psm1'
} else {
Remove-Module custom_profile
Import-Module 'C:\Users\[username]\Documents\WindowsPowerShell\custom_profile.psm1'
}
}
and then running
custom
will do what you want.
As noted in the comments you might need
Export-ModuleMember -Variable * -Function * -Alias *
if your module is supposed to export variables and aliases as well as functions.
A simple way might be to just use a variable instead of a function.
In profile:
$custom = 'C:\Users\[username]\Documents\WindowsPowerShell\custom_profile.ps1'
Interactively:
. $custom
Probably want to use a better name that's less likely to be overwritten, but same concept.
The most simple way would be to use PSReadLine, define your own handler to be executed, such as F5 to load custom prifile.
This is shorter then writing a command also as you have to press 1 key.
You should use PSReadLine anyway as it overpowers stock console in every aspect.

Emulating 'source' command in powershell

I am trying to emulate bash's source command in powershell. The intent is to make any change to my microsoft.powershell_profile.psl and source it into the existing instance of powershell.
The following command works in command-line
$profile_content = [string]::join([environment]::newline,(get-content $profile))
invoke-expression $profile_content
All is good; I put the same into microsoft.powershell_profile.psl and it does not work.
function source{
$profile_content = [string]::join([environment]::newline,(get-content $args[0]))
invoke-expression $profile_content
}
Am I overlooking something?
What you want is already built into PowerShell:
. C:\path\to\some.ps1
See about_Operators:
. Dot sourcing operator
Runs a script in the current scope so that any functions,
aliases, and variables that the script creates are added to the current
scope.
. c:\scripts.sample.ps1
Try changing your Microsoft.PowerShell_profile.ps1 to look like this:
function source{
$profile_content = [string]::join([environment]::newline,(get-content $args[0]))
invoke-expression $profile_content
}
source $profile
Basically, you can't just define the function, you need to call it in the file as well. HOWEVER, the way your function is set up, it will result in an infinite loop. Replace your function source() with something else.
Following should be enough:
function source { . $args }

Execute a parameter passed into a powershell script as if it were a line in the script

I've got a wrapper powershell script that I'm hoping to use to automate a few things. It's pretty basic, and accepts a parameter that I want the script to run as if it were a line in the script. I absolutely cannot get it to work.
example:
param( [string[]] $p)
echo $p
# Adds the base cmdlets
Add-PSSnapin VMware.VimAutomation.Core
# Add the following if you want to do things with Update Manager
Add-PSSnapin VMware.VumAutomation
# This script adds some helper functions and sets the appearance. You can pick and choose parts of this file for a fully custom appearance.
. "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-VIToolkitEnvironment.ps1"
$p
In the example above, I want $p to execute as if it were a line in the script. I know this isn't secure, and that's probably where the problem lies.
Here is how I try running the script and passing in a parameter for $p:
D:\ps\test>powershell -command "D:\ps\test\powershell_wrapper.ps1" 'Suspend-VM servername -Verbose -Confirm:$False'
How can I get my parameter of 'Suspend-VM servername -Verbose -Confirm:$False' to run inside my script? If I just include the value in the script instead of pass it in as a parameter it runs without any issues...
You can basically approach this two ways, depending on what your needs really are and how you want to structure your code.
Approach #1 - Invoke-Expression
Invoke-Expression basically allows you to treat a string like an expression and evaluate it. Consider the following trivial example:
Invoke-Expression '{"Hello World"}'
That will evaluate the string as if it were an expression typed in directly, and place the string "Hello World" on the pipeline. You could use that to take your string parameter and run it on-the-fly in your script.
Approach #2 - Using a ScriptBlock
PowerShell has a special data type called a ScriptBlock, where you can bind a script to a variable, and then invoke that script as part of your code. Again, here is a trivial example:
function Test-SB([ScriptBlock]$sb) {
$sb.Invoke()
}
Test-SB -sb {"Hello World"}
This example creates a function with a single parameter $sb that is of type ScriptBlock. Notice the parameter is bound to the actual chunk of code {"Hello World"}? That code is assigned to the $sb parameter, and then a call to the .Invoke method actually executes the code. You could adapt your code to take in a ScriptBlock and invoke it as part of your script.
Approach #3 - Updating your profile
OK, so I said there were two ways to approach it. There is actually a third... sort of... You could add the VMWare cmdlets to your $profile so they are always present and you don't need your wrapper to load in those libraries. Granted, this is a pretty big hammer - but it might make sense if this is the environment you are constantly working in. You could also just create a shortcut to PowerShell that runs a .ps1 on startup that includes those libraries and hangs around (this is what MS did with the SharePoint admin shell and several others). Take a look at this TechNet page to get more info on the $profile and if it can help you out:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb613488.aspx