4

Do you guys know, whether it's possible to convert PowerShell project consisting solely of functions, into module? What I want to achieve is to create distributable module of all my functions so others can use it. But without spending time of converting all functions into cmdlets.

Each of my functions is in separate file. When I then create *.psd1 and I try to include functions via 'FunctionsToExport', it doesn't work. I can't see my functions after module is loaded.

Is it even possible to export function from module when they're NOT (all of them) inside a .psm1 file? I'm still trying to figure out real differences and use of *psd1 and *psm1 files.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Martinecko
  • 1,719
  • 4
  • 22
  • 35

2 Answers2

6

Yes, you can turn a bunch of .ps1 files into a module. Create a new folder in your module directory $env:USERPROFILE\Documents\WindowsPowerShell\Modules and put all the .ps1 files in that folder. Also create two text files <foldername>.psm1 and <foldername>.psd1 in the folder, so that you have a structure like this:

$env:USERPROFILE
`-Documents
  `-WindowsPowerShell
    `-Modules
      `-MyModule
        +-MyModule.psd1
        +-MyModule.psm1
        +-script1.ps1
        +-script2.ps1
        :
        `-scriptN.ps1

Put the following line in the .psm1 file, so that it "imports" all .ps1 files:

Get-ChildItem -Path "$PSScriptRoot\*.ps1" | % { . $_.FullName }

and specify your metadata in the module manifest (the .psd1 file), e.g.:

@{
  ModuleToProcess   = 'MyModule.psm1'
  ModuleVersion     = '1.0'
  GUID              = '6bc2ac1e-2e88-4bc3-ac84-ecd16739b6aa'
  Author            = 'Matthew Lowe'
  CompanyName       = '...'
  Copyright         = '...'
  Description       = 'Description of your module.'
  PowerShellVersion = '2.0'

  FunctionsToExport = '*'
  CmdletsToExport   = ''
  VariablesToExport = ''
  AliasesToExport   = ''
}

A GUID can be generated for instance via [guid]::NewGuid().

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • Amazing answer. Thank you. Missing link for me was line ModuleToProcess = 'MyModule.psm1'. Default *psd1 file doesn't contain it. I was trying to dot-source function files from in this file, but apparently, it never got called. – Martinecko May 26 '15 at 06:29
  • You can limit exported cmdlets by adding names to `CmdletsToExport`. I have several helper cmdlets written that I do not want polluting the session. – hsimah Aug 03 '18 at 04:30
  • 1
    @hsimah Personally, I'd use "official" names (`Get-Foo`, `Select-Something`, ...) for functions/cmdlets I want to export, names without a hyphen (`FooHelper`, ...) for helper functions I don't want to export, and then export only the former via `FunctionsToExport = "*-*"`. – Ansgar Wiechers Aug 03 '18 at 07:11
2

Here's a very simple way of doing it, without including your functions through dot sourcing mode, as it's done in the other answer:

  1. Create a folder C:\MyModules.
  2. Inside this folder, create an empty file named MyModules.PSM1.
  3. Append to MyModules.PSM1 file, all functions (they don't need to be advanced) you want in the module.
  4. YOU ARE DONE.

Now, you have a folder ( C:\MyModules ) that you must install in the target machine.

To install it in the target machine (per user), copy the folder C:\MyModule to the user's default module location (i.e. folder): $home\Documents\WindowsPowerShell\Modules.

Now, this user can type in any PowerShell session the first letter(s) of any function included in your module, that PowerShell's IntelliSense will recognize the function from your module (and uggest the completion substring).

If you don't like the name MyModule, you can change it, as long as you change the folder name as well as the PSM1 file name.

You can also opt to install your module for all users: help about_modules.

  • 5
    This is actually something I wanted to avoid. Putting all functions into single file is not acceptable for me. It's really hard to do code reviews on such file and. Apart from that, I want to keep certain directory structure among my functions. I come from java world and I tend to keep functions in 'packages' or directories where they belong .. core/utils/network etc. – Martinecko May 26 '15 at 06:32
  • Well, you decide what's better for you. I told you how to implement what you asked for, **in a very simple way**. The module is just that a module, and how its content is ordered, does not interest anyone. At your side, you have the code that will result in that module in a way **YOU** like, arranged the way you like. Using them as source, you build a module, and how this module contains the code does not matter anyone, and it even does alter the way you order the sources (which are separated from the module, of course). I told you how to build a module **in a very simple way**. –  May 29 '15 at 05:28
  • Well, in case of including all functions, currently in separate files, into single *.psm1 file actually affects their order pretty much :-). Your answer is correct from general point of view, however it doesn;t answer my original question. From original question: "Is it even possible to export function from module when they're NOT (all of them) inside a .psm1 file? ". Sorry if my comment was offeding to you in any way. For that I apologize. I still very much appreciate your effort in answering, thanks. – Martinecko May 29 '15 at 09:15
  • I'm not offended, but you're bringing into context issues **not** mentioned in your OP. **1st)** you didn't say you want to avoid putting all files into a single PSM1 file. **2nd)** the order of files in the PSM1 file does not matter **unless** they have some interdependence. **3rd)** you didn't mention you want to export any function not included in the module. This is not possible, of course, because if a function is not included in a module, it cannot be managed by this module. Let's suppose you have 5 functions to include in your module (f1, f2, f3, f4, f5). –  May 30 '15 at 05:04
  • Using my method, all 5 would be exported by default. If you don't want some be exported, you can use the export directive to select **all** functions you want to export. Let me know if you need more clarification. –  May 30 '15 at 05:04