Got on a discussion this week with someone how to use PowerShell to update an MDT CustomSettings.ini file over the network. Well a *lot* of CS.ini files.. 🙂
My manager is the Global Ops Manager and now he is asking me to find a way to run [update of customsettings.ini] on about 50 servers worldwide so the other MDT admins don’t have to log onto each server just to add one line.
The example given was to update the AdminPassword in CS.ini. I hope this company is following best practices, and disabling the local Administrator account and/or changing the Password once joined to the domain or connected to SCCM.
Anywho, INI files are a tad bit difficult to modify in Powershell because there are no native PowerShell or .NET functions to perform the action. So instead we need to do some ugly Pinvoke calls to the appropriate Win32 API.
-k
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Update CustomSettings.ini file. | |
.DESCRIPTION | |
Updates one or more CUstomSettings.ini files with a common value. | |
Calling powershell.exe instance must have read/write privelages to the share. | |
.PARAMETER DeployShares | |
The full path to the share. Can be input from the pipeline | |
Example: | |
c:\DeploymentShare | |
\\localhost\DeploymentShare$ | |
.PARAMETER Section | |
The section name to update. | |
.PARAMETER Name | |
THe name to update | |
.PARAMETER Value | |
The value to write | |
.EXAMPLE | |
C:\PS> .\Update-INIFiles -DeployShares c:\DeploymentShare -Section Default -Name AdminPassword -value 'P@ssw0rd' | |
set a new password in an MDT deployment share | |
.EXAMPLE | |
C:\PS> "\\localhost\DeploymentShare$" | .\Update-INIFiles -Section Default -Name AdminPassword -value 'P@ssw0rd' | |
set a new password in an MDT deployment share, get the file from the pipeline. | |
C:\PS> type .\MyMDTServerList.txt | .\Update-INIFiles -Section Default -Name AdminPassword -value 'P@ssw0rd' | |
set a new password in an MDT deployment share, get the list of files from a list of servers passed in through the cmdline. | |
.EXAMPLE | |
C:\PS> [Reflection.Assembly]::LoadWithPartialName("System.Web") | out-null | |
C:\PS> $NewPassword = [System.Web.Security.Membership]::GeneratePassword(10,2) | |
C:\PS> "The new password will be: $NewPassword" | |
The new password will be: F{nK:*[L}H | |
C:\PS> type .\MyMDTServerList.txt | .\Update-INIFiles -Section Default -Name AdminPassword -value $NewPassword | |
Generate a new random password with powershell, then update all Cs.ini files from a list of servers passed in through the command line. | |
.LINK | |
https://foxdeploy.com/2014/09/04/adding-whatif-support-to-your-scripts-the-right-way-and-how-you-shouldnt-do-it/ | |
#> | |
[cmdletbinding(SupportsShouldProcess=$true)] | |
param( | |
[parameter(Mandatory=$true, ValueFromPipeline=$true)] | |
$DeployShares, | |
[parameter(Mandatory=$true)] | |
[string] $Section, | |
[parameter(Mandatory=$true)] | |
[string] $Name, | |
[parameter(Mandatory=$true)] | |
[string] $Value | |
) | |
begin { | |
## The signature of the Windows API that retrieves INI settings | |
$signature = @' | |
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] | |
public static extern bool WritePrivateProfileString( | |
string lpAppName, | |
string lpKeyName, | |
string lpString, | |
string lpFileName); | |
[DllImport("Kernel32.dll")] | |
public static extern uint GetLastError(); | |
'@ | |
## Create a new type that lets us access the Windows API function | |
$type = Add-Type –MemberDefinition $signature –Name API –Namespace Win32 –PassThru | |
} | |
process { | |
foreach ( $DPShare in $DeployShares ) { | |
if ($pscmdlet.ShouldProcess("$DPShare", "CustomSettings.ini write")){ | |
$result = [Win32.API]::WritePrivateProfileString($Section, $Name, $Value, "$DPShare\control\customsettings.ini") | |
if ( -not $result ) { | |
$err = [Win32.API]::GetLastError() | |
throw ( New-Object ComponentModel.Win32Exception ($err -as [int]) ) | |
} | |
} | |
} | |
} |