Meilleur auteur de réponses
Auto-chargement des modules Powershell ne fonctionne pas

Question
-
Bonjour tous,
Voici tout d’abord ma version Powershell :
PS C:\Program Files\WindowsPowerShell\Modules> $PsVersionTable Name Value ---- ----- PSVersion 5.1.17134.407 PSEdition Desktop PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} BuildVersion 10.0.17134.407 CLRVersion 4.0.30319.42000 WSManStackVersion 3.0 PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 PS C:\Program Files\WindowsPowerShell\Modules>
J’avais cru comprendre que les modules en *.psm1 étaient automatiquement chargés dès lors qu’ils étaient placés dans leur répertoire par défaut.
(après ouverture d’une nouvelle session PowerShell)
Les répertoires par défaut des modules et manifestes sont chez moi :PS C:\Users\administrateur.HJG> $env:PSModulePath -split (';') C:\Users\administrateur.HJG\Documents\WindowsPowerShell\Modules C:\Program Files\WindowsPowerShell\Modules C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\ PS C:\Users\administrateur.HJG>
J’ai donc créé un module élémentaire "test-module .psm1" (module "script" dans un des répertoires par défaut .
Quelque chose de très simple.Juste pour tester :PS C:\Program Files\WindowsPowerShell\Modules> Get-Content .\test-module.psm1 Function Test-module { Write-Host 'Test Module' } PS C:\Program Files\WindowsPowerShell\Modules>
Or après relance de Powershell pour nouvelle session, rien ne se passe.
Le module n’a pas été chargé :PS C:\Program Files\WindowsPowerShell\Modules> test-module test-module : Le terme «test-module» n'est pas reconnu comme nom d'applet de commande, fonction, fichier de script ou programme exécutable. Vérifiez l'orthographe du nom, ou si un chemin d'accès existe, vérifiez que le chemin d'accès est correct et réessayez. Au caractère Ligne:1 : 1 + test-module + ~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (test-module:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException PS C:\Program Files\WindowsPowerShell
Pour charger le module, je suis obligé de le faire manuellement par la cmdlet « import-module »
Et j’ai bien alors :PS C:\Program Files\WindowsPowerShell\Modules> get-command -Module test-module CommandType Name Version Source ----------- ---- ------- ------ Function Test-module 0.0 test-module PS C:\Program Files\WindowsPowerShell\Modules>
A noter que j'ai importé des modules depuis des dépôts externes (PSGallery) à l'aide de la cmdlet "Install-Module"
Et tout fonctionne très bien.
Les modules se chargent bien automatiquement.Il y a certainement quelque chose qui m'a échappé.
Merci pour votre aide.
hjg
- Modifié nonsolum lundi 24 décembre 2018 09:19
Réponses
-
Bonjour,
La demande date de plus d'un an mais n'ayant pas eu de réponse et ayant cherché moi-même. J'apporte la solution que j'ai trouvé :)
Pour que l'auto-chargement soit effectif, il faut qu'il y est un dossier {nom du module} dans un des dossiers de
$env:PSModulePath
et que ce dossier porte le même nom que les fichiers .psd1 et .psm1
Agréable journée à tous les codeurs
Osilio
- Proposé comme réponse Osilio mardi 30 mars 2021 16:04
- Marqué comme réponse Alexis ThorezModerator mardi 30 mars 2021 16:57
Toutes les réponses
-
salut nonsolum
je crois qu'il te faut le fichier version (manifeste) du module pour l'autoload, le fichier .psd1
PS : petit complément sur le sujet sur ce blog en anglais rubrique "Module autoloading"
dernière info la bonne !! :
Importation implicite d'un module (PowerShell 3.0)
À compter de Windows PowerShell 3.0, les modules sont importés automatiquement lorsqu'une cmdlet ou une fonction du module est utilisée dans une commande. Cette fonctionnalité fonctionne sur n'importe quel module d'un répertoire inclus dans la valeur de la variable d'environnement PSModulePath .
- Modifié 6ratgus jeudi 27 décembre 2018 15:01
-
Merci pour les infos
J’ai bien mon module « test-module.psm1 » dans un des répertoires de la variable d’environnement PSModulePath.
J’ai en effet :
PS C:\Program Files\WindowsPowerShell\Modules> gci Répertoire : C:\Program Files\WindowsPowerShell\Modules Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 12/04/2018 01:38 Microsoft.PowerShell.Operation.Validation d----- 12/04/2018 01:38 PackageManagement d----- 12/04/2018 01:38 Pester d----- 12/04/2018 01:38 PowerShellGet d----- 20/12/2018 22:00 PSLogging d----- 12/04/2018 01:38 PSReadline -a---- 28/12/2018 12:24 107 Test-module.psm1 PS C:\Program Files\WindowsPowerShell\Modules>
Je décide de compléter mon module en ajoutant la Cmdlet « Export-ModuleMember »
PS C:\Program Files\WindowsPowerShell\Modules> Add-Content` -Path .\Test-module.psm1 -Value "Export-ModuleMember -Function 'Test-Module' " PS C:\Program Files\WindowsPowerShell\Modules>
J’ai donc maintenant le module « test-module » comme suit :
PS C:\Program Files\WindowsPowerShell\Modules> Get-Content .\Test-module.psm1 Function Test-Module { Write-Host 'Test Module' } Export-ModuleMember -Function 'Test-Module' PS C:\Program Files\WindowsPowerShell\Modules>
À noter : la documentation précise que les fonctions sont, par défaut, automatiquement exportées à l’exception des alias et des variables.
Seulement, comme je l’ai précisé lors de mon précédent post, cela ne marche pas chez moi.
Alors je crée un « manifest » comme suit :
PS C:\Program Files\WindowsPowerShell\Modules> New-ModuleManifest -Path ` '.\test-module.psd1' -Author 'hjg' -RootModule 'test-module.psm1' PS C:\Program Files\WindowsPowerShell\Modules>
Et je vérifie si tout est correct :
PS C:\Program Files\WindowsPowerShell\Modules> Test-ModuleManifest .\test-module.psd1 ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Script 1.0 test-module Test-Module PS C:\Program Files\WindowsPowerShell\Modules>
Pas de problème, semble-t-il.
J’ouvre une nouvelle session PowerShell.
Puis je teste alors le couple module/manifest :
PS C:\Program Files\WindowsPowerShell\Modules> test-module test-module : Le terme «test-module» n'est pas reconnu comme nom d'applet de commande, fonction, fichier de script ou programme exécutable. Vérifiez l'orthographe du nom, ou si un chemin d'accès existe, vérifiez que le chemin d'accès est correct et réessayez. Au caractère Ligne:1 : 1 + test-module + ~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (test-module:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException PS C:\Program Files\WindowsPowerShell\Modules>
Rien à faire, cela ne marche pas, même si on se situe dans le cas où serait chargé dans la foulée le module suite à l’appel de fonction « test-module ».
Il me faut passer par la Cmdlet « Import-Module » et charger ainsi manuellement le module :
PS C:\Program Files\WindowsPowerShell\Modules> Import-Module .\Test-module.psm1 PS C:\Program Files\WindowsPowerShell\Modules>
Et puis:
PS C:\Program Files\WindowsPowerShell\Modules> Test-Module Test Module PS C:\Program Files\WindowsPowerShell\Modules>
Si je veux rendre pérenne l’import je dois ajouter au fichier profile de PowerShell la Cmdlet « Import-module » :
PS C:\Program Files\WindowsPowerShell\Modules> Add-Content -Path $profile` -Value "Import-Module 'C:\Program Files\WindowsPowerShell\Modules\Test-module.psm1'" PS C:\Program Files\WindowsPowerShell\Modules
Où se trouve le nœud ?
hjg
- Modifié nonsolum dimanche 30 décembre 2018 09:49
-
-
Bonjour,
La demande date de plus d'un an mais n'ayant pas eu de réponse et ayant cherché moi-même. J'apporte la solution que j'ai trouvé :)
Pour que l'auto-chargement soit effectif, il faut qu'il y est un dossier {nom du module} dans un des dossiers de
$env:PSModulePath
et que ce dossier porte le même nom que les fichiers .psd1 et .psm1
Agréable journée à tous les codeurs
Osilio
- Proposé comme réponse Osilio mardi 30 mars 2021 16:04
- Marqué comme réponse Alexis ThorezModerator mardi 30 mars 2021 16:57
-
Bonjour,
La demande date de plus d'un an mais n'ayant pas eu de réponse et ayant cherché moi-même. J'apporte la solution que j'ai trouvé :)
Pour que l'auto-chargement soit effectif, il faut qu'il y est un dossier {nom du module} dans un des dossiers de
$env:PSModulePath
et que ce dossier porte le même nom que les fichiers .psd1 et .psm1
Agréable journée à tous les codeurs
Osilio
ça fait un moment que j'étais passé à autre chose. :-)
Je crois me souvenir que, oui, c'est la solution.
En tout cas Merci pour cette suggestion.
hjg
-
Bonjour nonsolum,
Il faut effectivement que le module (fichier .pms1) soit dans un répertoire qui porte le BaseName du fichier .psm1 (MonModule.psm1 dans un répertoire nommé MonModule)
Pour importer automatiquement tous les modules, tu peux le faire via le fichier profile. Ce dernier est chargé automatiquement au lancement d'un shell. Attention, il y a différents fichiers profile possible (powershell, powershell ISE, Powershell dans VScode, et pour un utilisateur ou tous, ils ne sont pas stockés au même endroit).
# Pour tous les modules localisés dans un des path de $Env:PSpath
Get-Module -ListAvailable | Import-Module
# Pour les modules situés dans un autre path
$Path = ...\MonPath\MonModule
Import-Module -FullyQualifiedName $Path
Point d'attention : attention le chargement de tous les modules disponibles peut être consommateur de RAM sur la machine, en vain si on n'en a pas réellement besoin. Si le chargement desdits modules prend du temps (à l'instar des Update-Module), on peut s'affranchir de ceci, toujours dans un fichier profile, en exécutant les cmdlets précédentes comme un job.
ex. :
Start-Job -Name "Chargement des modules" -ScriptBlock { Get-Module -ListAvailable | Import-Module}
Ainsi, au chargement (exécution) du profile, on récupère la main tout de suite, et PS fait sa tâche d'importation des modules en tâche de fond. Cela peut sembler inutile, mais reste à tester en fonction du nombre de modules à charger.
Personnellement, j'utilise ce principe pour mettre à jour mes modules (et j'en ai un paquet), tous les vendredi en tâche de fond.Je te mets ceci ci-dessous pour l'exemple
# Mise à jour des modules chaque vendredi $Date = Get-Date if ($Date.DayOfWeek -eq "friday") { Write-Host "Mise à jour des modules en tâche de fond (Get-Job pour vérifier)" -ForegroundColor 'DarkGray' Start-Job -Name "UpdateModule" -ScriptBlock { Get-InstalledModule | foreach { $NewVersion = (find-module $_.name).version if ($NewVersion -gt $_.version) { Write-Host "$($_.name) a une mise à jour de $($_.version) vers $NewVersion" -ForegroundColor green Write-Host "Mise à jour de $($_.name) vers version $NewVersion" -ForegroundColor Yellow Update-Module -Name ($_.name) -Force -AcceptLicense -Scope CurrentUser Write-Host "désinstallation de la version $($_.version)" -ForegroundColor Yellow Uninstall-Module -Name $_.name -RequiredVersion $_.version -force Write-Host "$($_.name) a été mis à jour en version $NewVersion" -ForegroundColor Yellow } # end if } # end foreach } # end scriptblock } # end if
Mon profil se charge en moins de 100 ms ... et j'ai la main au bout de ce temps, malgré le fait que la mise à jour des modules puisse durer ... un certain temps pour ne pas dire un temps certain.:-) Ca bosse en tâche de fond.
[... "Patience et longueur de temps font plus que force ni que rage"
De Jean de la Fontaine j'en fais ma devise....]
Les Fables de La Fontaine devraient être enseignées de manière obligatoire dès le collège (et pas que celle-là), car elles sont toutes empreintes de vérité. Le 'sieur La Fontaine était un critique de son époque et d'aucuns diraient un contestataire. Perso, j'ai "Aide-toi, le ciel t'aidera" (Le laboureur et ses enfants) comme crédo, mais je pourrais en avoir d'autres.
Cordialement
Olivier