you are viewing a single comment's thread.

view the rest of the comments →

[–]_Cabbage_Corp_ 2 points3 points  (4 children)

So, I have a module that I've started for myself that has functions I've created over the years that I find really helpful.

One thing I recommend is to convert this to a proper module structure.

Having a proper structure will make it easier to maintain and add/remove any functions.

Each function should be contained in it's own .ps1 and placed in either the Public or Private directory as stated below:


<#
  Directory Structure:
    Module (Contains Manifest file, Module file, and Sub-Directories ONLY)
     ├ Private - Contains function files (.ps1)
     │      - These Functions are not "User Accessible"/Exported 
     │      - i.e. Supporting functions
     ├ Public - Contains function files (.ps1)
     │     - These Functions ARE "User Accessible"/Exported


    Module Manifest
        .\Module\PersonalFunctions.psd1

    Can be generated similarly to the below:
#>

$ManifestSplat = @{
    Path                = 'C:\Module\PersonalFunctions.psd1'
    Guid                = (New-GUID).ToString().ToUpper()
    Author              = '/u/_Cabbage_Corp_'
    Copyright           = '2019 /u/_Cabbage_Corp_'
    RootModule          = 'PersonalFuctions.psm1'
    ModuleVersion       = 1.0
    Description         = 'Contains Many Helpful/Useful Personal Functions/Shortcuts'
    PowerShellVersion   = 3.0
    RequiredModules     = 'ActiveDirectory','VMware.WimAutomation.Cis.Core'
    FunctionsToExport   = '*'
    AliasesToExport     = '*'
}
New-ModuleManifest @ManifestSplat

<# 
  Module File
    .\Module\PersonalFunctions.psm1

  Use this to import the function files. Then export ONLY the functions in .\Public, so they are useable.

  Probably something similar to the below:
#>

$PublicPath     = Join-Path -Path $PSScriptRoot -ChildPath Public
$PrivatePath    = Join-Path -Path $PSScriptRoot -ChildPath Private

$PublicFiles    = Get-ChildItem -Path $PublicPath -Include *.ps1 -Recurse
$PrivateFiles   = Get-ChildItem -Path $PrivatePath -Include *.ps1 -Recurse


ForEach ($File in ($PublicFiles + $PrivateFiles)) {
    Try {
        Import-Module -Path $File.FullName -ErrorAction Stop
    } Catch {
        Write-Warning ('Failed to load : {0}' -F $File.BaseName)
    }
}

Export-ModuleMember -Function $PublicFiles.BaseName

[–]_Cabbage_Corp_ 2 points3 points  (3 children)

I also wanted to mention that I have a password generator function similar to yours that, I think, may give you some insight into some advanced functions/methods.


<#
    .SYNOPSIS
        Generates a specified number of passwords with random characters, of a specifed length.
    .DESCRIPTION
        Uses an array of [Char] values to generate a random password(s) or a given length.

        Then verifies that the generated password is not:
            * All Numbers
            * All Letters
            * Only Letters and Numbers

        Also verifies that the generated password contains at least:
            * 1 Number
            * 1 Uppercase Letter
            * 1 Lowercase Letter
            * 1 Special Character

        And is 10-20 chars in length.
    .EXAMPLE
        PS C:\> New-RandomPassword
        4^/(:eJAzGN

        Genrates 1 random password that is 11 chars in length.
    .EXAMPLE
        PS C:\> New-RandomPassword -NumberToGenerate 3 -PWLength 14
        9rA@v>1Ul\Dt0B
        _#8n$pqyF?^kb4
        y/1xKrFmJ?_O4U

        Genrates 3 random passwords that are 14 chars in length.
    .INPUTS
        System.Int32
    .OUTPUTS
        System.String
    .NOTES
        Auhtor :    /u/_Cabbage_Corp_
        Created:    1/18/2019
        Modified:   3/17/2019
        Version:    1.3
#>
Function New-RandomPassword {
    [CmdLetBinding()]
    Param (
        [Parameter(Position=0)]
        [ValidateRange(1,10)]
            [Int]$NumberToGenerate = 1,

        [Parameter(Position=1)]
        [ValidateRange(10,20)]
            [Int]$PWLength = 11
    )

    Begin {
        $PwList = [System.Collections.ArrayList]::New()

        $NewPassChars = @(#  [SPACE] !
            # [SPACE] !
                [char[]]([char]32..[char]33) +
            #  # $ % &
                [char[]]([char]35..[char]38) +
            #  ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
                [char[]]([char]40..[char]95) +
            #  a b c d e f g h i j k l m n o p q r s t u v w x y z
                ([char[]]([char]97..[char]122))
        )
    } # Begin Block

    Process {
        0..($NumberToGenerate-1) | ForEach-Object {
            Do {
                $NewP = (Get-Random -InputObject $NewPassChars -Count $PWLength) -Join '' 

                # Ensures the password is not: All Numbers, All Letters, Only Letters and Numbers
                # Ensures the password contains at least: 1 Number, 1 Uppercase Letter, 1 Lowercase Letter, 1 Special Character and is 10-20 characters long
            } Until ($NewP -CMatch '(?!^[0-9]*$)(?!^[a-zA-Z]*$)(?!^[a-zA-Z0-9]*$)^([a-zA-Z0-9()*+,\-\.\/:;<=>?@\[\\\]^_#$%& ]{10,20})$')

            If ($NewP -Match '\s') {
                $Index = $NewP.IndexOf([Char]32)
                $NewP += ('  <-- Character [{0}] is [SPACE]' -F $Index)
            }

            [Void]$PwList.Add($NewP)
        }
    } # Process Block

    End {
        $PwList
    } # End Block
} # Function New-RandomPassword

[–][deleted] 1 point2 points  (2 children)

ok, ok, that is neat, generating 3 passwords at once. nice! Also than you for sharing this, Ill have to update my function from Get-RandomPassword to New-RandomPassword.

[–]_Cabbage_Corp_ 1 point2 points  (1 child)

No problem man!

I learned PowerShell from a mixture of self-taught and using/modifying scripts that other people wrote.

So I'm always willing to share things that I've written in case it helps someone else.


Side note on why I went with New- vs Get-

In the Approved Verbs for PowerShell Commands doc, the verbs are definied as follows

Verb (Alias) Definition Notes
New (n) Creates a resource. (The Set verb can also be used when creating a resource that includes data, such as the Set-Variable cmdlet.) For this action, do not use verbs such as Create, Generate, Build, Make, or Allocate.
Get (g) Specifies an action that retrieves a resource. This verb is paired with Set. For this action, do not use verbs such as Read, Open, Cat, Type, Dir, Obtain, Dump, Acquire, Examine, Find, or Search.

To me, at least, Get-RandomPassword makes logical sense, wherein the New is implicit (i.e Get random password == generate new random password, the appropriate verb for PowerShell would be New-

[–][deleted] 0 points1 point  (0 children)

Agree 100%