it:ad:powershell:howto:run_scripts_within_the_package_manager_console:background_info

IT:AD:Powershell:HowTo:Run scripts within the Package Manager Console/Background Info

Summary

Very useful: delivering userful company wide tools as powershell scripts, delivered easily as Nuget packages…what's not to love about that?!

There's underlying concepts are that You have

Create a Powershell Module

It's not obligatory, but you should prefer making a Powershell Module, rather than a Powershell Script.

Create a Nuget Package

The Nuget Package is how the PowerShell Module will be created.

Create a Package Tools Script

Nuget package has a designated directory for putting scripts in.

And a list of designated filenames to look for.

So, create a \Tools\ Directory as a sibling to the \content\ folder

In it you can create the following files:

  • Init.ps1:
    • runs the first time a package is installed in a solution. Not once per project in the solution.
      • It also runs every time the solution is opened.

      * Install.ps1:

    • runs when a package is installed in a project (each project install, even if multiple, in a solution).
    • runs after init.ps1 if there is one.
    • requirement: the package lib folder must have content of some kind, or it will not fire. Q: would a _placeholder.txt will do?
  • Uninstall.ps1:
    • runs when a package is installed in a project (each project install, even if multiple, in a solution).
We're ony insterested in the `init.ps1` at this point.

At the top of your init.ps1 script file, add this line:

    param($installPath, $toolsPath, $package, $project)
    Import-Module(Join-Path $toolsPath MyModule.psm1);

  • $installPath is the path to the folder where the package is installed
  • $toolsPath is the path to the tools directory in the folder where the package is installed
  • $package is a reference to the package object.
  • $project is a reference to the EnvDTE project object and represents the project the package is installed into.
    • Note: This will be null in Init.ps1 as it is a solution level script, not a project level one like $install.ps1 or $uninstall.ps1

When you are testing $project in the console while creating your scripts, you can set it to $project = Get-Project

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>XAct.AdminScripts</id>
    <version>0.0.0.12</version>
    <authors>xact</authors>
    <owners>xact</owners>
    <licenseUrl>https://bitbucket.org/xact/cs.ff.xact.lib/wiki/General/Legal/</licenseUrl>
    <projectUrl>https://bitbucket.org/xact/cs.ff.xact.lib/</projectUrl>
    <!-- <iconUrl/> -->
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Powershell scripts to administer XActLib assemblies in a solution.</description>
    <tags>XAct XActLib</tags>
    <dependencies>
      <!--Turned out I didn't want it...<dependency id="SolutionScripts" version="1.2" /> -->
    </dependencies>
  </metadata>
  <!-- Note:
         We're specifying SolutionsScripts\PS.LIB or it will end up in the SolutionScripts folder :-(
         We don't forget to put the init.ps1 
  <files>
     <file src="..\PS.LIB\**\*.*" target="SolutionScripts\PS.LIB" /> 
     <file src="..\xact.psm1" target="SolutionScripts" /> 
     <file src="init.ps1" target="Tools" /> 
  </files>  
</package>

The idea for our init.ps1 file was clept'ed from the SolutionScripts nuget project – but his solution didn't seem to work with Nuget's distribution mechanism, and only appeared to work with manual installations…hum.

param($installPath, $toolsPath, $package, $project)

Write-Host "InstallPath: $installPath";
Write-Host "toolsPath: $toolsPath";
Write-Host "package: $package";

#$parentFolder = resolve-path "$installPath\..";
$global:solutionScriptsContainer = Join-Path $installPath "SolutionScripts"

function global:Update-XAct-AdminScripts()
{       
Write-Host "Scanning $($global:solutionScriptsContainer) folder for PS scripts to mount.";
        
        if(!(test-path $solutionScriptsContainer -pathtype container)) 
        {
                new-item $solutionScriptsContainer -type directory
        }
		
        $files = Get-ChildItem $solutionScriptsContainer

        foreach ($file in $files)
        {       
                if ($file.extension -eq ".ps1") 
                {
                        Write-Host "        Sourcing: $file"                    
                        . $file.fullname
                }
                if ($file.extension -eq ".psm1")
                {
                        Write-Host "Importing Module: $file"
                        Import-Module $file.fullname
                }
        }
}

Update-XAct-AdminScripts

The package, as it has no lib or content files is intended to be a Solution level package.

But I noticed that at a project level, it's very easy to not see it (it won't show packages of the solution) and …let you reinstall it for the project… ie…a big flaky design.

I've also noticed that

  • Best to uninstall the old one first, before installing updates
  • Restarting Visual Studio after doing it, to let the scripts settle in correctly.

Note that you can refresh scripts (good for debugging…) by invoking

 Update-XAct-AdminScripts

Just as Powershell Modules look for the Profile.ps1 file in the Modules path, Nuget does something similar:

$profile
C:\Users\philha\Documents\WindowsPowerShell\NuGet_profile.ps1

But…that doesn't scale well (see http://lostechies.com/matthinze/2012/01/05/solutionscripts-little-scripts-for-the-nuget-console/)

Instead

Then put ps1 and psm1 files in a folder called SolutionScripts in the solution root (sibling to packages)

That's easier than having to setup modules, etc….but it doesn't make it easy to distribute the scripts…

  • /home/skysigal/public_html/data/pages/it/ad/powershell/howto/run_scripts_within_the_package_manager_console/background_info.txt
  • Last modified: 2023/11/04 02:26
  • by 127.0.0.1