none
Functions in Powershell RRS feed

  • Question

  • Hi,

     

    I have a function which I can sucesfully import using .\function.ps1. Now I’d like to have this function available whenever I start my powershell.

     

    I tried to add it in my $profile also saved the ps1 as a psm1 (imported it as a module) but whenever I start the function it does not appear Please advise

    J.


    Jan Hoedt


    • Edited by janhoedt Monday, March 9, 2015 1:23 PM Update
    Monday, March 9, 2015 1:16 PM

Answers

  • Thanks!  This is the script

    https://www.dropbox.com/s/ckibrat4uhj6wr1/script.ps1?dl=0



    Jan Hoedt

    Looking at this it appears that it could never have worked.  I suspect you have run it as a script andnot a function and that creting a function caused it to break.

    If thisis all that was in your file why not just paste it into you profile.  Fix it first:

    Function Add-SAComputerDeviceToSCCM{
    	param(
    		[Parameter(Mandatory=$true)]
    		[string]$ComputerName,
    		[Parameter(Mandatory=$true)]
    		[string]$MacAddress,
    		[Parameter(Mandatory=$true)]
    		[string]$CollectionName,
    		[Parameter(Mandatory=$true)]
    		[string]$SiteCode,
    		[Parameter(Mandatory=$true)]
    		[string]$SCCMServer
    	)
    	cd $SiteCode+':' #'
    	Import-CMComputerInformation -ComputerName $ComputerName -MacAddress $MacAddress -CollectionName $CollectionName
    	Write-Host -ForegroundColor Green "[S]: $ComputerName is added to $CollectionName"
    	$CollectionQuery = Get-WmiObject -Namespace "Root\SMS\Site_$SiteCode" -Class SMS_Collection -ComputerName $SCCMServer -ErrorAction STOP -Filter "Name='$CollectionName'"
    	$CollectionQuery.RequestRefresh() | Out-Null
    	Write-Host -ForegroundColor White "[I]: Updating collection" -NoNewLine
    	Do{
    		Write-Host -ForegroundColor White '.' -NoNewLine
    		Start-Sleep -s 10
    	}
    	While((Get-CMDevice -CollectionName $CollectionName | Where-Object {$_.Name -eq $ComputerName}) -eq $null)
    	Write-Host -ForegroundColor Green " OK"
    }
    

    The last line will not work:

     While((Get-CMDevice -CollectionName $CollectionName | Where-Object {$_.Name -eq $ComputerName}) -eq $null)

    That requires a script block. What is it you are expecting it to do?

    If this sis sin a file then the file must be dot sourced.  Use the fullpath to the file and dot source it

    . c:\scripts\script.ps1

    Notice the <dot><space>


    ¯\_(ツ)_/¯

    • Marked as answer by janhoedt Tuesday, March 10, 2015 10:46 AM
    Monday, March 9, 2015 6:04 PM

All replies

  • What were the steps you took to add the function to your profile?

    In PowerShell, type notepad $profile and either paste the entire function into your profile or enter the full path to the script (not .\Function.ps1 but rather c:\this\is\the\full\path\function.ps1).

    Monday, March 9, 2015 2:05 PM
  • This is a copy paste of the line in my profile:

    l:\scripts\sccm\Add-NewComputerToSCCM.ps1

    but still it does not appear.


    Jan Hoedt

    Monday, March 9, 2015 3:31 PM
  • When you create a script, there is a difference between a script file and a function defined within a script file, so this depends on the content of your 'Add-NewComputerToSCCM.ps1' script.

    First, please read the about_Scopes help topic. There is a section in there titled "Using Dot Source Notation with Scope". Pay special attention to this section.


    -- Bill Stewart [Bill_Stewart]

    Monday, March 9, 2015 3:35 PM
    Moderator
  • Thanks, but I don't understand.

    when I add the scrip via .\myscript.ps1 it works, so why wouldn't it work via adding to the $profile?


    Jan Hoedt

    Monday, March 9, 2015 3:47 PM
  • If you are trying to make persistent functions on a single system, you can do the following:

    http://mikepfeiffer.net/2010/06/how-to-add-functions-to-your-powershell-session/

    and

    https://msdn.microsoft.com/en-us/library/bb613488(VS.85).aspx

    If you want this to work on multiple systems, then you need to create a module.


    Entrepreneur, Strategic Technical Advisor, and Sr. Consulting Engineer - Strategic Services and Solutions Check out my book - Powershell 3.0 - WMI: http://amzn.to/1BnjOmo | Mastering PowerShell Coming in April 2015! This posting is provided AS IS with no warranties or guarantees, and grants no rights.

    Monday, March 9, 2015 3:53 PM
  • That depends on the content of the script you're dot-sourcing.

    Here's a short demonstration.

    Suppose this script, test1.ps1:


    Write-Output "Hello, world"
    

    Now suppose this script, test2.ps1:


    function Test-Output {
      Write-Output "Hello, world"
    }
    

    If you run this:


    PS C:\Scripts> . .\test1.ps1
    

    PowerShell will dot-source test1.ps1 (i.e., run in current scope, don't create new scope). That will run the Write-Output cmdlet.

    However if you run this:


    PS C:\Scripts> . .\test2.ps1
    

    This means that PowerShell will dot-source test2.ps1. This means there will be no output, but there will now be a Test-Output function defined for the current scope. You can see this by typing the following:


    PS C:\> get-content function:Test-Output

      Write-Output "Hello, world"



    -- Bill Stewart [Bill_Stewart]

    Monday, March 9, 2015 3:58 PM
    Moderator
  • Thanks, that are exactly the links I followed before I opened this question.


    Jan Hoedt

    Monday, March 9, 2015 4:01 PM
  • The ans2wer is to look at the rest of you file to see that it has a call to your function somewhere after the function.  If you convert it to a module that call will not be made,

    As above..you need to try and understand scopes and dot sourcing OR.... post the whole scripts so someone can show you why it is happeng  this way.


    ¯\_(ツ)_/¯

    Monday, March 9, 2015 4:32 PM
  • Please try the examples I posted and make sure you understand what is happening. It will become clear once you understand how dot-sourcing and scopes work.


    -- Bill Stewart [Bill_Stewart]

    Monday, March 9, 2015 4:53 PM
    Moderator
  • Thanks!  This is the script

    https://www.dropbox.com/s/ckibrat4uhj6wr1/script.ps1?dl=0



    Jan Hoedt

    Monday, March 9, 2015 4:55 PM
  • Sorry but I can't download that. I can suggest, however, that you start very basic and try the examples I posted first. Make sure you understand what's happening with the very minimal examples.

    -- Bill Stewart [Bill_Stewart]

    Monday, March 9, 2015 4:57 PM
    Moderator
  • No problem. Could you provide an example function and the proper way to integrate it into the profile?
    That way I can compare and see what's going on.

    Jan Hoedt

    Monday, March 9, 2015 5:05 PM
  • Thanks!  This is the script

    https://www.dropbox.com/s/ckibrat4uhj6wr1/script.ps1?dl=0



    Jan Hoedt

    Looking at this it appears that it could never have worked.  I suspect you have run it as a script andnot a function and that creting a function caused it to break.

    If thisis all that was in your file why not just paste it into you profile.  Fix it first:

    Function Add-SAComputerDeviceToSCCM{
    	param(
    		[Parameter(Mandatory=$true)]
    		[string]$ComputerName,
    		[Parameter(Mandatory=$true)]
    		[string]$MacAddress,
    		[Parameter(Mandatory=$true)]
    		[string]$CollectionName,
    		[Parameter(Mandatory=$true)]
    		[string]$SiteCode,
    		[Parameter(Mandatory=$true)]
    		[string]$SCCMServer
    	)
    	cd $SiteCode+':' #'
    	Import-CMComputerInformation -ComputerName $ComputerName -MacAddress $MacAddress -CollectionName $CollectionName
    	Write-Host -ForegroundColor Green "[S]: $ComputerName is added to $CollectionName"
    	$CollectionQuery = Get-WmiObject -Namespace "Root\SMS\Site_$SiteCode" -Class SMS_Collection -ComputerName $SCCMServer -ErrorAction STOP -Filter "Name='$CollectionName'"
    	$CollectionQuery.RequestRefresh() | Out-Null
    	Write-Host -ForegroundColor White "[I]: Updating collection" -NoNewLine
    	Do{
    		Write-Host -ForegroundColor White '.' -NoNewLine
    		Start-Sleep -s 10
    	}
    	While((Get-CMDevice -CollectionName $CollectionName | Where-Object {$_.Name -eq $ComputerName}) -eq $null)
    	Write-Host -ForegroundColor Green " OK"
    }
    

    The last line will not work:

     While((Get-CMDevice -CollectionName $CollectionName | Where-Object {$_.Name -eq $ComputerName}) -eq $null)

    That requires a script block. What is it you are expecting it to do?

    If this sis sin a file then the file must be dot sourced.  Use the fullpath to the file and dot source it

    . c:\scripts\script.ps1

    Notice the <dot><space>


    ¯\_(ツ)_/¯

    • Marked as answer by janhoedt Tuesday, March 10, 2015 10:46 AM
    Monday, March 9, 2015 6:04 PM
  • No problem. Could you provide an example function and the proper way to integrate it into the profile?
    That way I can compare and see what's going on.

    Jan Hoedt

    The previous answers already showed you that.  I suspect that you just don't know the basics of scripting or PowerShell.  It would help if you spend some time reading about how PowerShell is designed to work.  You cannot guess at it if you have no formal programming training.

    Bill explained it in great detail but you don't have enough basic knowledge to understand the explanation.


    ¯\_(ツ)_/¯

    Monday, March 9, 2015 6:15 PM
  • PowerShell executes $profile in the current scope (i.e., it dot-sources $profile) when it starts.

    There's no difference between $profile and any other script you dot-source.

    You can experiment with the examples I gave you without needing to modify your current profile in any way.

    As noted previously: Start slowly and look carefully at the examples I posted, and read about scope and dot-sourcing. Run the examples and watch what happens.

    Once you really understand what's happening, you will understand how to answer your own question.


    -- Bill Stewart [Bill_Stewart]


    Monday, March 9, 2015 6:29 PM
    Moderator