4

Why is the following code not working? According to this article the usage of global should be correct: http://technet.microsoft.com/en-us/library/ff730957.aspx

Function global:writeLog {
    param($logType, $logString, $logFile)

    $fileStream = New-Object IO.FileStream $logFile ,'Append','Write','Read'
    $streamWriter = New-Object System.IO.StreamWriter $fileStream

    $time = get-date -Format "hh:mm:ss"
    $streamWriter.writeLine("[${time}][$logType] ${logString}")

    $streamWriter.close()

}

$temp = {
    writeLog -logType "INFO" -logString "Test" -logFile "d:\scripts\powershell\logtest.txt"
}

Start-Job -ScriptBlock $temp 
get-job | receive-job -AutoRemoveJob -Wait

This is the exception that powershell throws

The term 'writeLog' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
    + CategoryInfo          : ObjectNotFound: (writeLog:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    + PSComputerName        : localhost
2
  • Does your $temp{ writeLog ... } exist for anything other than passing arguments? Instead pass the arguments directly from Start-Job to the function using the ArgumentList parameter, skipping the middle-man. Commented Oct 9, 2013 at 16:58
  • Write a more precise question! Commented Feb 25, 2020 at 13:41

4 Answers 4

2

PowerShell jobs actually run in a separate PowerShell process. You can see this like so:

$pid
Start-Job {$pid} | Receive-Job -Wait

Where $pid is the current PowerShell's process id.

Anything that needs to be accessed from the script that runs in the job, must be either defined in the scriptblock passed to Start-Job i.e. function defined in the script block or as parameters passed into the script block using the -ArgumentList parameter on Start-Job or the script can dot source another script (or import a module) that contains the functions it needs. Personally, I would put shared functions in a module like Utils.psm1 and then import like so:

Start-Job {param($scriptdir) Import-Module $scriptdir\Utils.psm1; ...} -Arg $PSScriptRoot
Sign up to request clarification or add additional context in comments.

Comments

2

From the documentation of Start-Job:

A Windows PowerShell background job runs a command "in the background" without interacting with the current session.

Therefor, the current session scope is ignored.

Trivial Solution: Define the function inside the scriptblock.

$JobScript = { 
    function write-log {
        ....
    }
    write-log <parameters>
}

Alternatively, check these related questions:

Powershell: passing parameters to a job

Variables in Start-Job

Comments

2

Define the function in a script block, then use

  1. Invoke-Command with NoNewScope to get it in the current scope
  2. The InitializationScript parameter to get it into the job
#Create Shared Functions Script Block
[scriptblock] $func = {function getPID() {write-output "Function Running in process id: $pid!"}}

#Set up functions in normal script scope so they're accessible here
Invoke-Command -NoNewScope -ScriptBlock $func

write-output "Main script started"

#run the function from the parent script
getPID

#Create background job script
$jobScript = {getPID}

#Run background job
write-output "starting background job"
Start-Job $jobScript -name "Job1" -InitializationScript $func

get-job | Receive-Job
get-job | Stop-Job
get-job | Remove-Job

Comments

0

Testing Global functions. Late, but it works today 9/28/23

Function Global:MyDisplay{
     Write-Host "Wahoo!" -ForegroundColor Green

}

Save to a file: Test.ps1
Call the file: Test.ps1
Type Function Name: MyDisplay

Display output: Wahoo!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.