(There is also a version to run the SCCM Client Actions remotely on clients. See: Performing all SCCM Client Actions on remote computers)
This is a follow up on my previous article perform all the SCCM Client Actions with vbscript. Now, I have chosen a different approach: a PowerShell form where you can select the actions you want to perform. The interface is also multilingual. It supports English (fall back language), French, German, Dutch and Spanish. If your OS is in one of these languages, then the interface is in the same language. Otherwise, it is English. You can also overrule the language.
Before we start, one of the challenges I had. I used the following WMI command first:
Invoke-WMIMethod -Namespace root\ccm -Class SMS_CLIENT -Name TriggerSchedule {00000000-0000-0000-0000-000000000001}
And I received the following error message:
So that was a no-go.
Therefore, I decided to use the same technique as with vbscript:
$CPApplet = New-Object -Comobject CPApplet.CPAppletMgr
$Actions = $CPApplet.GetClientActions()
ForEach ($Action in $Actions)
{
$Action.PerformAction()
}
No errors, and a working solution. Just 6 lines of code.
But I wanted some additional features:
- A nice GUI
- Select the SCCM actions you want to perform
- Select all the SCCM actions you want to perform
- Lock the user interface
- A log file
- Select or unselect all the SCCM actions
- Silent option, without a GUI
- Multilingual
- Last but not least: an error message if the SCCM client is not working fine.
In version 0.2 two new options have been implemented:
- An option to see the SCCM Client Properties, like client version, management point and site.
- An option to see the SCCM Client Components and its version.
In version 0.4 an issue with the PowerShell ConstrainedLanguage has been solved. When Applocker is in place a PowerShell script might be executed with a limited set of commands. So when the constrainedlanguage mode has been detected, the script falls back to a silent mode.
In version 0.6 some other improvements are implemented. Also, there was a bug that no entries were added to the log file. That has been solved too.
In version 1.0 the list of supported languages has been extended. See this article Translate content of a JSON file with DeepL, Google and Microsoft Cognitive Translation Services for more information.
In version 1.1 the following changes have been made:
- More supported languages
The supported languages have been increased. You can find the supported languages with the parameter-OverviewSupportedLanguages
- Modified -LanguageOverride
In the past, the LanguageOverride was checked via a[ValidateSet]
. That has been changed to a[ValidateScript]
. This script reads the JSON file with all the translations. You find the languages with($JSONObject | Get-Member -type NoteProperty).Name
.
You can test it here:
[CmdletBinding()] Param ( [Parameter(HelpMessage = 'Override the language.')] [ValidateNotNullOrEmpty()] [ValidateScript({ $JSONFile = "$Env:TEMP\JasonData.json" @' { "en" : { "Text 1" : "one", "Text 2" : "two" }, "de" : { "Text 1" : "eins", "Text 2" : "zwei" }, "nl" : { "Text 1" : "een", "Text 2" : "twee" } } '@ | Out-File -FilePath $JSONFile $JSONObject = Get-Content -Path $JSONFile -Raw -Encoding UTF8 | ConvertFrom-Json $Languages = @(($JSONObject | Get-Member -type NoteProperty).Name) $Languages = $Languages | Sort-Object if($Languages -contains $_) { Write-Host "$($_) is supported." $True } else { $SupportedLanguages = "" ForEach ($Language in $Languages) { $LanguageName = ((([CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "$Language*"})[0]).DisplayName).Split(" ")[0] if($SupportedLanguages.Length -eq 0) { $SupportedLanguages = "$Language ($LanguageName)" } else { $SupportedLanguages += ", $Language ($LanguageName)" } } $Lastcomma = $SupportedLanguages.LastIndexOf(", ") $Firstpart = $SupportedLanguages.Substring(0,$Lastcomma) $Lastpart = $SupportedLanguages.SubString($Lastcomma+2,($SupportedLanguages.Length) - $Lastcomma -2) Clear-Host Throw "$_ is no supported language. Supported languages are $Firstpart and $Lastpart." } })] [String] $LanguageOverride ) Clear-Host if($LanguageOverride) { $JSONFileNew = "$Env:TEMP\JasonData.json" $JSONObject = Get-Content -Path $JSONFileNew -Raw -Encoding UTF8 | ConvertFrom-Json $JSONObject.$LanguageOverride } else { Write-Host "No language override. " }
In version 1.2 the following changes have been made:
- Improved function Userdetails.
- Changed the date notation of the logfile to yyyy-MM-dd HH-mm-ss, for example, '2022-11-14 22-23-09'.
The examples below have been created on a Windows 10 English with a French MUI pack and with version 0.2:
Command line | Picture and logfile |
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" | ![]() |
<No logfile> | |
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" -DetailedLogging | ![]() |
jeu. 21 janv. 2021 18:55:57 ***** Check SCCM Client ***** jeu. 21 janv. 2021 18:55:57 ***** User details part ***** jeu. 21 janv. 2021 18:55:57 ***** Language part ***** jeu. 21 janv. 2021 18:55:57 Adding all the actions to the datagrid. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" -DetailedLogging -AllDefaultClientActions | ![]() |
jeu. 21 janv. 2021 18:59:25 ***** Check SCCM Client ***** jeu. 21 janv. 2021 18:59:25 ***** User details part ***** jeu. 21 janv. 2021 18:59:25 ***** Language part ***** jeu. 21 janv. 2021 18:59:25 Adding all the actions to the datagrid. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" -DetailedLogging -AllDefaultClientActions -Lock -NoCancel | ![]() |
jeu. 21 janv. 2021 19:01:44 ***** Check SCCM Client ***** jeu. 21 janv. 2021 19:01:44 ***** User details part ***** jeu. 21 janv. 2021 19:01:44 ***** Language part ***** jeu. 21 janv. 2021 19:01:44 The parameter -Lock is used, so the datagrid is locked for changes. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" -DetailedLogging -AllDefaultClientActions -Lock -NoCancel -LanguageOverride en | ![]() |
jeu. 21 janv. 2021 19:03:48 ***** Check SCCM Client ***** jeu. 21 janv. 2021 19:03:48 ***** User details part ***** jeu. 21 janv. 2021 19:03:48 ***** Language part ***** jeu. 21 janv. 2021 19:03:48 The parameter -Lock is used, so the datagrid is locked for changes. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" -DetailedLogging | ![]() |
jeu. 21 janv. 2021 19:06:43 ***** Check SCCM Client ***** jeu. 21 janv. 2021 19:06:43 ***** User details part ***** jeu. 21 janv. 2021 19:06:43 ***** Language part ***** jeu. 21 janv. 2021 19:06:43 Adding all the actions to the datagrid. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v02.ps1" -DetailedLogging | ![]() |
jeu. 21 janv. 2021 19:14:56 ***** Check SCCM Client ***** jeu. 21 janv. 2021 19:14:57 ***** User details part ***** jeu. 21 janv. 2021 19:14:57 ***** Language part ***** jeu. 21 janv. 2021 19:14:57 Adding all the actions to the datagrid. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v01.ps1" -DetailedLogging -LanguageOverride en | ![]() |
mar. 19 janv 2021 20:08:32 ***** Check SCCM Client *****
mar. 19 janv 2021 20:08:32 The SCCM Client is not working fine or not installed at all. mar. 19 janv 2021 20:08:32 ***** User details part ***** mar. 19 janv 2021 20:08:32 ***** Language part ***** mar. 19 janv 2021 20:08:33 The SCCM Client is not working fine. So the error screen is shown. |
|
."C:\SCCMActions\PerformAllSCCMClientActions_v01.ps1" -DetailedLogging -Silent | ![]() |
mar. 19 janv. 2021 20:15:53 ***** Check SCCM Client *****
mar. 19 janv. 2021 20:15:53 The SCCM Client is working fine. mar. 19 janv. 2021 20:15:53 ***** User details part ***** mar. 19 janv. 2021 20:15:53 ***** Language part ***** mar. 19 janv. 2021 20:15:53 Running action: Software Metering Usage Report Cycle |
Script usage: Get-Help "C:\tmp\PerformAllSCCMClientActions_v11\PerformAllSCCMClientActions_v12.ps1" -Detailed
NAME
C:\tmp\PerformAllSCCMClientActions_v12\PerformAllSCCMClientActions_v12.ps1
SYNOPSIS
Perform all SCCM Client Actions.
SYNTAX
C:\tmp\PerformAllSCCMClientActions_v12\PerformAllSCCMClientActions_v12.ps1 [-LanguageOverride <String>]
[-DetailedLogging] [-NoCancel] [-Silent] [-AllClientActions] [-Lock] [-OverviewSupportedLanguages]
[-HideSCCMClientButtons] [<CommonParameters>]
DESCRIPTION
Perform all SCCM Client Actions.
PARAMETERS
-LanguageOverride <String>
-DetailedLogging [<SwitchParameter>]
-NoCancel [<SwitchParameter>]
-Silent [<SwitchParameter>]
-AllClientActions [<SwitchParameter>]
-Lock [<SwitchParameter>]
-OverviewSupportedLanguages [<SwitchParameter>]
-HideSCCMClientButtons [<SwitchParameter>]
<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (https:/go.microsoft.com/fwlink/?LinkID=113216).
-------------------------- EXAMPLE 1 --------------------------
PS C:\>Let the user select the actions you want to perform.
."PerformAllSCCMClientActions_v12.ps1"
-------------------------- EXAMPLE 2 --------------------------
PS C:\>Let the user select the actions you want to perform with verbose output.
."PerformAllSCCMClientActions_v12.ps1" -Verbose
-------------------------- EXAMPLE 3 --------------------------
PS C:\>Perform all the actions silent.
."PerformAllSCCMClientActions_v12.ps1" -Silent
-------------------------- EXAMPLE 4 --------------------------
PS C:\>Perform all the actions and suppress the Cancel button. Lock the window for changes.
Create a logfile in the users' %TEMP% folder.
."PerformAllSCCMClientActions_v12.ps1" -AllClientActions -NoCancel -Lock -DetailedLogging
-------------------------- EXAMPLE 5 --------------------------
PS C:\>Perform all the actions and suppress the Cancel button. Lock the window for changes. Force the German
language.
Create a logfile in the users' %TEMP% folder.
."PerformAllSCCMClientActions_v12.ps1" -AllClientActions -NoCancel -Lock -LanguageOverride de -DetailedLogging
-------------------------- EXAMPLE 6 --------------------------
PS C:\>Perform all the actions and suppress the Cancel button. Lock the window for changes. Force the German
language.
Create a logfile in the users' %TEMP% folder. Hide the SCCM Client buttons.
."PerformAllSCCMClientActions_v12.ps1" -AllClientActions -NoCancel -Lock -LanguageOverride de -DetailedLogging
-HideSCCMClientButtons
-------------------------- EXAMPLE 7 --------------------------
PS C:\>Find all the supported languages:
."PerformAllSCCMClientActions_v12.ps1" -OverviewSupportedLanguages
REMARKS
To see the examples, type: "get-help C:\tmp\PerformAllSCCMClientActions_v12\PerformAllSCCMClientActions_v12.ps1
-examples".
For more information, type: "get-help C:\tmp\PerformAllSCCMClientActions_v12\PerformAllSCCMClientActions_v12.ps1
-detailed".
For technical information, type: "get-help
C:\tmp\PerformAllSCCMClientActions_v12\PerformAllSCCMClientActions_v12.ps1 -full".
And the script:
<#
.SYNOPSIS
Perform all SCCM Client Actions.
.DESCRIPTION
Perform all SCCM Client Actions.
.EXAMPLE
Let the user select the actions you want to perform.
."PerformAllSCCMClientActions_v12.ps1"
.EXAMPLE
Let the user select the actions you want to perform with verbose output.
."PerformAllSCCMClientActions_v12.ps1" -Verbose
.EXAMPLE
Perform all the actions silent.
."PerformAllSCCMClientActions_v12.ps1" -Silent
.EXAMPLE
Perform all the actions and suppress the Cancel button. Lock the window for changes.
Create a logfile in the users' %TEMP% folder.
."PerformAllSCCMClientActions_v12.ps1" -AllClientActions -NoCancel -Lock -DetailedLogging
.EXAMPLE
Perform all the actions and suppress the Cancel button. Lock the window for changes. Force the German language.
Create a logfile in the users' %TEMP% folder.
."PerformAllSCCMClientActions_v12.ps1" -AllClientActions -NoCancel -Lock -LanguageOverride de -DetailedLogging
.EXAMPLE
Perform all the actions and suppress the Cancel button. Lock the window for changes. Force the German language.
Create a logfile in the users' %TEMP% folder. Hide the SCCM Client buttons.
."PerformAllSCCMClientActions_v12.ps1" -AllClientActions -NoCancel -Lock -LanguageOverride de -DetailedLogging -HideSCCMClientButtons
.EXAMPLE
Find all the supported languages:
."PerformAllSCCMClientActions_v12.ps1" -OverviewSupportedLanguages
.NOTES
Author: Willem-Jan Vroom
Website: https://www.vroom.cc/
Twitter: @TheStingPilot
v0.1:
* Initial version.
v0.2:
* Added two buttons:
- SCCM Client Properties
- SCCM Client Components
* The parameter 'HideSCCMClientButtons' has been introduced.
* The parameter 'AllDefaultClientActions' has been renamed to 'AllClientActions'.
v0.3:
* The json file has the same name as the script. Easier for versioning.
* The name of the logfile is written to to the screen when usering verbose mode.
v0.4:
* The PowerShell LanguageMode is detected. If running in ConstrainedMode than running in silent mode and
no use of forms.
v0.5:
* Improved functions for the PowerShell Constrained Language.
* The functions Add-EntryToLogFile and UserDetails have been rewritten.
v0.6:
* Corrected that when using the detailedlogging switch, no content is written to the log file.
v1.0:
* The list of supported languages has been extended to:
en,bg,cs,da,de,es,fr,id,it,nl,sv,el,et,fi,hu,lt,pl,ro,sk,sl,uk
v1.1:
* If the parameter 'AllClientActions' was used, it was still possible to unselect all the SCCM Client Actions.
* Introduction of the 'OverviewSupportedLanguages' switch.
* List of supported languages has been extended.
v1.2:
* Changed the date notation of the logfile to yyyy-MM-dd HH-mm-ss, for example '2022-11-14 22-23-09'.
* The function 'UserDetails' has been modified.
#>
[CmdletBinding()]
Param
(
[Parameter(HelpMessage='Override the language.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[ValidateNotNullOrEmpty()]
[ValidateScript({
$JSONFile = $PSCommandPath -replace ".ps1",".json"
if(Test-Path($JSONFile))
{
$JSONObject = Get-Content -Path $JSONFile -Raw -Encoding UTF8 | ConvertFrom-Json
$Languages = @(($JSONObject | Get-Member -type NoteProperty).Name)
$Languages = $Languages | Sort-Object
if($Languages -contains $_)
{
$True
}
else
{
$SupportedLanguages = ""
ForEach ($Language in $Languages)
{
$LanguageName = ((([CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "$Language*"})[0]).DisplayName).Split(" ")[0]
if($SupportedLanguages.Length -eq 0)
{
$SupportedLanguages = "$Language ($LanguageName)"
}
else
{
$SupportedLanguages += ", $Language ($LanguageName)"
}
}
$Lastcomma = $SupportedLanguages.LastIndexOf(", ")
$Firstpart = $SupportedLanguages.Substring(0,$Lastcomma)
$Lastpart = $SupportedLanguages.SubString($Lastcomma+2,($SupportedLanguages.Length) - $Lastcomma -2)
Clear-Host
Throw "$_ is no supported language. The following $($Languages.Count) languages are supported: $Firstpart and $Lastpart."
}
}
else
{
Write-Host "The JSON File '$JSONFile' is not found."
Exit 99
}
})]
[String] $LanguageOverride,
[Parameter(HelpMessage ='Logging to the logfile in the users %TEMP% folder.')]
[Parameter(Mandatory = $False, ParameterSetName = 'Default')]
[Switch] $DetailedLogging,
[Parameter(HelpMessage ='Suppress the Cancel button.')]
[Parameter(Mandatory = $False, ParameterSetName = 'Default')]
[Switch] $NoCancel,
[Parameter(HelpMessage ='Perform the operation silently.')]
[Parameter(Mandatory = $False, ParameterSetName = 'Default')]
[Switch] $Silent,
[Parameter(HelpMessage ='Perform all the default client actions.')]
[Parameter(Mandatory = $False, ParameterSetName = 'Default')]
[Switch] $AllClientActions,
[Parameter(HelpMessage ='Lock the datagrid, so no changes can be made.')]
[Parameter(Mandatory = $False, ParameterSetName = 'Default')]
[Switch] $Lock,
[Parameter(HelpMessage='Force a per machine install or uninstall.')]
[Parameter(Mandatory=$False, ParameterSetName='Default')]
[Switch] $OverviewSupportedLanguages,
[Parameter(HelpMessage ='Do not show the SCCM Client Properties and SCCM Client Components buttons.')]
[Parameter(Mandatory = $False, ParameterSetName = 'Default')]
[Switch] $HideSCCMClientButtons
)
Clear-Host
# =============================================================================================================================================
# Function block
# =============================================================================================================================================
Function Add-EntryToLogFile
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-May-2020 / Modified 09-May-2022: Includes the function name
Created by: Willem-Jan Vroom
Organization:
Functionname: Add-EntryToLogFile
=============================================================================================================================================
.SYNOPSIS
This function adds a line to a log file
#>
Param
(
[Parameter(Mandatory=$True)] [string] $Entry,
[Parameter(Mandatory=$False)] [String] $FunctionName
)
Write-Verbose "[Function: $FunctionName] - $Entry"
if($Global:gblDetailedLogging -and $Global:gblLogFile)
{
$Timestamp = (Get-Date -UFormat "%a %e %b %Y %X").ToString()
Add-Content $Global:gblLogFile -Value $($Timestamp + "[Function: $FunctionName] - $Entry") -Force -ErrorAction SilentlyContinue
}
}
Function Test-RegistryKeyValue
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 30-Dec-20
Created by: (C) Aaron Jensen
https://stackoverflow.com/questions/5648931/test-if-registry-value-exists
Organization: Carbon Module
Functionname: Test-RegistryKeyValue
=============================================================================================================================================
.SYNOPSIS
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string] $Path,
[Parameter(Mandatory = $true)]
[string] $Name
)
if (-not (Test-Path -Path $Path -PathType Container))
{
return $false
}
$properties = Get-ItemProperty -Path $Path
if (-not $properties)
{
return $false
}
$member = Get-Member -InputObject $properties -Name $Name
if ($member)
{
return $true
}
else
{
return $false
}
}
Function UserDetails
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 03-Jan-21 / Modified on 14-Jan-21 / Modified on 22-Apr-22 / Modified on 01-May-2022 / Modified on 17-May-2022 /
Modified 21-Nov-2022
Created by: Willem-Jan Vroom
Functionname: UserDetails
=============================================================================================================================================
.SYNOPSIS
This function returns 4 details of the Current Logged In Usser
1. The username of the current logged in user
2. User\Domain of the current logged in user
3. User SID fo the User\Domain
4. Account name that is using the script
Initially, the scriptAccount was found with the command
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
But that command throws up an error due to the PowerShell ConstrainedMode.
Also, the output of whoami /user depends on the language. In the German language the output is different.
The header information is in the German language, so the header should be read from the CSV file.
That can be done with PSObject.Properties.Name
C:\Users\Test>whoami /user
BENUTZERINFORMATIONEN
---------------------
Benutzername SID
==================== ==============================================
windows10wkg_02\test S-1-5-21-1753037473-1212035439-1379364385-1001
On 21-Nov-2022 the function has been changed.
There are 6 situations that should be handled:
1. Find the logged on user sid when there is one user logged on on a 'normal' Windows computer
2. Find the logged on user sid when multiple users are logged on in an RDS / Citrix environment where there is no local admin.
3. Find the logged on user sid when multiple users are logged on in an RDS / Citrix environment where the users are local admin.
4. Find the logged on user sid when there is a SYSTEM account, and there is a user logged on on a 'normal' Windows computer.
This occurs during a Software Center installation performed under the SYSTEM account.
5. Find the logged on user sid when there is a SYSTEM account, and there is a user logged on on an RDS / Citrix environment.
6. Take care of the PowerShell Language Mode.
While testing I found that the MainWindowHandle is not 0 for the user that is running the explorer process. That is true for all the
above mentioned situations.
You can check while running this command with elevated rights:
get-process -IncludeUserName | Select-Object -Property Username, Id, Name,MainWindowHandle | Where {($_.Name -eq "explorer" -or $_.Name -eq "pfwsmgr")} | Format-Table
The output will be something like this:
UserName Id Name MainWindowHandle
-------- -- ---- ----------------
DEMO\user1 1380 explorer 0
DEMO\adminuser2 6556 explorer 131134
So, you have to continue with PID ID 6556.
So, I used the method of finding the PID, and use that PID as a condition for the Get-WMIObject to search for the explorer or pfwsmgr
process with that PID.
#>
# =============================================================================================================================================
# Find the current logged on user by checking the rights on the explore.exe (of pfwsmgr.exe with Ivanti Workspace Control) process.
# If the language mode is FullLanguage then use MainWindowHandle. That is needed when this script is run from SYSTEM context. I assume that
# the SYSTEM account is not effected by the PowerShell Language Mode.
# If the language mode is not FullLanguage then use a check on username and the owner of the explorer or pfwsmgr process.
# =============================================================================================================================================
If ($Global:gblFullLanguage)
{
$PIDID = (get-process | Select-Object -Property Id, Name, MainWindowHandle | Where {(($_.Name -eq "explorer" -or $_.Name -eq "pfwsmgr") -and $($_.MainWindowHandle).ToInt32() -gt 0)}).Id
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process 'explorer' or 'pfwsmgr' has the PID $PIDID."
$Explorer = (Get-WMIObject -Query "Select * From Win32_Process Where (ProcessId=$PIDID)")
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process with PID $PIDID has the name $($Explorer.Name)."
$UserName = $Explorer.GetOwner()
$SID = ($Explorer.GetOwnerSID()).SID
}
else
{
$Explorer = @(Get-WMIObject -Query "Select * From Win32_Process Where (Name='explorer.exe' or Name='pfwsmgr.exe')")
$EnvUSERNAME = $Env:USERNAME
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process 'explorer.exe' or 'pfwsmgr.exe' is running $($Explorer.Count) times."
For ($a=0; $a -le ($Explorer.Count); $a++)
{
$UserName = ($Explorer[$a]).GetOwner()
If ($($UserName.User) -eq $EnvUSERNAME)
{
$SID = (($Explorer[$a]).GetOwnerSID()).SID
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "A valid SID '$SID' has been found for user '$EnvUSERNAME'."
Break
}
}
}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found domain: $($UserName.Domain)."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found username: $($UserName.User)."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found SID: $SID."
$UserAndDomain = "$($Username.Domain )\$($Username.User)".ToUpper()
$tmpScriptAccount = (whoami /user /FO csv | convertfrom-csv)
$TranslatedUserName = $tmpScriptAccount.PSObject.Properties.Name[0]
$ScriptAccount = $($tmpScriptAccount.$TranslatedUserName).ToUpper()
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found scriptaccount: $ScriptAccount"
Return $($Username.User),$UserAndDomain,$SID,$ScriptAccount
}
Function Find-Language
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 30-Dec-20
Created by: Willem-Jan Vroom
Organisation:
Functionname: Find-Language
=============================================================================================================================================
.SYNOPSIS
#>
[CmdletBinding()]
Param
(
$CurrentUserSID
)
$Result = "en-US"
$ThisFunctionName = $MyInvocation.InvocationName
$RegKey = "REGISTRY::HKEY_USERS\$CurrentUserSID\Control Panel\Desktop"
$Value = "PreferredUILanguages"
if (Test-RegistryKeyValue -Path $RegKey -Name $Value)
{
$Result = (get-itemproperty $RegKey | Select -ExpandProperty $Value).Split()[0]
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Regkey '$RegKey' value '$Value' exists. The data is '$Result'."
Return $Result
}
$RegKey = "REGISTRY::HKEY_USERS\.DEFAULT\Control Panel\Desktop\MuiCached"
$Value = "MachinePreferredUILanguages"
if (Test-RegistryKeyValue -Path $RegKey -Name $Value)
{
$Result = (get-itemproperty $RegKey | Select -ExpandProperty $Value).Split()[0]
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Regkey '$RegKey' value '$Value' exists. The data is '$Result'."
Return $Result
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There was a problem reading the registry..."
Return $Result
}
Function Check-HasElevatedRights
{
<#
.NOTES
========================================================================================================================
Created with: Windows PowerShell ISE
Created on: 11-January-2019 / Modified 22-Apr-2022 / Modified 05-May-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Check-HasElevatedRights
========================================================================================================================
.SYNOPSIS
This function checks if an user has admin rights. The function returns $True or $False
Initially, the function was ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'544')
But that command throws up an error due to the PowerShell ConstrainedMode.
"S-1-5-32-544" -in (whoami /groups /FO csv | convertfrom-csv).sid does not work either as it will always return 'true', even if not elevated but
the logged on user is an admin.
So the only good test: check if you can create a file in c:\windows\fonts. If yes, then admin / elevated rights otherwise not.
#>
$RandomFile = ""
For($a=1; $a -le 8; $a++)
{
$RandomFile += [char](Random(97..122))
}
$RandomFile = "$($env:windir)\Fonts\$RandomFile.txt"
Try
{
New-Item $RandomFile -Force -ErrorAction SilentlyContinue | Out-Null
if(test-path($RandomFile))
{
Remove-Item $RandomFile -Force
Return $True
}
else
{
Return $False
}
}
Catch
{
Return $False
}
}
Function Check-SCCMClient
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 14-Jan-21
Created by: Willem-Jan Vroom
Organisation:
Functionname: Check-SCCMClient
=============================================================================================================================================
.SYNOPSIS
This function checks if the SCCM client on the machine is operational. It returns either nothing or an error message.
#>
$ErrorMessage = ""
$ThisFunctionName = $MyInvocation.InvocationName
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** Check SCCM Client *****"
Try
{
$class = Get-WmiObject -Class 'SMS_CLIENT' -List -Namespace 'root\ccm' -ErrorAction Stop
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The SCCM Client is working fine."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End checking SCCM Client *****"
Return $True,$ErrorMessage
}
Catch
{
$ErrorMessage = $($_.Exception.Message).Trim()
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The SCCM Client is not working fine or not installed at all."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The error message is: $ErrorMessage"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End checking SCCM Client *****"
Return $False,$ErrorMessage
}
}
Function SCCMClientProperties
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 20-Jan-21
Created by: Willem-Jan Vroom
Functionname: SCCMClientProperties
=============================================================================================================================================
.SYNOPSIS
This function shows a screen with the SCCM Client Properties or the SCCM Client Components.
#>
[CmdletBinding()]
param
(
[ValidateSet("Properties", "Components")]
[string] $Show,
[string] $Title
)
$ThisFunctionName = $MyInvocation.InvocationName
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Clicked on the button '$Title'"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The SCCM Client $Show"
$frmSCCMClientDetails = New-Object 'System.Windows.Forms.Form'
$datagridview_Details = New-Object 'System.Windows.Forms.DataGridView'
$btnOk1 = New-Object 'System.Windows.Forms.Button'
$frmSCCMClientDetails.Controls.Add($datagridview_Details)
$frmSCCMClientDetails.Controls.Add($btnOk1)
$frmSCCMClientDetails.AcceptButton = $btnOk1
$frmSCCMClientDetails.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmSCCMClientDetails.AutoScaleMode = 'Font'
$frmSCCMClientDetails.ClientSize = New-Object System.Drawing.Size(430, 354)
$frmSCCMClientDetails.ControlBox = $False
$frmSCCMClientDetails.FormBorderStyle = 'Fixed3D'
$frmSCCMClientDetails.Name = 'frmSCCMClientDetails'
$frmSCCMClientDetails.StartPosition = 'CenterParent'
$frmSCCMClientDetails.Text = $Title
$datagridview_Details.ColumnHeadersHeightSizeMode = 'AutoSize'
$datagridview_Details.Location = New-Object System.Drawing.Point(13, 13)
$datagridview_Details.Name = 'datagridview_Details'
$datagridview_Details.Size = New-Object System.Drawing.Size(405, 298)
$datagridview_Details.TabIndex = 1
$datagridview_Details.ScrollBars = 'Both'
$datagridview_Details.ReadOnly = $True
$datagridview_Details.AllowUserToAddRows = $False
$datagridview_Details.AllowUserToDeleteRows = $False
$datagridview_Details.AllowUserToResizeColumns = $False
$datagridview_Details.AllowUserToResizeRows = $False
$datagridview_Details.MultiSelect = $False
$datagridview_Details.ReadOnly = $True
$datagridview_Details.ColumnCount = 2
$datagridview_Details.AllowUserToResizeColumns = $True
$btnOk1.Location = New-Object System.Drawing.Point(343, 317)
$btnOk1.Name = 'btnOk'
$btnOk1.Size = New-Object System.Drawing.Size(75, 25)
$btnOk1.TabIndex = 0
$btnOk1.Text = '&Ok'
$btnOk1.UseVisualStyleBackColor = $True
$btnOk1.add_Click({$frmSCCMClientDetails.Close()})
if($Show -eq "Properties")
{
$SCCMClientProperties = $Global:CPApplet.GetClientProperties() | Select-Object Name,Value
$datagridview_Details.Columns[0].Name = "Name"
$datagridview_Details.Columns[0].width = 150
$datagridview_Details.Columns[1].Name = "Value"
$datagridview_Details.Columns[1].width = 250
$SCCMClientProperties
ForEach ($Property in $SCCMClientProperties)
{
$PropertyName = $Property."Name"
$PropertyValue = $Property."Value"
if( ($PropertyName -eq "ClientVersion") -or ($PropertyName -eq "CurrentManagementPoint") -or ($PropertyName -eq "Name") )
{
$datagridview_Details.Rows.Add($PropertyName,$PropertyValue) | Out-Null
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The SCCM Client property '$PropertyName' has the value '$PropertyValue'"
}
}
}
else
{
$SCCMClientComponents = $Global:CPApplet.GetClientComponents() | Select-Object DisplayName,Version
$datagridview_Details.Columns[0].Name = "Name"
$datagridview_Details.Columns[0].width = 240
$datagridview_Details.Columns[1].Name = "Version"
$datagridview_Details.Columns[1].width = 160
ForEach ($Component in $SCCMClientComponents)
{
$ComponentDisplayName = $Component."DisplayName"
$ComponentVersion = $Component."Version"
$datagridview_Details.Rows.Add($ComponentDisplayName,$ComponentVersion) | Out-Null
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The SCCM Client Component '$ComponentDisplayName' has the version '$ComponentVersion'"
}
}
[void]$frmSCCMClientDetails.ShowDialog($formPerformSCCMClientAct)
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "End of the SCCM Client $Show"
}
Function formPerformSCCMClientAct
{
# =============================================================================================================================================
# Check the SCCM Client and show a box in case the SCCM Client is not working at all.
# There is an error if the function 'Check-SCCMClient' returns not an empty string.
# =============================================================================================================================================
$ThisFunctionName = "[$($MyInvocation.InvocationName)]"
if (-not($BoleanSCCMClient))
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The SCCM Client is not working fine. So the error screen is shown."
$frmSCCMClient = New-Object 'System.Windows.Forms.Form'
$txtNoSCCMClient = New-Object 'System.Windows.Forms.TextBox'
$btnOkErrorForm = New-Object 'System.Windows.Forms.Button'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
$btnOkErrorForm_Click={
$tmpValue = $($SCCMActions.$Language.btnOk).Replace("&","")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The '$tmpValue' button has been clicked."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The application is closed."
$frmSCCMClient.Close()
$frmSCCMClient.Dispose()}
$frmSCCMClient.Controls.Add($txtNoSCCMClient)
$frmSCCMClient.Controls.Add($btnOkErrorForm)
$frmSCCMClient.AcceptButton = $btnOkErrorForm
$frmSCCMClient.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmSCCMClient.AutoScaleMode = 'Font'
$frmSCCMClient.ClientSize = New-Object System.Drawing.Size(287, 106)
$frmSCCMClient.ControlBox = $False
$frmSCCMClient.FormBorderStyle = 'Fixed3D'
$frmSCCMClient.Name = 'frmSCCMClient'
$frmSCCMClient.Text = 'SCCM Client'
$frmSCCMClient.StartPosition = 'CenterScreen'
$txtNoSCCMClient.Location = New-Object System.Drawing.Point(13, 13)
$txtNoSCCMClient.Multiline = $True
$txtNoSCCMClient.Name = 'txtNoSCCMClient'
$txtNoSCCMClient.Size = New-Object System.Drawing.Size(259, 47)
$txtNoSCCMClient.TabIndex = 1
$txtNoSCCMClient.TabStop = $False
$txtNoSCCMClient.Text = "$($SCCMActions.$Language.txtNoSCCMClient) $ErrorMessageRegardingSCCMClient."
$btnOkErrorForm.Location = New-Object System.Drawing.Point(197, 66)
$btnOkErrorForm.Name = 'btnOkErrorForm'
$btnOkErrorForm.Size = New-Object System.Drawing.Size(75, 25)
$btnOkErrorForm.TabIndex = 0
$btnOkErrorForm.Text = $SCCMActions.$Language.btnOk
$btnOkErrorForm.UseVisualStyleBackColor = $True
$btnOkErrorForm.add_Click($btnOkErrorForm_Click)
$btnOk.Enabled = $False
$DefaultSCCMActions.Enabled = $False
$chkAllDefaultActions.Enabled = $False
$btnClientComponents.Enabled = $False
$btnClientProperties.Enabled = $False
$btnCancel.Enabled = $True
$btnCancel.Visible = $True
$frmSCCMClient.ShowDialog() | Out-Null
}
else
{
$chkAllDefaultActions.Checked = $AllClientActions
}
# =============================================================================================================================================
# End checking the SCCM Client.
# =============================================================================================================================================
}
# =============================================================================================================================================
# End function block
# =============================================================================================================================================
# =============================================================================================================================================
# Functions, used in the forms blocks
# =============================================================================================================================================
Function CheckedChanged
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Functionname: CheckedChanged
=============================================================================================================================================
.SYNOPSIS
Selects or unselects all items in the datagrid.
#>
if($chkAllDefaultActions.Checked)
{
$DefaultSCCMActions.SelectAll()
}
else
{
$DefaultSCCMActions.ClearSelection()
}
}
Function ButtonOk
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Functionname: ButtonOk
=============================================================================================================================================
.SYNOPSIS
The Ok button has been clicked so all the requested actions are run and the form is closed.
#>
$btnOk.Enabled = $False
$btnCancel.Enabled = $False
$btnClientComponents.Enabled = $False
$btnClientProperties.Enabled = $False
$tmpValue = $($SCCMActions.$Language.btnOk).Replace("&","")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The '$tmpValue' button has been clicked."
$Total = $DefaultSCCMActions.SelectedRows.Count
$Counter = 1
$SCCMActionsProgressBar.Visible = $True
$Rows = $DefaultSCCMActions.SelectedRows
ForEach ($Row in $Rows)
{
$SCCMActionsProgressBar.Value = $($Counter / $Total * 100)
$SCCMActionName = $DefaultSCCMActions.Rows[$Row.Index].Cells['Name'].Value
ForEach ($Object in $Actions)
{
if($Object.Name -eq $SCCMActionName)
{
Try
{
$txtActionName.Text = $SCCMActionName
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Running action: $SCCMActionName"
$Object.PerformAction()
}
Catch
{
$ErrorMessage = ($_.Exception.Message).Trim()
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There was an error while running the SCCM Client Action '$SCCMActionName'."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error message: $ErrorMessage."
}
}
}
Sleep -Seconds $DefaultWaitInSeconds
$Counter++
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The application is closed."
$formPerformSCCMClientAct.Close()
$formPerformSCCMClientAct.Dispose()
}
Function ButtonCancel
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Functionname: ButtonCancel
=============================================================================================================================================
.SYNOPSIS
The cancel button is clicked so the form is closed.
#>
$tmpValue = $($SCCMActions.$Language.btnCancel).Replace("&","")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The '$tmpValue' button has been clicked."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The application is closed."
$formPerformSCCMClientAct.Close()
$formPerformSCCMClientAct.Dispose()
}
# =============================================================================================================================================
# End functions, used in the forms blocks.
# =============================================================================================================================================
# =============================================================================================================================================
# Show the supported languages
# =============================================================================================================================================
If ($OverviewSupportedLanguages)
{
Clear-Host
$PSFile = $PSCommandPath
$JSONFile = $PSFile.Replace(".ps1",".json")
If (Test-Path($JSONFile))
{
$JSONObject = Get-Content -Path $JSONFile -Raw -Encoding UTF8 | ConvertFrom-Json
$Languages = @(($JSONObject | Get-Member -type NoteProperty).Name)
$Languages = $Languages | Sort-Object
Write-Host "$($Languages.Count) Supported languages:"
ForEach ($Language in $Languages)
{
$LanguageName = ((([CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "$Language*"})[0]).DisplayName).Split(" ")[0]
Write-Host " - Use '$Language' for the $LanguageName language."
}
Write-Host "Use '$([char](34))$PSFile$([char](34)) -LanguageOverride <language>' to override the language."
}
else
{
Write-Host "The file '$JSONFile' does not exists."
}
Exit 0
}
# =============================================================================================================================================
# Declares the variables.
# =============================================================================================================================================
$CurrentDir = Split-Path -parent $MyInvocation.MyCommand.Definition
$arrAppNames = @()
$Global:gblDetailedLogging = $DetailedLogging
$ApplicationName = "Perform all SCCM Client Actions"
$ApplicationVersion = "v1.2"
$DefaultWaitInSeconds = 0.05
$PowerShellLanguageMode = $ExecutionContext.SessionState.LanguageMode
$Global:gblFullLanguage = $PowerShellLanguageMode -eq "FullLanguage"
# =============================================================================================================================================
# Find the logpath.
# It is the key 'HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders' with the value 'Local AppData'.
# And then '\temp' is added.
# =============================================================================================================================================
$OnlyUserName, `
$LoggedOnUserInDomainFormat, `
$UseridSID, `
$InstallAccount = UserDetails
$RegKey = "REGISTRY::HKEY_USERS\$UseridSID\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
$ValueName = "Local AppData"
$Value = (Get-ItemProperty $RegKey).$ValueName
$LogPath = $Value + "\temp"
# =============================================================================================================================================
# Define the results file. This file contains all the results.
# =============================================================================================================================================
$ThisFunctionName = "[Main - Resultsfile]"
if($Global:gblDetailedLogging)
{
$strLastPartOfFileName = " ($((Get-Date -format "yyyy-MM-dd HH-mm-ss").ToString())).log"
$PreFixLogFile = "PerformAllSCCMClientActions"
$Global:gblLogFile = $LogPath + "\"+ $PreFixLogFile + $strLastPartOfFileName
New-Item $Global:gblLogFile -ItemType File -Force | Out-Null
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The logfile '$($Global:gblLogFile)' has been created."
}
if(-not $Global:gblFullLanguage)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The script will run in a silent mode as the PowerShell Language Mode '$PowerShellLanguageMode' is not supported."
$Silent = $True
}
# =============================================================================================================================================
# Check if there is a (working) SCCM Client installed.
# =============================================================================================================================================
$BoleanSCCMClient,$ErrorMessageRegardingSCCMClient = Check-SCCMClient
# =============================================================================================================================================
# Find all the arguments and put them in the log file
# Source: https://ss64.com/ps/psboundparameters.html
# =============================================================================================================================================
$ThisFunctionName = "[Main - Arguments]"
if($Global:gblFullLanguage)
{
$TableWithParameters = @()
$RecordWithParameters = [ordered] @{"Key" = "";
"Value" = ""}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** Parameters part *****"
ForEach($boundparam in $PSBoundParameters.GetEnumerator())
{
$tmpValue = $($boundparam.Value)
$Value = ""
if($tmpValue -is [array])
{
ForEach ($object in $tmpValue)
{
if(-not($value))
{
$Value = $object
}
else
{
$Value +=",$($object)"
}
}
}
else
{
$Value = $tmpValue
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Key: $($boundparam.Key) Value: $Value"
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End Parameters part *****`r`n"
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameters are not written to the logfile due to PowerShell ConstrainedMode."
}
# =============================================================================================================================================
# Write the logged in user details to the log file.
# =============================================================================================================================================
$ThisFunctionName = "[Main - User Details]"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** User details part *****"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logged on user: $LoggedOnUserInDomainFormat"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logged on user (SID): $UseridSID"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Installation account: $InstallAccount"
if($Global:gblDetailedLogging)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logfile: $Global:gblLogFile"
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End User details part *****`r`n"
# =============================================================================================================================================
# Read the JSON file with the translations.
# If the JSON file does not contain the detected language, then fallback to English.
# =============================================================================================================================================
$ThisFunctionName = "[Main - Language]"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** Language part *****"
if ($LanguageOverride)
{
$Language = $LanguageOverride
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameter -LanguageOverride is used. The language is '$Language'."
}
else
{
$Language = (Find-Language -CurrentUserSID $UseridSID).SubString(0, 2)
}
$JSONFile = $CurrentDir + "\"+ $($MyInvocation.MyCommand.Name -replace ".ps1",".json")
if (-not (Test-Path($JSONFile)))
{
$Message = "The language file '$JSONFile' does not exists. Leaving the script."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry $Message
Write-Host $Message
Exit 1
}
$SCCMActions = Get-Content $JSONFile -Encoding UTF8 | ConvertFrom-Json
if (-not ($SCCMActions.$Language))
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The language '$Language' is not found in the json file '$JSONFile'."
$Language = "en"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Falling back to the default language '$Language'."
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The language '$Language' is used."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End language part *****`r`n"
# =============================================================================================================================================
# End reading the JSON file with the translations.
# =============================================================================================================================================
if($Silent)
{
# =============================================================================================================================================
# Begin silent block
# =============================================================================================================================================
$AllClientActions = $True
if(-not ($BoleanSCCMClient))
{
$ThisFunctionName = "[Main - Check SCCM Client]"
$ErrorMessage = "There is no working SCCM Client."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry $ErrorMessage
Write-Host $ErrorMessage
Exit 2
}
# =============================================================================================================================================
# Perform the SCCM Client Actions
# =============================================================================================================================================
$Global:CPApplet = New-Object -Comobject CPApplet.CPAppletMgr
$Actions = $Global:CPApplet.GetClientActions()
$ThisFunctionName = "[Silent - Perform SCCM Client Actions]"
$Counter = 1
$Total = $Actions.Count
ForEach ($Object in $Actions)
{
Write-Progress -Activity "Processing all the SCCM Client Actions" -Status "Action: $($Object.Name)." -PercentComplete (($Counter / $Total) * 100 )
Try
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Running action: $($Object.Name)"
$Object.PerformAction()
}
Catch
{
$ErrorMessage = ($_.Exception.Message).Trim()
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There was an error while running the SCCM Client Action '$($Object.Name)'."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error message: $ErrorMessage."
}
Sleep -Seconds $DefaultWaitInSeconds
$Counter ++
}
# =============================================================================================================================================
# End silent block
# =============================================================================================================================================
}
Else
{
# =============================================================================================================================================
# Begin not silent block
# =============================================================================================================================================
# =============================================================================================================================================
# Forms Block
# =============================================================================================================================================
Add-Type -AssemblyName System.Windows.Forms
$formPerformSCCMClientAct = New-Object 'System.Windows.Forms.Form'
$btnCancel = New-Object 'System.Windows.Forms.Button'
$btnOk = New-Object 'System.Windows.Forms.Button'
$chkAllDefaultActions = New-Object 'System.Windows.Forms.CheckBox'
$txtActionName = New-Object 'System.Windows.Forms.TextBox'
$txtDescription = New-Object 'System.Windows.Forms.TextBox'
$DefaultSCCMActions = New-Object 'System.Windows.Forms.DataGridView'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
$SCCMActionsProgressBar = New-Object 'System.Windows.Forms.ProgressBar'
$btnClientComponents = New-Object 'System.Windows.Forms.Button'
$btnClientProperties = New-Object 'System.Windows.Forms.Button'
$formPerformSCCMClientAct_Shown={formPerformSCCMClientAct}
$ThisFunctionName = "[formPerformSCCMClientAct]"
$formPerformSCCMClientAct.Controls.Add($btnCancel)
$formPerformSCCMClientAct.Controls.Add($btnOk)
$formPerformSCCMClientAct.Controls.Add($chkAllDefaultActions)
$formPerformSCCMClientAct.Controls.Add($DefaultSCCMActions)
$formPerformSCCMClientAct.Controls.Add($SCCMActionsProgressBar)
$formPerformSCCMClientAct.Controls.Add($txtActionName)
$formPerformSCCMClientAct.Controls.Add($txtDescription)
$formPerformSCCMClientAct.Controls.Add($btnClientComponents)
$formPerformSCCMClientAct.Controls.Add($btnClientProperties)
$formPerformSCCMClientAct.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$formPerformSCCMClientAct.AutoScaleMode = 'Font'
$formPerformSCCMClientAct.ClientSize = New-Object System.Drawing.Size(467, 504)
$formPerformSCCMClientAct.Name = 'formPerformSCCMClientAct'
$formPerformSCCMClientAct.Text = "$ApplicationName $ApplicationVersion"
$formPerformSCCMClientAct.add_shown($formPerformSCCMClientAct_Shown)
$formPerformSCCMClientAct.FormBorderStyle = 'FixedDialog'
$formPerformSCCMClientAct.StartPosition = 'CenterScreen'
$btnClientProperties.Location = New-Object System.Drawing.Point(24, 449)
$btnClientProperties.Name = 'btnClientProperties'
$btnClientProperties.Size = New-Object System.Drawing.Size(110, 44)
$btnClientProperties.TabIndex = 10
$btnClientProperties.Text = $SCCMActions.$Language.SCCMClientProperties
$btnClientProperties.UseVisualStyleBackColor = $True
$btnClientProperties.add_Click({SCCMClientProperties -Show Properties -Title $($SCCMActions.$Language.SCCMClientProperties)})
$btnClientComponents.Location = New-Object System.Drawing.Point(140, 449)
$btnClientComponents.Name = 'btnClientComponents'
$btnClientComponents.Size = New-Object System.Drawing.Size(110, 44)
$btnClientComponents.TabIndex = 11
$btnClientComponents.Text = $SCCMActions.$Language.SCCMClientComponents
$btnClientComponents.UseVisualStyleBackColor = $True
$btnClientComponents.add_Click({SCCMClientProperties -Show Components -Title $($SCCMActions.$Language.SCCMClientComponents)})
$btnCancel.Location = New-Object System.Drawing.Point(287, 449)
$btnCancel.Name = 'btnCancel'
$btnCancel.Size = New-Object System.Drawing.Size(75, 44)
$btnCancel.TabIndex = 5
$btnCancel.Text = $SCCMActions.$Language.btnCancel
$btnCancel.UseVisualStyleBackColor = $True
$btnCancel.add_Click($btnCancel_Click)
$btnOk.Location = New-Object System.Drawing.Point(368, 449)
$btnOk.Name = 'btnOk'
$btnOk.Size = New-Object System.Drawing.Size(75, 44)
$btnOk.TabIndex = 6
$btnOk.Text = $SCCMActions.$Language.btnOk
$btnOk.UseVisualStyleBackColor = $True
$chkAllDefaultActions.Location = New-Object System.Drawing.Point(24, 21)
$chkAllDefaultActions.Name = 'chkAllDefaultActions'
$chkAllDefaultActions.Size = New-Object System.Drawing.Size(240, 24)
$chkAllDefaultActions.TabIndex = 1
$chkAllDefaultActions.Text = $SCCMActions.$Language.chkAllDefaultActions
$chkAllDefaultActions.UseVisualStyleBackColor = $True
$DefaultSCCMActions.ColumnHeadersHeightSizeMode = 'AutoSize'
$DefaultSCCMActions.Location = New-Object System.Drawing.Point(24, 51)
$DefaultSCCMActions.Name = 'DefaultSCCMActions'
$DefaultSCCMActions.Size = New-Object System.Drawing.Size(419, 306)
$DefaultSCCMActions.TabIndex = 0
$DefaultSCCMActions.ColumnCount = 2
$DefaultSCCMActions.ColumnHeadersVisible = $true
$DefaultSCCMActions.Columns[0].Name = "Name"
$DefaultSCCMActions.Columns[0].width = 600
$DefaultSCCMActions.ScrollBars = 'Vertical'
$DefaultSCCMActions.ReadOnly = $True
$DefaultSCCMActions.AllowUserToAddRows = $False
$DefaultSCCMActions.AllowUserToDeleteRows = $False
$DefaultSCCMActions.AllowUserToResizeColumns = $False
$DefaultSCCMActions.AllowUserToResizeRows = $False
$DefaultSCCMActions.SelectionMode = "FullRowSelect"
$DefaultSCCMActions.MultiSelect = $true
$DefaultSCCMActions.ReadOnly = $True
$txtActionName.Location = New-Object System.Drawing.Point(153, 377)
$txtActionName.Name = 'txtActionName'
$txtActionName.Size = New-Object System.Drawing.Size(290, 20)
$txtDescription.Location = New-Object System.Drawing.Point(24, 377)
$txtDescription.Name = 'txtDescription'
$txtDescription.Size = New-Object System.Drawing.Size(123, 20)
$txtDescription.Text = $SCCMActions.$Language.txtDescription
$SCCMActionsProgressBar.Location = New-Object System.Drawing.Point(24, 403)
$SCCMActionsProgressBar.Name = '$SCCMActionsProgressBar'
$SCCMActionsProgressBar.Size = New-Object System.Drawing.Size(419, 40)
$SCCMActionsProgressBar.Visible = $False
$SCCMActionsProgressBar.Style = 'Continuous'
if($HideSCCMClientButtons)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameter 'HideSCCMClientButtons' is specified, so the buttons '$($SCCMActions.$Language.SCCMClientProperties)' and"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "'$($SCCMActions.$Language.SCCMClientComponents)' will be invisible."
$btnClientProperties.Visible = $False
$btnClientComponents.Visible = $False
}
$DefaultSCCMActions.Add_Click({
if($chkAllDefaultActions.Checked)
{
$DefaultSCCMActions.SelectAll()
}
})
# =============================================================================================================================================
# End Forms Block
# =============================================================================================================================================
# =============================================================================================================================================
# Hide the Cancel button in case the parameter 'NoCancel' is used.
# =============================================================================================================================================
if($NoCancel)
{
$btnCancel.Visible = $False
$formPerformSCCMClientAct.ControlBox = $False
$tmpValue = $SCCMActions.$Language."btnCancel".Replace("&","")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameter -NoCancel is used, so the cancel button '$tmpValue' is invisible."
}
if($Lock)
{
$DefaultSCCMActions.ReadOnly = $True
$chkAllDefaultActions.Enabled = $False
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameter -Lock is used, so the datagrid is locked for changes."
}
# =============================================================================================================================================
# Fill the grid
# =============================================================================================================================================
if($BoleanSCCMClient)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Adding all the actions to the datagrid."
$Global:CPApplet = New-Object -Comobject CPApplet.CPAppletMgr
$Actions = $Global:CPApplet.GetClientActions()
$Actions | foreach {$DefaultSCCMActions.Rows.Add($_."Name") | Out-Null }
if($AllClientActions)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameter 'AllClientActions' is specified, so all the rows are selected."
}
}
# =============================================================================================================================================
# End Fill the grid
# =============================================================================================================================================
# =============================================================================================================================================
# Create the buttons and checkboxes
# =============================================================================================================================================
$chkAllDefaultActions.Add_CheckedChanged({CheckedChanged})
$btnOk.add_Click({ButtonOk})
$btnCancel.add_Click({ButtonCancel})
# =============================================================================================================================================
# End creating the buttons and checkboxes.
# =============================================================================================================================================
[void]$formPerformSCCMClientAct.ShowDialog()
$formPerformSCCMClientAct.Dispose()
# =============================================================================================================================================
# End not silent block
# =============================================================================================================================================
}
# =============================================================================================================================================
# End application
# =============================================================================================================================================
The content of PerformAllSCCMClientActions_v12.json. Use my script Translate content of a JSON file with Google, Microsoft and DeepL to add extra languages.
{
"en": {
"btnCancel": "&Cancel",
"btnOk": "&Ok",
"chkAllDefaultActions": "Select all default actions",
"SCCMClientComponents": "SCCM Client Components",
"SCCMClientProperties": "SCCM Client Properties",
"txtDescription": "Running action:",
"txtNoSCCMClient": "The SCCM Client is nog working properly. The error message is:"
},
"de": {
"btnCancel": "Abbrechen",
"btnOk": "Okay",
"chkAllDefaultActions": "Alle Standardaktionen auswählen",
"SCCMClientComponents": "SCCM-Clientkomponenten",
"SCCMClientProperties": "SCCM-Clienteigenschaften",
"txtDescription": "Ausführende Aktion:",
"txtNoSCCMClient": "Der SCCM-Client funktioniert einwandfrei. Die Fehlermeldung lautet:"
},
"es": {
"btnCancel": "Cancelar",
"btnOk": "De acuerdo",
"chkAllDefaultActions": "Seleccionar todas las acciones predeterminadas",
"SCCMClientComponents": "Componentes de cliente de SCCM",
"SCCMClientProperties": "Propiedades del cliente SCCM",
"txtDescription": "Acción en ejecución:",
"txtNoSCCMClient": "El cliente SCCM no funciona correctamente. El mensaje de error es:"
},
"fr": {
"btnCancel": "Annuler",
"btnOk": "D’accord",
"chkAllDefaultActions": "Sélectionner toutes les actions par défaut",
"SCCMClientComponents": "Composants clients SCCM",
"SCCMClientProperties": "Propriétés du client SCCM",
"txtDescription": "Action en cours d’exécution :",
"txtNoSCCMClient": "Le client SCCM ne fonctionne pas correctement. Le message d’erreur est :"
},
"id": {
"btnCancel": "Membatalkan",
"btnOk": "Oke",
"chkAllDefaultActions": "Memilih semua tindakan default",
"SCCMClientComponents": "Komponen Klien SCCM",
"SCCMClientProperties": "Properti Klien SCCM",
"txtDescription": "Tindakan berjalan:",
"txtNoSCCMClient": "Klien SCCM tidak berfungsi dengan baik. Pesan kesalahannya adalah:"
},
"it": {
"btnCancel": "Annulla",
"btnOk": "Ok",
"chkAllDefaultActions": "Seleziona tutte le azioni predefinite",
"SCCMClientComponents": "Componenti client SCCM",
"SCCMClientProperties": "Proprietà client SCCM",
"txtDescription": "Azione in esecuzione:",
"txtNoSCCMClient": "Il client SCCM non funziona correttamente. Il messaggio di errore è:"
},
"nl": {
"btnCancel": "Annuleren",
"btnOk": "OK",
"chkAllDefaultActions": "Selecteer alle standaardacties",
"SCCMClientComponents": "SCCM-clientcomponenten",
"SCCMClientProperties": "Sccm-clienteigenschappen",
"txtDescription": "Lopende actie:",
"txtNoSCCMClient": "De SCCM Client werkt niet goed. De foutmelding is:"
},
"pt": {
"btnCancel": "Cancelar",
"btnOk": "Okey",
"chkAllDefaultActions": "Selecionar todas as ações padrão",
"SCCMClientComponents": "Componentes do cliente SCCM",
"SCCMClientProperties": "Propriedades do cliente SCCM",
"txtDescription": "Ação em execução:",
"txtNoSCCMClient": "O cliente SCCM está nog funcionando corretamente. A mensagem de erro é:"
},
"zh": {
"btnCancel": "取消",
"btnOk": "还行",
"chkAllDefaultActions": "选择所有默认操作",
"SCCMClientComponents": "SCCM 客户端组件",
"SCCMClientProperties": "SCCM 客户端属性",
"txtDescription": "跑步动作:",
"txtNoSCCMClient": "SCCM 客户端工作正常。错误消息是:"
}
}
Are you looking for a script that removes items from the Software Center Cache: then use my script Clear Software Center Cache.
After extracting the ZIP file, please 'unblock' the Powershell script and/or the batch file.
