Monday, June 22, 2015

Quick and Dirty Powershell Modules

So you have built some awesome scripts and turned them into advanced functions. Whats next? It is time to put them into a module. It can be a lot easier than you realize. Lets go step by step and build our first module to hold all of your advanced functions.

# Start in our profile powershell folder
CD ~\Documents\WindowsPowershell

# Create a folder for our module and functions
MD Modules\Other\Functions

# Create a module manifest
$Manifest = @{
    Path        = ".\Modules\Other\Other.psd1"
    RootModule  = ".\Other.psm1" # Module loader
    Author      = "Kevin Marquette"
    Description = "Odds and ends"   
}
New-ModuleManifest @Manifest -Verbose

# Create our module loader (that loads our advanced functions)
$ModuleLoader = @'
  $moduleRoot = Split-Path -Path $MyInvocation.MyCommand.Path

  Write-Verbose "Importing Functions"
  # Import everything in the functions folder
  "$moduleRoot\Functions\*.ps1" |
      Resolve-Path |
      Where-Object { -not ($_.ProviderPath.Contains(".Tests.")) } |
      ForEach-Object { . $_.ProviderPath ; Write-Verbose $_.ProviderPath}
'@

Set-Content -Value $ModuleLoader -Path .\Modules\Other\Other.psm1

# Now create a single file for each advanced function and place it in the functions folder
# Sample function
$TestFunction = @'
   function Test-Other
   {
        [cmdletbinding()]
        param()
        Write-Output "Hello World!!"
   }
'@
Set-Content -Value $TestFunction -Path .\Modules\Other\functions\Test-Other.ps1

# Load it and test it out
Import-Module Other -Verbose -Force
Test-Other


You could easily place all your functions into the Other.psm1 file and everything would still work. But this creates a framework that makes your functions easy to manage. That functions folder can now be a dumping ground for all your advanced functions. If you out grow this module, you can create a new one and just move the functions over.

The module loader is what enables that. Later we will add pester tests and this already accounts for this. This is a pattern that I seen used by other Powershell MVPs. It has greatly simplified my function management.

Friday, June 05, 2015

JoinDomainOrWorkgroup 1323 error unable to update the password

I am using the Win32_ComputerSystem WMI object to join machines to a domain with JoinDomainOrWorkgroup. Then I ran into an issue on XP/2003 where I would get this 1323 return code and it would fail. This looked to work find for server 2012 so I started digging.

From the MSDN documentation, error 1323 means  "error unable to update the password".  My first set of searches implied that the time was out of sync between the servers. Manual join worked fine and after syncing the time to the DC before the join, I had the same issue.

$wmi.JoinDomainOrWorkgroup("Domain","Password","UserName",$null,3

Then I found a comment here that said add the domain to the username.

$wmi.JoinDomainOrWorkgroup("Domain","Password","Domain\UserName",$null,3

And then it worked.