kspviswa
kspviswa

Reputation: 657

Why is the GUI not displayed when executing a cmdlet from powershell console, however displayed when running as a script?

I have a following function, which displays a credential window as follows.

File: popup.ps1 (This is not a psm. Just a script with only popup())

function popup
{
    [CmdletBinding()]
    param(
        [Parameter (Mandatory=$True)]
        [string] $username
    )

    $credential = Get-Credential -Username $username -Message "Provide Credentials"
    $pass = $credential.GetNetworkCredential().password
}

Now, if this ps1 is sourced in a PowerShell console and execute popup() command, the credentials pop-up is not shown. However, if I wrap this function by a calling script and execute (i.e. right click → Run with PowerShell) I'm able to see the GUI pop-up.

File: wrapper.ps1

. "./popup.ps1"

$uname = "viswa-ksp"
popup -username $uname

Could anyone explain me why GUI not shown when ran from PowerShell console, however when executed as a script? Am I missing something here?

EDIT :

It was actually a bug from my side. Fellow developer had commented the sourcing part . <path to the cmdlet source> as part of his debugging / troubleshooting for a different issue and I have overseen it. However thought mentally that the sourcing is still there ( since I know I had included the sourcing ).

Thanks for your valuable comments. Since more than 2 people said not reproducible, I again went and read the script once-again and found this issue.

But here is the follow-up question. I know that for cmdlet you will have to source it. But I want to understand, why nothing is happening if you just run the cmdlet without sourcing it. No error No pop-up. I even tested the return code. It is empty.

PS C:\Users\kspviswa\Desktop> .\popup.ps1
PS C:\Users\kspviswa\Desktop> $ret = .\popup.ps1
PS C:\Users\kspviswa\Desktop> Write-Host $ret

PS C:\Users\kspviswa\Desktop>

Would anybody explain this behaviour?

Upvotes: 1

Views: 853

Answers (2)

Prasoon Karunan V
Prasoon Karunan V

Reputation: 3053

The reason why nothing returned after running the script without dot-sourcing is , the script is not throwing any output. save this as a script and run without dot-sourcing

function popup
{
[CmdletBinding()]
param(
    [Parameter (Mandatory=$True)]
    [string] $username
)
write-host "String Inside function"
$credential = Get-Credential -Username $username -Message "Provide   Credentials"
$credential.GetNetworkCredential().password
}
write-host "String outside Function but inside the script"

The output must be String outside Function but inside the script
try it by dot-sourcing

PS >. .\script.ps1
PS >String outside Function but inside the script
PS >popup -username USERNAME
PS >String Inside function

And if you don't dot-source the script, the function will get defined and removed after the script executes as the scope of the function is inside the script by default

and if you dot-source it will load function into memory.

If you change the scope of the function as global, you can use it without dot-sourcing

function global: popup
{
[CmdletBinding()]
param(
    [Parameter (Mandatory=$True)]
    [string] $username
)
write-host "String Inside function"
$credential = Get-Credential -Username $username -Message "Provide   Credentials"
$credential.GetNetworkCredential().password
}
write-host "String outside Function but inside the script"

You can run the script without dot sourcing open a new PowerShell console and try this

PS >.\script.ps1
PS >String outside Function but inside the script
PS >popup -username USERNAME
PS >String Inside function

more about scopes https://technet.microsoft.com/en-us/library/hh847849.aspx

Best regards,

kvprasoon

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200373

Your function doesn't return the password because you assign it to a variable instead of actually returning it. Change this line:

$pass = $credential.GetNetworkCredential().password

into this:

$credential.GetNetworkCredential().password

Also, running a script doesn't automatically call any function defined in it. A function definition just makes the function available in the scope in which the script is executed. Dot-sourcing loads the script in the current scope, so you can use the function in your console after dot-sourcing the script. If you run the script it is executed in a child scope, so you'd need to explicitly call the function in the child scope to invoke its functionality. See about_Scopes and the dot-sourcing section of about_Scripts

Upvotes: 1

Related Questions