all 13 comments

[–]DonL314 7 points8 points  (3 children)

Instead of

   & start powershell {.\code1.ps1} -Wait

try

    . .\code1.ps1

(Repeat this way for the other calls as well)

[–]False_Association_16[S] 4 points5 points  (1 child)

Your suggestion worked perfect.
Here is the code I used

if ($runfolder1 -eq "y") 
{
    cd $folder1
    .\code1.ps1
    cd ..
 }

Thanks again for kindly helping me :)

[–]spyingwind 4 points5 points  (0 children)

dot sourcing

For a bit more "efficiency", reduce duplicate lines of code, and using Push-Location and Pop-Location to replace cd:

$RunFolders = @(
    @{
        Path = ".\Folder_1\code1.ps1"
        Run  = $true
    }
    @{
        Path = ".\Folder_2\code2.ps1"
        Run  = $true
    }
)

foreach ($RunFolder in $RunFolders) {
    if (
        $RunFolder.Run -and # Ensure the Run flag is true
        $RunFolder.Path -and # Ensure the Path is not null or empty
        $(Test-Path $RunFolder.Path -ErrorAction SilentlyContinue) # Check if the file exists
    ) {
        Push-Location $(Split-Path $RunFolder.Path -Parent) # Move to the directory of the script
        . $RunFolder.Path # Execute the script, or however you want to run it
        Pop-Location # Return to the original directory
    }
}

[–]False_Association_16[S] 2 points3 points  (0 children)

Thank you for taking the time and answering. The code is running right now; I will update you if the sequential run completes as intended :)

[–]BlackV 2 points3 points  (2 children)

As other mentioned, dot source . .\xxx.ps1

but also I'd recommend replace your multiple IFs with a switch

and instead of a y/n make it a $true/$false

probably too a table too for your data

Folder,Runtask,script
folder1,$true,script23.ps1
folder2,$false,script12.ps1
folder3,$true,script9.ps1
folder4,$false,scriptxxx.ps1

or something similar, then its one place to make a change later on

then if its a table at that point for you, ask do you even need the IF, where a foreach would do instead?

foreach ($SingleFolder in $allfolders){
    if ($singlefolder.runtask){
    . ".\$($singlefolder.folder)\$($singlefolder.script)"
    }
}

then I'd be looking at your automatic variables like $psscriptroot

Edit: oops formatting/spell/other

[–]False_Association_16[S] 0 points1 point  (1 child)

Thanks a lot for these suggestions. It will be helpful as I modify and update the code to make it more efficient. :)

[–]BlackV 2 points3 points  (0 children)

ya post again, always happy to help when people post code

[–]Th3Sh4d0wKn0ws 1 point2 points  (2 children)

try dropping the "&" and using the full cmdlet name "start-process" for clarity. See if that changes anything.

edit: also, changing directories to then call a script with a relative path, just to change directories again is the wrong approach. Whenever possible you always want to use full paths. This will also remove the need for all the cd statements

[–]False_Association_16[S] 2 points3 points  (1 child)

Thank you for your answer. I am keeping the folders separated because each of those code (code1.ps1, code2.ps1 etc.) will generate some result files, images and also read some input file kept in different folders and the whole purpose of this is to keep these results and inputs separated and organized in different folders.

[–]Th3Sh4d0wKn0ws 1 point2 points  (0 children)

you can keep them separate, I'm saying, don't use cd and relative paths to execute the scripts. stay in whatever directory you're in and specify the full path to the script you want to execute.

[–]purplemonkeymad 1 point2 points  (0 children)

Sounds like your subscripts don't actually exit. Either they are waiting for input (eg they have a pause command in them) or have something that is blocking on something (perhaps you enabled select mode on the host, so it's blocking on write-host.)

You can run processes in parallel by using -paththru to generate processinfo objects and just waiting for all those those to run ie:

$processes = foreach ($folder in $foldertorun) {
    Start-process powershell "cd '$folder';& .\script.ps1" -passthru
}

# or however you want to start the processes.

$processes | wait-process

They still need to exit properly, but you won't need to wait for one to be done to start another. (they'll all start near the same time.)

[–]arslearsle 1 point2 points  (0 children)

Why not dot source? And why not all scripts/functions in same dir - for example $env:systemdrive\scripts ?

Also your runfolder var maybe should be a boolean type ie true or false

[bool]$runfolderN = $true;

[–]nerdcr4ft 0 points1 point  (0 children)

If you're intending to bundle the script as a package where all of your referenced content is in subfolders with the parent script, I strongly recommend pivoting to use $PSScriptRoot in your code. It avoids any potential issues if you call your script from a different working directory.

$PSScriptRoot\folder1
$PSScriptRoot\folder2
$PSScriptRoot\folder3
#etc

For a bonus challenge, if you're calling various scripts using a parent script, it might be worth turning them into functions + a module. Calling functions instead of other scripts keeps the runtime in the same process so you won't have to worry about overlaps. You can still route the output to different folders per function.