最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dot source - Powershell script file that contains function doesnt load - Stack Overflow

programmeradmin0浏览0评论

I have got a powershell script file which contains the function below. its called my_functions.ps1

function Get-My-PlainText()
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)][System.Security.SecureString]$SecureString
    )
    BEGIN { }
    PROCESS
    {
        $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString);

        try
        {
            return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr);
        }
        finally
        {
            [Runtime.InteropServices.Marshal]::FreeBSTR($bstr);
        }
    }
    END { }
}

I have got another script (called scriptB.ps1) that is supposed to call this function file before using the functions referenced by the file

scriptB.ps1 calls the function file by running the following inline within the file.

powershell .\my_functions.ps1
Import-Module .\my_functions.ps1

I get the error below.

The term 'Get-My-Plaintext' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is
     | correct and try again.

Currently this behaviour happens on powershell terminal running powershell v 7.45, and the only way to fix it is to copy the function and paste it on the terminal.

Is there a way to resolve this problem and avoid the need to copy and paste the functions, its only this function that has this issue.

Thanks in advance.

I have got a powershell script file which contains the function below. its called my_functions.ps1

function Get-My-PlainText()
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)][System.Security.SecureString]$SecureString
    )
    BEGIN { }
    PROCESS
    {
        $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString);

        try
        {
            return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr);
        }
        finally
        {
            [Runtime.InteropServices.Marshal]::FreeBSTR($bstr);
        }
    }
    END { }
}

I have got another script (called scriptB.ps1) that is supposed to call this function file before using the functions referenced by the file

scriptB.ps1 calls the function file by running the following inline within the file.

powershell .\my_functions.ps1
Import-Module .\my_functions.ps1

I get the error below.

The term 'Get-My-Plaintext' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is
     | correct and try again.

Currently this behaviour happens on powershell terminal running powershell v 7.45, and the only way to fix it is to copy the function and paste it on the terminal.

Is there a way to resolve this problem and avoid the need to copy and paste the functions, its only this function that has this issue.

Thanks in advance.

Share Improve this question edited Nov 19, 2024 at 14:30 mklement0 443k68 gold badges712 silver badges930 bronze badges asked Nov 18, 2024 at 21:50 learnerlearner 1,0512 gold badges20 silver badges54 bronze badges 5
  • 2 The executable for PowerShell Core 7.4.5 is pwsh.exe. Using powershell will invoke Windows PowerShell; probably 5.1. – lit Commented Nov 18, 2024 at 21:58
  • 3 Don't include () after function name while including a param (...) section. You are defining both 0 parameters and one parameter at the same time. – Darin Commented Nov 18, 2024 at 21:59
  • 3 After sourcing the file in using . .\my_functions.ps1, the command Get-Command -Name Get-My-PlainText shows that it is loaded . – lit Commented Nov 18, 2024 at 22:05
  • Note that Import-Module .\SomeScript.ps1 - while ill-advised for conceptual reasons alone, given that a .ps1 file is just a script, not a module - is in effect the same as . .\SomeScript.ps1 (dot-sourcing), which is what you need. (Adding -Verbose to the Import-Module call shows this.) However, a side effect of using Import-Module is that a pseudo-module SomeScript is then reported by Get-Module. Also, repeating the Import-Module call in the same session is a quiet no-op - even if the script's content has changed; reloading requires -Force. – mklement0 Commented Nov 19, 2024 at 14:29
  • Two asides: To better align with PowerShell's naming conventions, Get-My-PlainText should be Get-MyPlainText; a simpler version of your function body would be [pscredential]::new('unused', $SecureString).GetNetworkCredential().Password – mklement0 Commented Nov 19, 2024 at 14:35
Add a comment  | 

1 Answer 1

Reset to default 2

There are 2 clear solutions to your issue.

1. dot sourcing

Change powershell to a dot

. .\my_functions.ps1

When you call powershell you are actually calling powershell.exe which launches a different process/session, loads the function into that session, then the session ends and takes that definition with it. Dot sourcing will pull that function into your current scope.

2. Rename .ps1 to .psm1 and use Import-Module

Import-Module .\my_functions.psm1

This will Import functions into the current session.

Also, as Darin pointed out in the comments, you have an extra pair of parenthesis. When you define a function, you can use the inline syntax

Function Get-Something ($Param1, $Param2){
    ...
}

or with a Param() block. (Decorating the param block with [cmdletbinding()] or at least one Parameter with [parameter()] makes it an advanced function)

Function Get-Something {
    [cmdletbinding()]
    Param(
        $Param1,
        $Param2
    )
    ...
}

It doesn't appear to cause issues as you have it, but is confusing for others at a minimum.

EDIT

mklement0 pointed out the Import-Module works on .ps1 as well. He is correct as I just confirmed. I'll leave the answer as is but renaming to psm1 is NOT required.

发布评论

评论列表(0)

  1. 暂无评论