PowerShell - &string Collision with Existing Alias - powershell

code:
function start() {
# do something
}
&"start"
How would keep & from finding the Start-Process alias first? Is there a way of removing the start alias for the lifetime of my script? Changing the name of the function is not an option.

You can specifically tell it you want to call the function, and not an alias.
function start() {
# do something
Write-Output "It Worked"
}
&(gi function:\start)
Any parameters can just be tacked on to the end of the call, as usual.
function start() {
Param(
[int] $toout
)
# do something
Write-Output "It Worked: $($toout + 5): See!"
}
&(gi function:\start) 5

Put:
Remove-Item alias:\start -Force
at the top of the script to remove it for the run, or add it to the system profile.ps1 to remove it permanently (every time powershell starts)

This also works, similar to the first answer:
function start(){
Write-Host "FOO"
}
&(get-command -CommandType Function -Name start)

Related

Why weird assignment from variable inside Powershell switch statement?

I'm a beginner at Powershell and am struggling to understand some syntax from some code I found on Github. I've read the docs on Powershell assignment, and on switch statements, and can't understand what is going on with the = $Yes and = $No in this code snippet:
Switch ($Prompt3) {
Yes {
Stop-EdgePDF
Write-Output "Edge will no longer take over as the default PDF viewer."; = $Yes
}
No {
= $No
}
}
I haven't been able to find any references to this kind of syntax, and it doesn't seem to do anything in the script. So why is it there?
UPDATE: This issue has been resolved.
Looks to me like the variable name that was getting the assignment was deleted in a change back in August.
$PublishSettings = $Yes
Was changed to:
= $Yes
And:
$PublishSettings = $No
Was changed to:
= $No
Looks like poor search and replace.
I've created an issue for the problem at GitHub.
There are many characters that are valid in a function (or variable) name; this includes the = symbol. What you're observing is a function or alias.
Examples:
# standard function
function =
{
return $args
}
# accessing the function: drive
${Function:=} = {
return $args
}
# defining a new alias
New-Alias -Name = -Value Get-Variable
# using the Alias attribute
function Test-Thing
{
[Alias('=')]
param()
return $args
}

Powershell - persist variable outside of function

I'm trying to import an xml file and store as a variable for the remainder of a powershell session. The import is obviously successful but the variable content does not persist outside of the function.
Function auth
{
$cred = import-clixml -Path c:\temp\cred.xml
}
try this:
Function auth
{
$global:cred = "test"
}
auth
$global:cred
You can use globals as Esperento57 suggests or you can do this
function auth
{
return 'test'
}
$cred = auth
More succinct:
function auth
{
'test'
}
$cred = auth
You need to declare the variable outside the scope of the function first and then inside the function explicitly tell the variable to update using the script:var method.
Here's the example is taken from https://www.kongsli.net/2013/04/25/powershell-gotchas-refer-to-variables-outside-a-function/ to which credit is given.
The thing is that we have to explicitly tell Powershell to update the variable in the parent scope instead of creating a new variable in the current scope.
$x = 1
function changeit {
"Changing `$x. Was: $x"
$script:x = 2
"New value: $x"
}
"`$x has value $x"
changeit
"`$x has value $x"
If you need to do this but with a number of functions and variables, you can place them all into a script and then dotsource the script.
Imagine a script like this:
#MyDevFunctions.ps1
$myImportantVar = "somevar"
$myOtherVar = "ABC123"
Function Get-MyCoolValue(){$myImportantVar}
Write-Host "Finished Loading MyDevFunctions"
If you wanted to run this, and then also persist the values of the variables and also the functions themselves, from your parent script you simply invoke it like so:
PS > . .\MyDevFunctions.ps1
"Finished Loading MyDevFunctions"
PS > $myOtherVar
ABC123
PS> Get-MyCoolValue
someVar

PowerShell - execute script block in specific scope

I am trying to implement RSpec/Jasmine like BDD framework in Powershell (or at least research the potential problems with making one).
Currently I am having problems with implementing simple before/after functionality. Given
$ErrorActionPreference = "Stop"
function describe()
{
$aaaa = 0;
before { $aaaa = 2; };
after { $aaaa; }
}
function before( [scriptblock]$sb )
{
& $sb
}
function after( $sb )
{
& $sb
}
describe
the output is 0, but I would like it to be 2. Is there any way to achieve it in Powershell (short of making $aaaa global, traversing parent scopes in script blocks till $aaaa is found, making $aaaa an "object" and other dirty hacks:) )
What I would ideally like is a way to invoke a script block in some other scope but I don't have a clue whether it is possible at all. I found an interesting example at https://connect.microsoft.com/PowerShell/feedback/details/560504/scriptblock-gets-incorrect-parent-scope-in-module (see workaround), but am not sure how it works and if it helps me in any way.
TIA
The call operator (&) always uses a new scope. Instead, use the dot source (.) operator:
$ErrorActionPreference = "Stop"
function describe()
{
$aaaa = 0;
. before { $aaaa = 2; };
. after { $aaaa; }
}
function before( [scriptblock]$sb )
{
. $sb
}
function after( $sb )
{
. $sb
}
describe
Note the use of . function to invoke the function in same scope as where `$aaaa is defined.

Parse powershell script parameters

Is there an easy way to parse the params from a powershell script file
param(
[string]$name,
[string]$template
)
I have started reading the file and wondered if there is a better way, maybe by a help/man command?
class PowerShellParameter {
public string Name;
public string Type;
public string Default;
}
string[] lines = File.ReadAllLines(path);
bool inparamblock = false;
for (int i = 0; i < lines.Length; i++) {
if (lines[i].Contains("param")) {
inparamblock = true;
} else if (inparamblock) {
new PowerShellParameter(...)
if (lines[i].Contains(")")) {
break;
}
}
}
There are at least two possibilies. First one (imho better): use Get-Command:
# my test file
#'
param(
$p1,
$p2
)
write-host $p1 $p2
'# | Set-content -path $env:temp\sotest.ps1
(Get-Command $env:temp\sotest.ps1).parameters.keys
For all members look at
Get-Command $env:temp\sotest.ps1 | gm
#or
Get-Command $env:temp\sotest.ps1 | fl *
The other (harder way) is to use regular expression
[regex]::Matches((Get-Help $env:temp\sotest.ps1), '(?<=\[\[-)[\w]+') | select -exp Value
I like the solution with Get-Command proposed by #stej. Unfortunately it does not work if script parameters have explicit types specified and an assembly of such a type is not yet loaded into the session. That is why I still use this script: Get names of script parameters
I'm not really sure what you're after, is it documenting your scripts? In that case have a look at Get-Help about_Comment_Based_Help. It will tell you how to do that, and after that you can use Get-Help on your script/module.
If you're after more strict parameter handling, take a look at about_functions_advanced_parameters and about_functions_cmdletbindings on how to better structure parameters. For example,
[Parameter(Position=0,Mandatory=$true,HelpMessage='Enter
architecture("OSX","WinXP","Win7","Linux")')]
[ValidateSet("OSX","WinXP","Win7","Linux")]
[string]$architecture
will make that parameter mandatory, read from position 0 of the command, allow only a value from the given set, and give a brief help message when asking for input if that parameter was not given.

powershell function return

I try to start a function of an script out of another script.
I want to save the return into a variable but this doesn't work.
script1.ps1:
function test
{
return "hallo"
}
script2.ps1:
./script1.ps1; $p=test
or
$p = ./script1.ps1; test
It seems that $p is null, but I don't know what's wrong.
Can anybody please help me?
thx
Try this:
. ./script1.ps1; $p=test
Why: you have to load the function into current scope (that's the period at the beginning – the dot source operator).
If you use ';', then completely new statement begins. So from you example $p = ./script.ps1; test, you assign output from script.ps1 to $p and then run the function.