# encoding: ascii
# api: powershell
# title: Automount new PSDrives
# description: This only works PowerShell v2.0 CTP2, and you’ll need to save it as AutoMount.psm1 in a directory under your documents folder like so (vista example):
# version: 1.0
# type: class
# license: CC0
# function: Enable-AutoMount
# x-poshcode-id: 525
# x-archived: 2009-01-04T02:50:28
#
# userprofile\documents\windowspowershell\packages\automount\automount.psm1
# You can then load it with the command:
# ps> add-module automount
# I have this in my profile. You can temporarily disable automount with the function Disable-AutoMount and reenable it at anytime with Enable-AutoMount. The module also exposes four new events for you to consume yourself. You could, for example, hook your own script to run anytime a device is added and/or removed. This is what I do myself in the module. I hook a WMI event once then forward 1 of 4 possible new events depending on the type of WMI event that was raised.
# NOTE: this particular flavour of WMI query only works in Vista and Windows 2003 it appears. I’m looking into getting it working with 2000/XP also.
#
# AutoMount.psm1 v1.0
# Oisin "x0n" Grehan (MVP)
$query = new-object System.Management.WqlEventQuery
$query.EventClassName = "__InstanceOperationEvent"
# default to every 2 seconds
$query.WithinInterval = new-object System.TimeSpan 0,0,2
# this WMI is only available with Windows 2003 and Vista (not XP it appears).
# this could be rewritten to use different WMI queries to support 2000/NT/XP also.
$query.QueryString = "Select * from Win32_VolumeChangeEvent"
# attach a watcher
$watcher = new-object System.Management.ManagementEventWatcher $query
# here we use -SupportEvent instead of -SourceIdentifier
# this prevents this event from being generally visible
# also note the use of the call operator to invoke a
# function in the scope of the module since this action
# occurs outside of module scope.
Register-ObjectEvent $watcher -EventName "EventArrived" `
-SupportEvent "WMI.VolumeChange" -Action {
& (get-module automount) VolumeChangeCallback @args
}
# New PSEvents:
#
# PowerShell.DeviceConfigurationChanged
# PowerShell.DeviceArrived
# PowerShell.DeviceRemoved
# PowerShell.DeviceDocking
# win32_volumechangeevent event types
$eventTypes = @{
1 = "ConfigurationChanged";
2 = "Arrived";
3 = "Removed";
4 = "Docking";
}
# private module level callback function
function VolumeChangeCallback ($sender, $eventargs) {
trap { write-warning $_ }
$driveName = $eventArgs.NewEvent.DriveName.TrimEnd(":")
$eventType = [int]$eventArgs.NewEvent.EventType # was uint16
$forwardedEvent = "Device$($eventTypes[$eventType])"
# forward a new simpler event specific to device event type
[void]( New-PSEvent "PowerShell.$forwardedEvent" -Sender $driveName `
-EventArguments $eventargs )
}
# hook up our psdrive mount / unmount events
# and start the WMI watcher
function Enable-AutoMount {
Register-PSEvent -SourceIdentifier "PowerShell.DeviceArrived" `
-Action {
new-psdrive -name $args[0] -psprovider `
filesystem -root "$args[0]:";
}
Register-PSEvent -SourceIdentifier "PowerShell.DeviceRemoved" `
-Action {
remove-psdrive -name $args[0] -ea 0; # may not exist
}
$watcher.Start()
}
# tear down our psdrive mount / unmount events
# and stop the WMI watcher
function Disable-AutoMount {
Unregister-PSEvent -SourceIdentifier "PowerShell.DeviceArrived"
Unregister-PSEvent -SourceIdentifier "PowerShell.DeviceRemoved"
$watcher.Stop()
}
# export functions to control automount
Export-ModuleMember Enable-AutoMount, Disable-AutoMount
# start watching and (un)mounting
Enable-AutoMount