Powershell : Executing custom function on remote servers - powershell

i have custom functions list, and another config file that is going to be used by the functions, my goal is to run those functions on remote servers, considering that some functions call other function from within them that's why i can't use the method below to call functions that are loaded in the local session.
invoke-command -scriptblock ${function:foo}
is it possible to make a module out of it and then make that module get imported automatically on system boot rather than user logon.
any suggestions on how to accomplish the main goal ?

Well, if you want to install Powershell Module on the system just copy it to appropriate directory.
Installing Modules for all Users in Program Files
If you want a module to be available to all user accounts on the computer, install the module in the Program Files location.
$EnvProgramFiles\WindowsPowerShell\Modules\<Module Folder>\<Module Files>
Reference: https://msdn.microsoft.com/en-us/library/dd878350(v=vs.85).aspx
Install Modules in PSModulePath whenever possible, install all modules in a path that is listed in the PSModulePath environment variable or add the module path to the PSModulePath environment variable value.
The PSModulePath environment variable ($Env:PSModulePath) contains the locations of Windows PowerShell modules. Cmdlets rely on the value of this environment variable to find modules.
By default, the PSModulePath environment variable value contains the following system and user module directories, but you can add to and edit the value.
$PSHome\Modules (%Windir%\System32\WindowsPowerShell\v1.0\Modules)
# This location is reserved for modules that ship with Windows. Do not install modules to this location.
$Home\Documents\WindowsPowerShell\Modules (%UserProfile%\Documents\WindowsPowerShell\Modules)
$Env:ProgramFiles\WindowsPowerShell\Modules (%ProgramFiles%\WindowsPowerShell\Modules)

Related

How does Powershell Auto-Load Modules?

We learn that Powershell introduced Module Auto-Loading in 3.0 :
... PowerShell imports modules automatically the first time that you
run any command in an installed module. You can now use the
commands in a module without any set-up or profile configuration, ...
And this is done via PSModulePath.
What the docs fail to explain is how Powershell can detect which commands are in a module without first loading the module.
That is, when I use Import-Module, I "know" that Powershell will execute (??!) the powershell code in my .psm1 file, exporting all functions, ... or whatever I spec with Export-Modulemember.
However, the Auto-Load feature has to know before hand that a certain command is available via a certain module without actually loading the module.
Since we had some misbehaving third party modules in PsModulePath and since we have a very few modules that we wrote ourselves that we like to anchor in PSModulePath, I would very much like to understand how the files in PSModulePath are processed.
This is a partial answer.
This is done/implemented via Get-Command and this seems to be enabled to "parse" module files without actually executing the PoSh Code there. See below.
From the powershell docs:
Implicitly Importing a Module
... works on any module in a directory that is included in the value
of the PSModulePath environment variable ...
To support automatic importing of modules, the Get-Command cmdlet
gets all cmdlets and functions in all installed modules, even if the
module is not imported into the session. ...
And then:
Get-Command
The Get-Command cmdlet gets all commands that are installed on the
computer ...
Get-Command that uses the exact name of the command, without
wildcard characters, automatically imports the module that contains
the command so that you can use the command immediately. ...
Get-Command gets its data directly from the command code, unlike
...
The docs do not explain how this is implemented, but one could possibly look up how it's done in the source code. (I wasn't so far able to find it, despite browsing the sources for a while.)
Incidentally I find mentioned that Powershell 3 was the first version to expose the AST, so it stands to reason that the posh code does exactly that: Parse the Scripts and inspect their AST in some way to determine if the command is provided.

Can I run powershell commands without installing module?

I would like to run a script that requires to use commands from the GroupPolicy module. However, this module is not guaranteed to be installed on every machine and some machines might be stand alone. Can I have have the module copied over with my scripts and run commands from it, without installing the module?
Can I have have the module copied over with my scripts and run commands from it, without installing the module?
Yes. Installing a module in PowerShell simply means placing it one of the directories listed in the $env:PSModulePath environment variable, which allows PowerShell to discover it and import (load) it on demand, as part of the module auto-loading feature
However, you're free to copy modules elsewhere, as long as the code that relies on them knows their path and loads them with an explicit Import-Module call.
For instance, if you bundle your script with a GroupPolicy subdirectory containing that module, the script could import it as follows:
# $PSScriptRoot contains the calling script's directory.
Import-Module $PSScriptRoot\GroupPolicy

How to share a Powershell psm1 across Azure Functions

You can create a modules folder and place a psm1 file there for auto loading. Is there a way to share that psm1 across functions in the same App Service?
Yes, you may move your modules folder up the directory tree and place it under wwwroot, e.g. D:\home\site\wwwroot\mymodules. Auto-loading will not occur in this setup, so you will need to explicitly add the Import-Module command in your PowerShell script, e.g.
Import-Module "D:\home\site\wwwroot\mymodules\MyScript.psm1";
If you suspect that MyScript.psm1 is already installed on the system and need to override it with your version, add the -Global flag as follows
Import-Module "D:\home\site\wwwroot\mymodules\MyScript.psm1" -Global;

Installing PowerShell module persistently for all users

I'm installing a PowerShell module via Octopus Deploy onto a number of different servers. For testing purposes, I went with the guidance of Microsoft's documentation for installing PowerShell Modules.
This worked fine, but as the documentation stated, my changes would be visible only for the current session. That is, if I were to do the following:
$modulePath = [Environment]::GetEnvironmentVariable("PSModulePath", [EnvironmentVariableTarget]::Machine)
# More practically, this would be some logic to install only if not present
$modulePath += ";C:\CustomModules"
[Environment]::SetEnvironmentVariable("PSModulePath", $modulePath, [EnvironmentVariableTarget]::Machine)
When running this installer automatically on tentacle servers, future PowerShell sessions do not appear to see the newly installed modules.
How can I install a PowerShell module in a profile agnostic way so that every PowerShell session started can see it?
PowerShell can only "see" modules installed in one of the directories listed in $env:PSModulePath. Otherwise you'll have to import the module with its full path.
To make a new module visible to all users you basically have two options:
Install the module to the default system-wide module directory (C:\Windows\system32\WindowsPowerShell\v1.0\Modules).
Modify the system environment so that PSModulePath variable already contains your custom module directory (e.g. via a group policy preference).
The latter will only become effective for PowerShell sessions started after the modification was made, though.
This profile applies to all users and all shells.
%windir%\system32\WindowsPowerShell\v1.0\profile.ps1
After taking the steps you spelled out in your question (which I think is the general way to go), I found two ways to get the new module source recognized by Powershell:
Restart the machine. (Works every time.)
Reset the PSModulePath in each open session.
$env:PSModulePath=[Environment]::GetEnvironmentVariable("PSModulePath", "Machine")
I found this was necessary to run in both normal and elevated prompts to get this to work without restarting in each type of prompt. (See also the conversation # Topic: PSModulePath.)

How do I change where a Powershell module is installed?

I am using version 3.0 and there doesn't seem to be a way to specify a default folder where all your modules are installed. In particular, I am trying to install Posh-Git, but it insists on installing the modules in MyDocuments\WindowsPowershell. How do I change this?
By default, PowerShell looks for modules in one of two locations, both are specified in the
PSModulePath environment variable.
System modules: %windir%\System32\WindowsPowerShell\v1.0\Modules
Current user modules: %UserProfile%\Documents\WindowsPowerShell\Modules
You can add your own module directory to the path:
$env:PSModulePath+=';c:\MyModules'