call one powershell script from another

Hi,
I have two powershell script files test1.ps1 and test2.ps1. Both of them are on same folder (c:\myscript).

test1.ps1 has following line and test2.ps2 has few simple powershell commands

Start-Transcript -Path c:\myscript\log1.txt
codes to do some stuff
& .\test2.ps1
codes to do some stuff
Stop.Transcript

When I run test1.ps1 manually from the PS command prompt, the script executes fine without any errors.
However if I run as part of the schedule task then it throws following error:

& : The term '.\test2.ps1' 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.
At C:\myscript\test1.ps1:74 char:3
+ & .\test2.ps1
+   ~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (.\test2.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Line 74 is

& .\test2.ps1

On the scheduled task >> the Action has
Action: Start a program
Details: Powershell.exe -ExecutionPolicy Bypass C:\myscript\test1.ps1

I am not sure why it throws error when running via schedule task, Any help would be much appreciated, thank you.

5 Spice ups

Try Invoke-Expression instead of &.

1 Spice up

Something like that:

$command = “.\test2.ps1"
Invoke-Expression $command

I think it the problem is that you are not using an explicit path. You can verify my assumption by inserting

$PWD; pause

to the line above to see what location the script is in.

If you did want to keep the relative path in your script you can use the Set-Location cmdlet to make sure you are where you think you are. I prefer to use environmental variables such as $ENV:SystemDrive and just list the location.

2 Spice ups

Invoke-Expression is very handy but I always try to use it as a last resort because it can easily lead to code injection.

Most of the time a PowerShell script is running in the user’s context so they could just simply run the command directly instead of doing some Invoke-Expression trickery but it is still worth thinking about whenever you use that cmdlet.

thank you

I have tried the following

$command = “.\test2.ps1"
Invoke-Expression $command

but got this error

.\test2.ps1 : The term '.\test2.ps1' 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.
At line:1 char:1
+ .\test2.ps1
+ ~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (.\test2.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

By default when you run powershell it will be in a current directory of c:\windows\system32 (as admin ) or c:\users\username (as normal user) running powershell

Assuming you have both scripts in the same directory and hello.ps1 is the first script and goodbuy.ps1 is the second

You can use the automatic variable $PSScriptRoot to see where the first script was called from

Hello.ps1

write-host "Hello"
$PSScriptRoot 

$ScriptToRun= $PSScriptRoot+"\goodbuy.ps1"

&$ScriptToRun

Goodbuy.ps1

write-host "Goodbuy"
3 Spice ups

thank you britv8, your solution has worked without any errors.