Possible to update PowerShell profile with script?

Is it possible to have a script that could detect if a PowerShell profile is created and if not create it and then update the profile with a couple of functions? I’m asking as I’ve written a lot of PowerShell scripts recently and am going to share them with some co-workers. However some of them require additional functions to work, and I thought it’d be nice for the users to just run a script that checks for a profile and then updates the profile with the functions. I want it to be if the profile already existed as well and had functions on it that the script would just add to the profile, not overwrite and erase anything. Possible or am I just crazy?

Very possible. However, quite difficult to do in a robust manner. You’d need to parse the AST to determine if a given function matching your specifications is in the script.

I would start by:

  1. Define your functions in this script.
  2. Pull these functions into an array using Get-Item Function:\Function-Name
  3. Use Test-Path to check if a profile exists. If not, just copy all your functions to the script.
  4. If the profile already exists, use Get-Command to retrieve the AST: (Get-Command $Profile).Scriptblock.Ast
  5. With this, you can filter the AST for defined functions in the profile script. Match these up against your functions, and do a simple -eq comparison to determine if the contents of the functions match, if you want.
  6. Loop back to 3 and use the same code to add missing functions into the file. Just append to the file, don't try to be fancy and insert things into the middle, it'll just be messy and unreliable.

You want to have shared functions in a PowerShell script module that’s accessible on a common network share. The reason is you don’t want to have numerous copies of the functions in every user’s PS profile. As you make one change after the other in your functions, updating the numerous copies in the user’s different profiles and many different computers becomes untenable and is an unnecessary complication.

If the client computers have PS5, I recommend using a public or private (NuGet) Repo not unlike the PowerShell gallery. It has the added benefit of versioning your scripts. If not, you can use a network share and scripted process to copy (install) your module in machines that have PS2 for example…

A script module can be as little as a .psm1 and a .psd1 files.

To create PS profile for users, you can have a logon script like:

# Create folder structure if not exist
New-Item -Path (Split-Path $profile) -ItemType Directory -EA 0
if (-not (Test-Path (Split-Path $profile))) { throw "Unable to create folder ($(Split-Path $profile))" }

# over-write profile ps1
@'
New-PSDrive -Name z -PSProvider FileSystem -Root \\server\share-Persist -EA 0
set-location z:\scripts
Import-Module AzureRM,AZSBTools -DisableNameChecking
'@ | Out-File $profile -Force

# View it
# notepad $profile

If you have a trusted network location you could have a load script in the powershell profile that just imports any modules from the trusted location, or for offline have the load grab any modules from the network location, compute a hash to determine a change and then have it copy the modules locally into one of the paths in $env:PSModulePath (preferably the user module path). Then just add your new code to the network “repository”. That way they always get the new code.

Hey Eric,

[edit] had this thread open when no one had replied. by the time i replied there were other replies [/]

Interesting idea. When would the “profile checker” script run?

Ok thanks for all the tips so far. I’m still new to PowerShell and learning more and more each day. I’m not quite sure what I’m doing here, so here’s what I have so far. I’m sure I’m missing a lot, but any help is appreciated.

function Open-VMRC {

<#

.Synopsis

Function to replicate Open-VMConsoleWindow but use the VMware Remote Console Application

.Description

Connect to the virtual machine using the currently connected server object.

.Example

Get-VM "MyVM" | Open-VMRC

.Parameter VirtualMachine

Virtual Machine object

#>

#[CmdletBinding()]

param (

[Parameter(Mandatory=$true,ValueFromPipeline=$True)][VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$vm

)

$ServiceInstance = Get-View -Id ServiceInstance

$SessionManager = Get-View -Id $ServiceInstance.Content.SessionManager

$vmrcURI = "vmrc://clone:" + ($SessionManager.AcquireCloneTicket()) + "@" + $global:DefaultVIServer.Name + "/?moid=" + $vm.ExtensionData.MoRef.Value

Start-Process -FilePath $vmrcURI

}

Get-Item Function:\Open-VMRC

if (!(Test-Path -Path $profile)){New-Item -Type File -Path $profile -Force}