function Load-Form {
$Form.Controls.Add($TBComputerName)
$Form.Controls.Add($GBComputerName)
$Form.Controls.Add($ButtonOK)
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
}
function Set-OSDComputerName {
$ErrorProvider.Clear()
if ($TBComputerName.Text.Length -eq 0) {
$ErrorProvider.SetError($GBComputerName, "Please enter a computer name")
}
else {
if ($TBComputerName.Text.Length -gt 15) {
$ErrorProvider.SetError($GBComputerName, "Computer name cannot be more than 15 characters")
}
else {
$OSDComputerName = $TBComputerName.Text.Replace("[","").Replace("]","").Replace(":","").Replace(";","").Replace("|","").Replace("=","").Replace("+","").Replace("*","").Replace("?","").Replace("<","").Replace(">","").Replace("/","").Replace("\","").Replace(",","")
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value("OSDComputerName") = "$($OSDComputerName)"
$Form.Close()
}
}
}
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Global:ErrorProvider = New-Object System.Windows.Forms.ErrorProvider
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(285,140)
$Form.MinimumSize = New-Object System.Drawing.Size(285,140)
$Form.MaximumSize = New-Object System.Drawing.Size(285,140)
$Form.StartPosition = "CenterScreen"
$Form.SizeGripStyle = "Hide"
$Form.Text = "Enter Computer Name"
$Form.ControlBox = $false
$Form.TopMost = $true
$TBComputerName = New-Object System.Windows.Forms.TextBox
$TBComputerName.Location = New-Object System.Drawing.Size(25,30)
$TBComputerName.Size = New-Object System.Drawing.Size(215,50)
$TBComputerName.TabIndex = "1"
$GBComputerName = New-Object System.Windows.Forms.GroupBox
$GBComputerName.Location = New-Object System.Drawing.Size(20,10)
$GBComputerName.Size = New-Object System.Drawing.Size(225,50)
$GBComputerName.Text = "Computer name:"
$ButtonOK = New-Object System.Windows.Forms.Button
$ButtonOK.Location = New-Object System.Drawing.Size(195,70)
$ButtonOK.Size = New-Object System.Drawing.Size(50,20)
$ButtonOK.Text = "OK"
$ButtonOK.TabIndex = "2"
$ButtonOK.Add_Click({Set-OSDComputerName})
Load-Form
Friday, August 24, 2018
Powershell Script to prompt for computer name during OSD
Friday, August 17, 2018
WinPE Version List
WinPE Version List (Updated June 16, 2018)
The table below shows the main versions of WinPE that you will see in the wild, along with their WinPE version, the Windows version name, and the numeric Windows version string that it was built from.
WinPE | Windows | Windows Version | Notes |
1.0 | Windows XP | 5.1.2600.x | First version of WinPE. |
1.1 | Windows XP SP1 | 5.1.2600.x | |
1.2 | Windows Server 2003 | 5.2.3790.x | |
1.5 | Windows XP SP2 | 5.1.2600.x | Windows PE 2004. |
1.6 | Windows Server 2003 SP1 | 5.2.3790.x | Windows PE 2005. |
2.0 | Windows Vista | 6.0.6000.x | |
2.1 | Windows Server 2008 | 6.0.6001.x | |
2.2 | Windows Server 2008 SP2 | 6.0.6002.x | |
3.0 | Windows 7 | 6.1.7600.x | Windows AIK 2.0. |
3.1 | Windows 7 SP1 | 6.1.7601.x | Windows AIK Supplement for Windows 7 SP1. |
4.0 | Windows 8 | 6.2.9200.x | Windows ADK (Windows Kits 8.0). |
5.0 | Windows 8.1 | 6.3.9300.x | Windows ADK (Windows Kits 8.1). |
5.1 | Windows 8.1 Update 1 | 6.3.9600.x | Windows ADK (Windows Kits 8.1 Update). |
10 (1507) | Windows 10 1507 | 10.0.10240.16384 | Windows ADK (Windows Kits 10.0) 1507 |
10 (1511) | Windows 10 1511 | 10.0.10586.0 | Windows ADK (Windows Kits 10.0) 1511 |
10 (1607) | Windows 10 1607 | 10.0.14393.0 | Windows ADK (Windows Kits 10.0) 1607 |
10 (1703) | Windows 10 1703 | 10.0.15063.0 | Windows ADK (Windows Kits 10.0) 1703 |
10 (1709) | Windows 10 1709 | 10.0.16299.15 | Windows ADK (Windows Kits 10.0) 1709 |
10 (1803) | Windows 10 1803 | 10.0.17134.1 | Windows ADK (Windows Kits 10.0) 1803 |
List of Built-In Task OSD Sequence Variables
Built-in Variable Name | Description |
---|---|
_SMSTSAdvertID
|
Stores the current running task sequence advertisement ID. It uses the same format as a Configuration Manager 2007 software distribution advertisement ID. If the task sequence is running from stand-alone media, this variable is undefined.
Example:
ABC20001
|
_SMSTSBootImageID
|
Stores the Configuration Manager 2007 boot image package ID if a boot image package is associated with the current running task sequence. The variable will not be set if no Configuration Manager 2007 boot image package is associated.
Example:
ABC00001
|
_SMSTSClientGUID
|
Stores the value of Configuration Manager 2007 client GUID. This variable is not set if the task sequence is running from stand-alone media.
Example:
0a1a9a4b-fc56-44f6-b7cd-c3f8ee37c04c
|
_SMSTSCurrentActionName
|
Specifies the name of the currently running task sequence step. This variable will be set before the task sequence manager runs each individual step.
Example:
run command line
|
_SMSTSDownloadOnDemand
|
Set to true if the current task sequence is running in download-on-demand mode, which means the task sequence manager downloads content locally only when it must access the content.
|
_SMSTSInWinPE
|
This variable is set to true when the current task sequence step is running in the Windows PE environment, and it is set to false if not. You can test this task sequence variable to determine the current operating system environment.
|
_SMSTSLastActionRetCode
|
Stores the return code returned by the last action that was run.
Example:
0
|
_SMSTSLastActionSucceeded
|
The variable is set to true if the last action succeeded and to false if the last action failed. If the last action was skipped because the step was disabled or the associated condition evaluated to false, this variable is not reset, which means it still holds the value for the previous action.
|
_SMSTSLaunchMode
|
Specifies the task sequence launch method. The task sequence can have the following values:
|
_SMSTSLogPath
|
Stores the full path of the log directory. This can be used to determine where actions should be logged. This value is not set when no hard drive is available.
|
_SMSTSMachineName
|
Stores and specifies the computer name. Stores the name of the computer that the task sequence will use to log all status messages. To change the computer name in the new operating system, use the OSDComputerName variable.
Example:
ABC
|
_SMSTSMediaType
|
Specifies the type of media that will be used to initiate the installation. Examples of types of media are Boot Media, Full Media, PXE, and Prestaged Media.
|
_SMSTSMP
|
Stores the name or IP address of a Configuration Manager 2007 management point.
|
_SMSTSMPPort
|
Stores the management point port number of a Configuration Manager 2007 management point.
Example:
80
|
_SMSTSOrgName
|
Stores the branding title name, which will be displayed in a task sequence progress user interface dialog box.
Example:
XYZ Organization
|
_SMSTSPackageID
|
Stores the current running task sequence ID. This ID uses the same format as a Configuration Manager 2007 software package ID.
Example:
HJT00001
|
_SMSTSPackageName
|
Stores the current running task sequence name specified by the Configuration Manager 2007 administrator when the task sequence is created.
Example:
Deploy xpsp2 task sequence
|
_SMSTSRunFromDP
|
Set to true if the current task sequence is running in run-from-distribution-point mode, which means the task sequence manager obtains required packages from distribution point shares.
|
_SMSTSSiteCode
|
Stores the site code of the Configuration Manager 2007 site.
Example:
ABC
|
_SMSTSType
|
Specifies the type of the current running task sequence. It can have the following values:
1 - indicates a generic task sequence.
2 - indicates an operating system deployment task sequence.
|
_SMSTSTimezone
|
The _SMSTSTimezone variable stores the time zone information in the following format (without spaces):
Bias, StandardBias, DaylightBias, StandardDate.wYear, wMonth, wDayOfWeek, wDay, wHour, wMinute, wSecond, wMilliseconds, DaylightDate.wYear, wMonth, wDayOfWeek, wDay, wHour, wMinute, wSecond, wMilliseconds, StandardName, DaylightName
Example
For the Eastern Time U.S. and Canada, the value would be 300,0,-60,0,11,0,1,2,0,0,0,0,3,0,2,2,0,0,0,Eastern Standard Time,Eastern Daylight Time
|
_SMSTSUseCRL
|
Specifies whether the task sequence uses the certificate revocation list when it uses a Secure Socket Layer (SSL) certificate to communicate with the management point.
|
_SMSTSUserStarted
|
Specifies whether a task sequence is started by a user. This variable will only be set if the task sequence is started from the Configuration Manager 2007 client. For example, if _SMSTSLaunchMode is set to SMS. The variable can have the following values:
|
_SMSTSUseSSL
|
Specifies whether the task sequence uses SSL to communicate with the Configuration Manager 2007 management point. If your site is running in native mode, the value is set to true.
|
SMSTSErrorDialogTimeout
|
When an error occurs in a task sequence, a dialog box is displayed that is dismissed automatically after a default time-out value. Use this variable to specify a time-out value in seconds other than the default of 15 minutes.
|
SMSTSRebootDelay
|
Specifies how many seconds to wait before the computer restarts. The task sequence manager will display a notification dialog before reboot if this variable is not set to 0.
Examples:
0
30
|
SMSTSRebootMessage
|
Specifies the message to display in the shutdown dialog box when a reboot is requested. If this variable is not set, a default message will appear.
Example:
This computer is being rebooted by the task sequence manager.
|
SMSTSRebootRequested
|
Indicates that a reboot is requested after the current task sequence step is completed. If a reboot is required, just set this variable to true, and the task sequence manager will restart the computer after this task sequence step. The task sequence step must set this task sequence variable if it requires a reboot to complete the task sequence step. After the computer is rebooted, the task sequence will continue to run from the next task sequence step.
|
SMSTSLocalDataDrive
|
Specifies where temporary files are stored on the destination computer while the task sequence is running.
|
SMSTSRetryRequested
|
Requests a retry after the current task sequence step is completed. If this task sequence variable is set, the SMSTSRebootRequested must also be set to true. After the computer is restarted, the task sequence manager will rerun the same task sequence step.
|
Creating Your Own Task Sequence Variables
Operating System Deployment Task Sequence Variables
Tuesday, August 14, 2018
Powershell script to determine OS architecture (32bit or 64bit)
This will return either "32" or "64" depending on the OS architecture.
Write-Host (Get-WmiObject -Class Win32_Processor | Select-Object AddressWidth).AddressWidthNOTE: this is OS architecture, not CPU architecture. That is not relevant on 64bit machines, but if you have 32bit Windows running on a 64bit CPU it will return 32.
Labels:
32bit,
64bit,
Architecture,
OS,
PowerShell,
WMI,
x64,
x86
Tuesday, October 31, 2017
Powershell Script to Email an Alert if a Scheduled Task fails
-------------------------------------------------------------
Monitor-ScheduleTask s.ps1
-------------------------------------------------------------
Monitor-ScheduleTask
-------------------------------------------------------------
<#
.Synopsis
Determines which scheduled tasks (if any) have failed in the last 30 minutes
and sends an email listing those failures.
.DESCRIPTION
Determines which scheduled tasks (if any) have failed in the last 30 minutes
and sends an email listing those failures.
.USAGE
Create a scheduled task that has three triggers.
The triggers are on Task Scheduler log events 101, 103, and 202.
Be sure that the scheduled task is running under an account with
enough credentials to read the log and to run this script, and
is running whether or not that account is logged on.
Obviously, this script should be the action taken on trigger (program is
powershell.exe, this script path\filename as parameter)
Adjust the variables that begin with "$Email" below to be correct for your
environment.
#>
$EmailUsername = "anonymous"
$EmailPassword = ConvertTo-SecureString -String "anonymous" -AsPlainText -Force
$EmailTo = "myemail.address.com","myteamm atesemail.address.com"
$EmailFrom = "$env:COMPUTERNAME@mydomain. com"
$EmailSMTPServer = "MySMTPServer.Domain.com"
$events = get-scheduledtask | where {$_.State -ne "Disabled"} | where {((Get-ScheduledTaskInfo $_).LastTaskResult -ne "0") -and ((Get-ScheduledTaskInfo $_).LastTaskResult -ne "267009") -and((Get-ScheduledTaskInfo $_).LastRunTime -ge ((Get-Date).AddMinutes(-30)) -and ((Get-ScheduledTaskInfo $_).TaskPath -notlike "\Microsoft\*" )) -and $_.TaskName -notlike"User_Feed_Synchronization*"} | Select TaskName
$count = ($events.TaskName).Count
$EmailBody = ""
if ($count -ge 1){
foreach ($event in $events){
$FailedTaskMessage = "A scheduled task on $env:COMPUTERNAME has failed.`n`r`n`rFailed Task:" + $event.TaskName + "`n`r"
$EmailBody = $EmailBody + $FailedTaskMessage
}
}
else{
$EmailBody = "Task Scheduler Engine reported a failed task.`n`r`n`rAutomation is unable to determine which task failed."
}
$EmailCredentials = New-Object System.Management.Automation. PSCredential($EmailUsername,$ EmailPassword)
$EmailSubject = "A scheduled task on $env:COMPUTERNAME has failed"
Write-Output $EmailBody
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -SmtpServer $EmailSMTPServer -Credential $EmailCredentials -Body $EmailBody
Friday, September 22, 2017
Powershell script to create SCCM maintenance window collections based on an external source (CMDB)
As written this will download the external data from a URL but that is easily converted to a simple file copy (or completely removed) if a URL is not how you get your CMDB data. As always, don't just download and run stuff that you find on the internet, check it over for possible malicious code before you do anything with it. Enjoy!
-------------------------------------------------------------
Update-MWCollections.ps1
-------------------------------------------------------------
<#
-------------------------------------------------------------
-------------------------------------------------------------
-------------------------------------------------------------
Update-MWCollections.ps1
-------------------------------------------------------------
<#
.Synopsis Maintains Software Updates Maintenance Window Collections in SCCM based on information from an external source (CMDB) .DESCRIPTION *********************************************************** Look for the "#User Variables" to make any necessry changes The script will not download a copy the CMDB information while in test mode (will use the test file). It will, however, create maintenance windows on any collections that it creates so ensure that you only have test machines in your test file's data. *********************************************************** Downloads data from CMDB website and stores a local copy as a .csv Reads the CMDB data from the .csv into an array of objects Reads SCCM data directly from SCCM into an array of objects Loops through the array of CMDB objects, checking each against the SCCM objects Sets a count of SCCM maintenance windows collections to the number that the CMDB object belong to If the count of SCCM maintenance windows collections is more than 1, it removes the computer from all SCCM maintenance windows and sets the count to 0 If the count of SCCM maintenance windows collections is exactly 1, it checks to ensure that the one maintenance window collection to which the computer belongs is correct if it is not correct it removes the computer from its current collection and sets the count to 0 If the count of SCCM maintenance windows collections is 0, it checks to see if the correct maintenance window collection exists, if not it creates it it adds the computer to the correct maintenance window collection .NOTES Created by Mark Randol - randoltech.blogspot.com #> function Get-OccuranceOfDayOfWeek{ [CmdletBinding(DefaultParameterSetName='OccuranceOfDayOfWeek', SupportsShouldProcess=$true, PositionalBinding=$false)] [OutputType([DateTime])] Param( # Day of the Week [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='OccuranceOfDayOfWeek')] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [ValidateLength(0,15)] [ValidateSet("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")] [Alias("day","dayname","dow")] [String] $DayOfWeek, # Occurance [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='OccuranceOfDayOfWeek')] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [ValidateSet(1,2,3,4)] [Alias("occ")] [Int] $Occurance ) Begin{ } Process{ [Int]$TestDayNum = 0 [Arr]$OccuranceDates = @() do { $TestDayNum = $TestDayNum + 1 $TestDayName = (Get-Date -Day $TestDayNum).DayOfWeek } until ($TestDayName -eq $DayOfWeek) $OccuranceDate = $TestDayNum do{ $OccuranceDates += @($OccuranceDate) $OccuranceDate = $OccuranceDate + 7 } while ($OccuranceDate -lt 32) } End{ [Int]$OutputInt = $Occurance - 1 [DateTime]$MyOutput = (Get-Date -Year (Get-Date).Year -Month (Get-Date).Month -Day $OccuranceDates[$OutputInt]).Date Return $MyOutput } } function Add-SCCMArrayMember{ [CmdletBinding(DefaultParameterSetName='CollectionMembership', SupportsShouldProcess=$true, PositionalBinding=$false)] [OutputType([object])] Param( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0, ParameterSetName='CollectionMembership')] [string]$MaintenanceWindow, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1, ParameterSetName='CollectionMembership')] [string]$CollectionID, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=2, ParameterSetName='CollectionMembership')] [string]$ComputerName, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=3, ParameterSetName='CollectionMembership')] [string]$ResourceID ) Begin{ $CollectionMembership = new-object PSObject } Process{ $properties = @{'MaintenanceWindow'=$MaintenanceWindow; 'CollectionID'=$CollectionID; 'ComputerName'=$ComputerName; 'ResourceID'=$ResourceID} $CollectionMembership = New-Object -Property $properties -TypeName PSObject } End{ return $CollectionMembership } } function Add-CMDBArrayMember{ [CmdletBinding(DefaultParameterSetName='CMDBArrayMember', SupportsShouldProcess=$true, PositionalBinding=$false)] [OutputType([object])] Param( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0, ParameterSetName='CMDBArrayMember')] [string]$MaintenanceWindow, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1, ParameterSetName='CMDBArrayMember')] [string]$ComputerName ) Begin{ $Membership = new-object PSObject } Process{ $properties = @{'MaintenanceWindow'=$MaintenanceWindow; 'ComputerName'=$ComputerName} $Membership = New-Object -Property $properties -TypeName PSObject } End{ return $Membership } } function Create-NewSCCMMWCollection{ [CmdletBinding(DefaultParameterSetName='NewSCCMMWCollection', SupportsShouldProcess=$true, PositionalBinding=$false)] [OutputType([object])] Param( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0, ParameterSetName='NewSCCMMWCollection')] [string]$CollectionName, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1, ParameterSetName='NewSCCMMWCollection')] [string]$TargetFolderID, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=2, ParameterSetName='NewSCCMMWCollection')] [string]$Schedule, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=3, ParameterSetName='NewSCCMMWCollection')] [string]$LimitingCollectionID, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=4, ParameterSetName='NewSCCMMWCollection')] [int]$MaintDuration, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=5, ParameterSetName='NewSCCMMWCollection')] [string]$DeploymentCollectionID, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=5, ParameterSetName='NewSCCMMWCollection')] [string]$SiteCode ) Begin{ } Process{ #Create the collection $ActivityMessage = "Adding new SCCM Maintenance Window collection " + $CollectionName $StatusMessage = "Creating collection named " + $CollectionName Write-Output $StatusMessage $newColl = New-CMDeviceCollection -Name $CollectionName -limitingcollectionid $LimitingCollectionID -RefreshType Continuous #Create the collection $NewCollectionID = $($newColl).collectionid $NewCollectionName = $($newColl).Name #Move the to the correct folder $CurrentFolderID = 0 $ObjectTypeID = 5000 $StatusMessage = "Moving " + $NewCollectionName + " to Maintenance Windows Folder" Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage $Namespace = "Root\SMS\Site_" + $SiteCode Invoke-WmiMethod -Namespace $Namespace -Class SMS_objectContainerItem -Name MoveMembers -ArgumentList $CurrentFolderID,$NewCollectionID,$ObjectTypeID,$TargetFolderID #Put a maintenance window on the collection #Turn the schedule variable into a comma delimited array $CommaDelimitedSchedule = $Schedule.Replace("st-",",").Replace("nd-",",").Replace("rd-",",").Replace("th-",",").Replace("st&","").Replace("nd&","").Replace("rd&","").Replace("th&","").Replace("@",",").Replace("-",",") #Initialize variables from the array contents $WeekOrderStr = $CommaDelimitedSchedule.Split(',')[0] $DayOfWeek = $CommaDelimitedSchedule.Split(',')[1] $StartTimeStr = $CommaDelimitedSchedule.Split(',')[2] $StartHour = Get-Date $schedule.split('@')[1] [Int]$WeekOrder = 0 $EndTime = $StartTime.AddHours($maintDuration) if ($WeekOrderStr -eq "every"){ $WeekOrder = 0 #Set up for every week $MWWindowName = "$prefix $WeekOrderStr-$DayOfWeek@$StartTimeStr" $StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage IF ($DayOfWeek -eq "Day" -or $DayOfWeek -eq "day"){ #schedule is every day $StartTime = ((get-date -Day 1).Date).AddHours($StartHour.Hour) $EndTime = $StartTime.AddHours($maintDuration) $StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage $schedtoken = New-CMSchedule -Start $StartTime -End $EndTime -RecurInterval Days -RecurCount 1 New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken } #schedule is every day else{ #schedule is one day of week $StartTime = (Get-OccuranceOfDayOfWeek -DayOfWeek $DayOfWeek -Occurance 1).AddHours($StartHour.Hour) $EndTime = $StartTime.AddHours($maintDuration) $StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage $schedtoken = New-CMSchedule -DayOfWeek $DayOfWeek -Start $StartTime -End $EndTime -RecurCount 1 New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken } #schedule is one day of week } else { $WeekOrder = $WeekOrderStr.Substring(0,1) #Set up for the week in the 1st character (monthly and fortnightly) $StartTime = (Get-OccuranceOfDayOfWeek -DayOfWeek $DayOfWeek -Occurance $WeekOrder).AddHours($StartHour.Hour) $EndTime = $StartTime.AddHours($maintDuration) $MWWindowName = $prefix + (($WeekOrderStr.Substring(0,1)).replace("1","1st").replace("2","2nd")).replace("3","3rd").replace("4","4th") + "-$DayOfWeek@$StartTimeStr" $StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage $schedtoken = New-CMSchedule -WeekOrder $WeekOrder -DayOfWeek $DayOfWeek -Start $StartTime -End $EndTime New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken if ($WeekOrderStr.Length -eq 2){ $WeekOrder = $WeekOrderStr.Substring(1,1) #Set up for the week in the 2nd character (fortnightly) $StartTime = (Get-OccuranceOfDayOfWeek -DayOfWeek $DayOfWeek -Occurance $WeekOrder).AddHours($StartHour.Hour) $EndTime = $StartTime.AddHours($maintDuration) $MWWindowName = $prefix + (($WeekOrderStr.Substring(1,1)).replace("1","1st").replace("2","2nd")).replace("3","3rd").replace("4","4th") + "-$DayOfWeek@$StartTimeStr" $StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage $schedtoken = New-CMSchedule -WeekOrder $WeekOrder -DayOfWeek $DayOfWeek -Start $StartTime -End $EndTime New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken } } #Include the collection in the deployment collection membership $StatusMessage = "Adding " + $NewCollectionName + " as an include to the deployment collection" Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage Add-CMDeviceCollectionIncludeMembershipRule -CollectionId $DeploymentCollectionID -IncludeCollectionId $NewCollectionID } End{ } } function Remove-AllCurrentMWMembership{ [CmdletBinding(DefaultParameterSetName='AllCurrentMWMembership', SupportsShouldProcess=$true, PositionalBinding=$false)] [OutputType([int])] Param( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0, ParameterSetName='AllCurrentMWMembership')] [string]$ComputerName, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1, ParameterSetName='AllCurrentMWMembership')] [string]$SiteServerName, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=2, ParameterSetName='AllCurrentMWMembership')] [string]$SiteCode, [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=3, ParameterSetName='AllCurrentMWMembership')] [string]$Prefix ) Begin{ $NameSpace = "root\SMS\site_" + $SiteCode $QueryText = "SELECT SMS_Collection.* FROM SMS_FullCollectionMembership, SMS_Collection where name = '" + $ComputerName + "' and SMS_FullCollectionMembership.CollectionID = SMS_Collection.CollectionID and SMS_FullCollectionMembership.CollectionName like '" + $Prefix + "%'" $Collections = Get-WmiObject -Query $QueryText -Namespace $NameSpace
} Process{ foreach ($Collection in $Collections){ $CollectionName = $Collection.name $ActivityMessage = “Removing computer from a collection.” $StatusMessage = “Removing $ComputerName from $CollectionName” Write-Output $StatusMessage Write-Progress -Activity $ActivityMessage -Status $StatusMessage Remove-CMCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceName $ComputerName -Force } } End{ } } Import-Module -Name "$(split-path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1" #Load the Configuration Manager Module #Initialize program variables $Date = Get-Date -Format yyyy-MM-dd_HHmm $StartTime = Get-Date $SCCMMWTable = @([pscustomobject]) $CMDBMWTable = @([pscustomobject]) [Int]$OuterLoopCounter = -1 [Int]$MainCounter = -1 [Int]$InnerLoopCounter = -1 #User Variables $TestMode = $true #Set to $false to run production - provides quick and easy switch to/from test mode. $SiteCode = "SIT" $SiteServer = "siteserver.yourdomain.org" $WorkingFolder = "D:\Folder\Sub-Folder" #What is our main folder to work with. This just keeps things clean and stops stuff from ending up in places like C:\ $LogFolder = $WorkingFolder + "\Logs" #Where to put our logs $CMDBDownloadURL = "https://sum.dum.url" $ProxyServerURL = "http://proxyserver.yourdomain.org:8015" $LogFile = $LogFolder + "\Update-SUPMWCollections." + $Date + ".log" #Where to put the log file and what to name it. $LocalCMDBpathProd = $WorkingFolder + "\CMDBData.$Date.csv" #production - we download to this file and then work with it locally $LocalCMDBpathTest = $WorkingFolder + "\CMDBData.Test.csv" #test - for testing use this instead of the downloaded file to speed things up $CMDBExportPath = $LogFolder + "\CMDBMWs." + $Date + ".csv" #Where to put the CMDB reference list. This is so we can check the scripts work later. $PreChangeExportPath = $LogFolder + "\Pre-UpdateMWs." + $Date + ".csv" #Where to put the MW reference list before changes have been made. This is so we can check the scripts work later. $PostChangeExportPath = $LogFolder + "\Post-UpdateMWs." + $Date + ".csv" #Where to put the MW reference list after changes have been made This is so we can check the scripts work later. $DeploymentCollectionIDProd = "SIT12345" #Production - ID of the collection to which the software updates are actually deployed. Maintenance window collections are "include" collections on this collection. $DeploymentCollectionIDTest = "SIT23456" #Testing - ID of the collection to which the software updates are actually deployed. Maintenance window collections are "include" collections on this collection. $PrefixTest = "Software Updates Maintenance Window (TEST) - " #Test - Prefix for new software update collections when created $PrefixProd = "Software Updates Maintenance Window (PROD) - " #Prefix for new software update collections when created $MWFolderID = 12345678 #The ID of the folder in SCCM where you would like these collections to reside, otherwise they will all end up in the root folder of your console and make it all ugly $LimitingCollectionID = "SIT34567" #Limiting collection for new software update collections when created - usually all systems but could be something more limiting like all SCCM clients $MaintDuration = 2 #How long do you want your software updates maintenance windows to be (in hours) $location = $SiteCode + ":\" set-location $SiteCode #Change to local instance of ConfigMgr Start-Transcript -path ${LogFile} if ($TestMode = $false){ $LocalCMDBpath = $LocalCMDBpathProd $DeploymentCollectionID = $DeploymentCollectionIDProd $Prefix = $PrefixProd #Download the CMDB data file to local location $web = New-Object System.Net.WebClient $proxy = new-object System.Net.WebProxy $proxy.Address = $ProxyServerURL $proxy.useDefaultCredentials = $true #once we get access for the service account, this line can go away $web.Credentials = Get-Credential $web.proxy = $proxy $web.DownloadFile($CMDBDownloadURL,$LocalCMDBpath) } else { $LocalCMDBpath = $LocalCMDBpathTest $DeploymentCollectionID = $DeploymentCollectionIDTest $Prefix = $PrefixTest } #Import CMDB MW Data into an array of objects $ActivityMessage = “Importing CMDB Data” $StatusMessage = "" Write-Progress -Activity $ActivityMessage Write-Output "Importing CMDB Data" $CMDBRawFile = Import-Csv -LiteralPath $LocalCMDBpath $ActivityMessage = "Getting CMDB maintenance window information" $StatusMessage = "Getting CMDB maintenance window information" Write-Output $StatusMessage Write-Progress -Activity $ActivityMessage -Status $StatusMessage $LoopCounter = -1 foreach ($CMDBComputer in $CMDBRawFile){ $LoopCounter++ if ($CMDBComputer.sch_name -ne $null -and $CMDBComputer.sch_name -ne "" -and $CMDBComputer.win_host_name -ne $null -and $CMDBComputer.win_host_name -ne ""){ $CMDBComputerName = ($CMDBComputer.win_host_name).ToUpper() $StatusMessage = "Importing information for computer $CMDBComputerName" $progress = (($LoopCounter / ($CMDBRawFile | Measure-Object).Count) * 100) Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress $CMDBMWTable += Add-CMDBArrayMember -MaintenanceWindow $CMDBComputer.sch_name -ComputerName $CMDBComputerName } } $ActivityMessage = “Completed reading in the CMDB information” $StatusMessage = "Completed reading in the CMDB information - writing the CMDB file." Write-Output $StatusMessage Write-Progress -Activity $ActivityMessage -Status $StatusMessage $CMDBMWTable | Sort-Object -Property computername | Export-Csv -Path $CMDBExportPath -NoClobber -Encoding Default -NoTypeInformation #Import SCCM data into an array of objects $ActivityMessage = “Getting SCCM collection information” $StatusMessage = "Getting SCCM collection membership data" Write-Output $StatusMessage Write-Progress -Activity $ActivityMessage -Status $StatusMessage $IncludeRulesOfDeploymentCollection = Get-CMCollectionIncludeMembershipRule -CollectionId $DeploymentCollectionID $OuterLoopCounter = -1 foreach ($IncludeRule in $IncludeRulesOfDeploymentCollection){ $OuterLoopCounter++ $SCCMCollectionID = $IncludeRule.IncludeCollectionID $SCCMCollectionName = (Get-CMDeviceCollection -Id $SCCMCollectionID).Name $SCCMMaintenanceWindow = $SCCMCollectionName.Replace($Prefix,"") $StatusMessage = "Importing membership information for collection $SCCMCollectionName which is an 'include' rule member of " + (Get-CMDeviceCollection -Id $DeploymentCollectionID).Name $progress = (($OuterLoopCounter / $IncludeRulesOfDeploymentCollection.Count) * 100) Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress $SCCMIncludedCollectionMembers = Get-CMCollectionMember -CollectionId $SCCMCollectionID $InnerLoopCounter = -1 foreach ($member in $SCCMIncludedCollectionMembers){ $InnerLoopCounter++ $MainCounter++ $SCCMMWTable += Add-SCCMArrayMember -MaintenanceWindow $SCCMMaintenanceWindow -CollectionID $SCCMCollectionID -ComputerName $member.Name -ResourceID $member.ResourceID } } $ActivityMessage = “Completed reading in the list of 'include' Collections from the Deployment Collection” $StatusMessage = "Done getting SCCM collection membership information - writing the Pre-Change file." Write-Output $StatusMessage Write-Progress -Activity $ActivityMessage -Status $StatusMessage $SCCMMWTable | Sort-Object -Property ComputerName | Export-Csv -Path $PreChangeExportPath -NoClobber -Encoding Default -NoTypeInformation #Compare the two arrays of objects $ActivityMessage = “Comparing the SCCM data to the CMDB data” $StatusMessage = "Comparing the SCCM data to the CMDB data and making any necessary adjustments to SCCM" Write-Output $StatusMessage Write-Progress -Activity $ActivityMessage -Status $StatusMessage $LoopCounter = -1 #Main comparison loop. This is what will take the longest amount of time in the run cycle. foreach ($CMDBMWComputer in $CMDBMWTable){ #Check each computer in the CMDB $LoopCounter++ $progress = (($LoopCounter / $CMDBMWTable.Count) * 100) $CountOfSCCMMWs = 0 #Only continue if there is actually a computername in CMDB (yes, it happens) if ($CMDBMWComputer.ComputerName -ne $null -and $CMDBMWComputer.ComputerName -ne ""){ $CountOfSCCMMWs = (($SCCMMWTable | ? { $_.computername -eq $CMDBMWComputer.ComputerName }) | Measure-Object).Count $CheckSCCMMW = ($SCCMMWTable | ? { $_.computername -eq $CMDBMWComputer.ComputerName }) #Only continue if there is a maintenance window in CMDB (yeah, that happens too) if($CMDBMWComputer.MaintenanceWindow -ne $null -and $CMDBMWComputer.MaintenanceWindow -ne ""){ #Only continue if the computer is also in SCCM $SCCMComputerObject = (Get-CMDevice -Name $CMDBMWComputer.ComputerName) if ($SCCMComputerObject){ $StatusMessage = "Checking maintenance windows for " + $CMDBMWComputer.ComputerName Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress #If the computer is in more than one maintenance window collection then remove it from all of them if ($CountOfSCCMMWs -gt 1){ $StatusMessage = $CMDBMWComputer.ComputerName + "`tis in multiple maintenance window collections." Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage Remove-AllCurrentMWMembership -ComputerName $CMDBMWComputer.ComputerName -SiteServerName $SiteServer -SiteCode $SiteCode -Prefix $Prefix $CountOfSCCMMWs = 0 #Set the count to zero since the computer is now a member of no maintenance window collections } #End - If the computer is in more than one maintenance window collection then remove it from all of them and set the count to 0 #If the computer is in only one maintenance window collection we need to check that it is the correct one if ($CountOfSCCMMWs -eq 1){ #If the computer is not in the correct maintenance window collection then remove it from the one that it is in and set the count to 0 if ($CMDBMWComputer.MaintenanceWindow -ne ($CheckSCCMMW.MaintenanceWindow).Replace($Prefix,"")){ $StatusMessage = $CMDBMWComputer.ComputerName + "`tis in the wrong maintenance window collection.`tSCCM collection = " + $CheckSCCMMW.MaintenanceWindow + "`tCMDB Maintenance Window = " + $CMDBMWComputer.MaintenanceWindow Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage Remove-AllCurrentMWMembership -ComputerName $CMDBMWComputer.ComputerName -SiteServerName $SiteServer -SiteCode $SiteCode -Prefix $Prefix $CountOfSCCMMWs = 0 #Set the count to zero since the computer is now a member of no maintenance window collections } #End - If the computer is not in the correct maintenance window collection then remove it from the one that it is in and set the count to 0h else{ #If the computer is in the correct maintenance window collection then huzzah and continue $StatusMessage = $CMDBMWComputer.ComputerName + "`tis in the correct maintenance window collection.`tSCCM collection = " + $CheckSCCMMW.MaintenanceWindow + "`t CMDB Maintenance Window = " + $CMDBMWComputer.MaintenanceWindow Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage } #End - If the computer is in the correct maintenance window collection then huzzah and continue } #End - If the computer is in only one maintenance window collection we need to check that it is the correct one #If the computer is in no maintenance window collection the put it into the correct maintenance window collection if ($CountOfSCCMMWs -eq 0){ $StatusMessage = $CMDBMWComputer.ComputerName + "`tis not in any maintenance window collection." Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage $NewCollectionName = $Prefix + $CMDBMWComputer.MaintenanceWindow $MWExist = (Get-CMCollection -Name $NewCollectionName) if (-not $MWExist){ $StatusMessage = "The correct maintenance window does not exist, it should be named " + $Prefix + $CMDBMWComputer.MaintenanceWindow Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage Create-NewSCCMMWCollection -CollectionName $NewCollectionName -TargetFolderID $MWFolderID -LimitingCollectionID $LimitingCollectionID -Schedule $CMDBMWComputer.MaintenanceWindow -MaintDuration $MaintDuration -DeploymentCollectionID $DeploymentCollectionID -SiteCode $SiteCode } #End - If the correct maintenance window collection doesn't exist then create it #Add the computer to the collection $StatusMessage = "Adding " + $CMDBMWComputer.ComputerName + " to " + $NewCollectionName Write-Progress -Activity $ActivityMessage -Status $StatusMessage Write-Output $StatusMessage Add-CMDeviceCollectionDirectMembershipRule -CollectionId (Get-CMCollection -Name $NewCollectionName).CollectionID -ResourceId (Get-CMDevice -Name $CMDBMWComputer.ComputerName).resourceid } #End - If the computer is in no maintenance window collection the put it into the correct maintenance window collection }#END - only continue if the computer is also in SCCM else{ #Computer is not in SCCM $StatusMessage = $CMDBMWComputer.ComputerName + "`tis not in SCCM." Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage }#END - Computer is not in SCCM }#END - Only continue if there is a maintenance window in CMDB (yeah, that happens too) else{ #There was no maintenance window listed in CMDB $StatusMessage = $CMDBMWComputer.ComputerName + "`thas no maintenance window listed in CMDB." Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress Write-Output $StatusMessage }#END - Only continue if there is a maintenance window in CMDB (yeah, that happens too) } #END - Only continue if there is actually a computername in CMDB (yeah, it happens) }#End - Check each computer in the CMDBStop-Transcript #End Logging
-------------------------------------------------------------
-------------------------------------------------------------
Thursday, May 11, 2017
Powershell script to recycle a list of services
This script will stop a set of services in the order given and then start them again in the reverse order.
<#
.Synopsis
Recycle-Services.ps1 - Stops a list of services and restarts them again
.DESCRIPTION
This script will stop a given list of services, in the order given,
then start the services again in the reverse order.
While stopping the services it will disable them to prevent other automation
from restarting them prematurely. When restarting the services it will set
their startup type to "Automatic".
Script by Mark Randol - randoltech.blogspot.com
.USAGE
Change the line that has
[String[]]$ServiceNames =
to include whatever services you need restarted. You can add as many as you like
just be sure to enclose the service names in quotations and seperate them with commas
Example:
[String[]]$ServiceNames = "Audiosrv","MyService","SUMDUMSERVICE"
#>
function Wait-ServiceState{
[CmdletBinding()]
[OutputType([int])]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[Alias('Service','ServiceNames')][String[]] $Service2WaitFor,
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[String[]] $State
)
Process{
$maxRepeat = 120 #Number of half seconds
do
{
$CurrentStatus = (Get-Service $Service2WaitFor).Status
$maxRepeat--
sleep -Milliseconds 500
} until ($CurrentStatus -eq $State -or $maxRepeat -eq 0)
Return $maxRepeat
}
} #Waits until service is in specified state or a specified amount of time has elapsed, whichever comes first
function Stop-MyService{
[CmdletBinding()]
[OutputType([String])]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[Alias('Service','ServiceNames')][String] $Service2Stop
)
Process{
If (Get-Service $Service2Stop -ErrorAction Stop){
If ((Get-Service $Service2Stop).StartType -ne 'Disabled') {Set-Service -Name $Service2Stop -StartupType Disabled -ErrorAction Stop}
If ((Get-Service $Service2Stop).Status -ne 'Stopped') {Stop-Service -Name $Service2Stop -ErrorAction Continue}
$StoppedService = (Wait-ServiceState -Service2WaitFor $Service2Stop -State Stopped -ErrorAction Stop)
}
If ($StoppedService -ne 0){
$OutputString = "$Service2Stop successfully stopped."
Return $OutputString
}
else{
$OutputString = "Unable to stop $Service2Stop"
Return $OutputString
}
}
} #Sets the service to disabled and stops it.
function Start-MyService{
[CmdletBinding()]
[OutputType([String])]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[Alias('Service','ServiceNames')][String] $Service2Start
)
Process{
If (Get-Service $Service2Start -ErrorAction Stop){
If ((Get-Service $Service2Start).StartType -ne 'Automatic') {Set-Service -Name $Service2Start -StartupType Automatic -ErrorAction Stop}
If ((Get-Service $Service2Start).Status -ne 'Running') {Start-Service $Service2Start -ErrorAction Continue}
$StartedService = (Wait-ServiceState -Service2WaitFor $Service2Start -State Running -ErrorAction Stop)
}
If ($StartedService -ne 0){
$OutputString = "$Service2Start successfully started."
Return $OutputString
}
else{
$OutputString = "Unable to start $Service2Start"
Return $OutputString
}
}
} #Sets the service to automatic and starts it.
[String[]]$ServiceNames = "MyService","SUMDUMSERVICE"
[int]$ServiceNum = 0
[string]$Service = ""
#Stop the services
do{
$Service = $ServiceNames[$ServiceNum] Write-Output ("Stopping $Service")
$Stopped = (Stop-MyService -Service2Stop $Service)
$SuccessString = "$Service successfully stopped."
Write-Output $Stopped
iF ($Stopped -ne $SuccessString){
Return $Stopped
}
$ServiceNum ++
} #Stop the services in the order given
while ($ServiceNum -lt $ServiceNames.Count)
#Start the services
$ServiceNum = $ServiceNames.Count - 1
do{
$Service = $ServiceNames[$ServiceNum]
Write-Output ("Starting $Service")
$Started = (Start-MyService -Service2Start $Service)
$SuccessString = "$Service successfully started."
Write-Output $Started
iF ($Started -ne $SuccessString){
Return $Started
}
$ServiceNum --
} #Start the services in reverse order
while ($ServiceNum -gt -1)
$OutputString = "0"
Return $OutputString
<#
.Synopsis
Recycle-Services.ps1 - Stops a list of services and restarts them again
.DESCRIPTION
This script will stop a given list of services, in the order given,
then start the services again in the reverse order.
While stopping the services it will disable them to prevent other automation
from restarting them prematurely. When restarting the services it will set
their startup type to "Automatic".
Script by Mark Randol - randoltech.blogspot.com
.USAGE
Change the line that has
[String[]]$ServiceNames =
to include whatever services you need restarted. You can add as many as you like
just be sure to enclose the service names in quotations and seperate them with commas
Example:
[String[]]$ServiceNames = "Audiosrv","MyService","SUMDUMSERVICE"
#>
function Wait-ServiceState{
[CmdletBinding()]
[OutputType([int])]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[Alias('Service','ServiceNames')][String[]] $Service2WaitFor,
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[String[]] $State
)
Process{
$maxRepeat = 120 #Number of half seconds
do
{
$CurrentStatus = (Get-Service $Service2WaitFor).Status
$maxRepeat--
sleep -Milliseconds 500
} until ($CurrentStatus -eq $State -or $maxRepeat -eq 0)
Return $maxRepeat
}
} #Waits until service is in specified state or a specified amount of time has elapsed, whichever comes first
function Stop-MyService{
[CmdletBinding()]
[OutputType([String])]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[Alias('Service','ServiceNames')][String] $Service2Stop
)
Process{
If (Get-Service $Service2Stop -ErrorAction Stop){
If ((Get-Service $Service2Stop).StartType -ne 'Disabled') {Set-Service -Name $Service2Stop -StartupType Disabled -ErrorAction Stop}
If ((Get-Service $Service2Stop).Status -ne 'Stopped') {Stop-Service -Name $Service2Stop -ErrorAction Continue}
$StoppedService = (Wait-ServiceState -Service2WaitFor $Service2Stop -State Stopped -ErrorAction Stop)
}
If ($StoppedService -ne 0){
$OutputString = "$Service2Stop successfully stopped."
Return $OutputString
}
else{
$OutputString = "Unable to stop $Service2Stop"
Return $OutputString
}
}
} #Sets the service to disabled and stops it.
function Start-MyService{
[CmdletBinding()]
[OutputType([String])]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
[Alias('Service','ServiceNames')][String] $Service2Start
)
Process{
If (Get-Service $Service2Start -ErrorAction Stop){
If ((Get-Service $Service2Start).StartType -ne 'Automatic') {Set-Service -Name $Service2Start -StartupType Automatic -ErrorAction Stop}
If ((Get-Service $Service2Start).Status -ne 'Running') {Start-Service $Service2Start -ErrorAction Continue}
$StartedService = (Wait-ServiceState -Service2WaitFor $Service2Start -State Running -ErrorAction Stop)
}
If ($StartedService -ne 0){
$OutputString = "$Service2Start successfully started."
Return $OutputString
}
else{
$OutputString = "Unable to start $Service2Start"
Return $OutputString
}
}
} #Sets the service to automatic and starts it.
[String[]]$ServiceNames = "MyService","SUMDUMSERVICE"
[int]$ServiceNum = 0
[string]$Service = ""
#Stop the services
do{
$Service = $ServiceNames[$ServiceNum] Write-Output ("Stopping $Service")
$Stopped = (Stop-MyService -Service2Stop $Service)
$SuccessString = "$Service successfully stopped."
Write-Output $Stopped
iF ($Stopped -ne $SuccessString){
Return $Stopped
}
$ServiceNum ++
} #Stop the services in the order given
while ($ServiceNum -lt $ServiceNames.Count)
#Start the services
$ServiceNum = $ServiceNames.Count - 1
do{
$Service = $ServiceNames[$ServiceNum]
Write-Output ("Starting $Service")
$Started = (Start-MyService -Service2Start $Service)
$SuccessString = "$Service successfully started."
Write-Output $Started
iF ($Started -ne $SuccessString){
Return $Started
}
$ServiceNum --
} #Start the services in reverse order
while ($ServiceNum -gt -1)
$OutputString = "0"
Return $OutputString
Subscribe to:
Posts (Atom)