├── AddSharedPrintersIntune.ps1
├── AutoEnrollAlreadyAzureADJoined.ps1
├── Create-AutoPilotDevicesDynamicGroup.ps1
├── Create-IntuneUsersDynamicGroup.ps1
├── CreateRegistryKeyForCurrentUserAsSystem.ps1
├── DriveMap+Logonscript.ps1
├── Install-WingetTools.intunewin
├── Install-WingetTools.ps1
├── Install-WingetTools_Detection.ps1
├── Invoke-ADCSCertMappingNDES.ps1
├── PinToTaskbar.ps1
├── Remove-LocalAdminPrivelageDETECTION.ps1
├── Remove-LocalAdminPrivelageREMEDIATION.ps1
├── RemoveDuplicatedShortcuts_plustask.ps1
├── Volume_Shadow_Copy_Task.ps1
├── Winget-InstallDetection.ps1
├── Winget-InstallPackage.intunewin
├── Winget-InstallPackage.ps1
├── Winget-InstallStorePackage-Detection.ps1
├── Winget-InstallStorePackage.ps1
├── Winget-UpgradeSelect.ps1
├── WingetUpgrade-ProactiveDetection.ps1
├── WingetUpgrade-Remediation.ps1
├── WingetUpgradeTask.ps1
├── chromebookmarks.ps1
├── map-printers-scheduledtask.ps1
├── powersettings.ps1
├── remove-localadmins.ps1
├── set_startmenu_taskbar_layout.ps1
├── sharepoint_trustedsites.ps1
├── startmenu_layout_plus_scheduledtask.ps1
└── teams_firewallrules.ps1
/AddSharedPrintersIntune.ps1:
--------------------------------------------------------------------------------
1 | # This first section adds the registry keys for point and print. This allows standard users to install printers.
2 | # Enter the trusted printers by FQDN below
3 | $printServers = @(
4 | "PrintServer1.domain.local"
5 | "PrintServer2.domain.local"
6 | )
7 | #endregion
8 | #region PnP retrictions
9 | $hklmKeys = @(
10 | [PSCustomObject]@{
11 | Name = "Restricted"
12 | Type = "DWORD"
13 | Value = "1"
14 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
15 | }
16 | [PSCustomObject]@{
17 | Name = "TrustedServers"
18 | Type = "DWORD"
19 | Value = "1"
20 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
21 | }
22 | [PSCustomObject]@{
23 | Name = "InForest"
24 | Type = "DWord"
25 | Value = "0"
26 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
27 | }
28 | [PSCustomObject]@{
29 | Name = "NoWarningNoElevationOnInstall"
30 | Type = "DWord"
31 | Value = "1"
32 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
33 | }
34 | [PSCustomObject]@{
35 | Name = "UpdatePromptSettings"
36 | Type = "DWord"
37 | Value = "2"
38 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
39 | }
40 | [PSCustomObject]@{
41 | Name = "ServerList"
42 | Type = "String"
43 | Value = $printServers -join ";"
44 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
45 | }
46 | [PSCustomObject]@{
47 | Name = "RestrictDriverInstallationToAdministrators"
48 | Type = "DWORD"
49 | Value = "0"
50 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
51 | }
52 | )
53 | $hklmKeys += [PSCustomObject]@{
54 | Name = "PackagePointAndPrintServerList"
55 | Type = "DWORD"
56 | Value = "1"
57 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PackagePointAndPrint"
58 | }
59 | foreach ($p in $printServers) {
60 | $hklmKeys += [PSCustomObject]@{
61 | Name = $p
62 | Type = "String"
63 | Value = $p
64 | Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PackagePointAndPrint\ListofServers"
65 | }
66 | }
67 |
68 | function Set-ComputerRegistryValues {
69 | param (
70 | [Parameter(Mandatory = $true)]
71 | [array]$RegistryInstance
72 | )
73 | try {
74 | foreach ($key in $RegistryInstance) {
75 | $keyPath = "$($key.Path)"
76 | if (!(Test-Path $keyPath)) {
77 | Write-Host "Registry path : $keyPath not found. Creating now." -ForegroundColor Green
78 | New-Item -Path $keyPath -Force | Out-Null
79 | Write-Host "Creating item property: $($key.Name)" -ForegroundColor Green
80 | New-ItemProperty -Path $keyPath -Name $key.Name -Value $key.Value -PropertyType $key.Type -Force
81 | }
82 | else {
83 | Write-Host "Creating item property: $($key.Name)" -ForegroundColor Green
84 | New-ItemProperty -Path $keyPath -Name $key.Name -Value $key.Value -PropertyType $key.Type -Force
85 | }
86 | }
87 | }
88 | catch {
89 | Throw $_.Exception.Message
90 | }
91 | }
92 | #endregion
93 | Set-ComputerRegistryValues -RegistryInstance $hklmKeys
94 |
95 | ######################################################################################################################################################
96 | # This next section creates a scheduled task to run as the logged on user. This will auto map the printers if they are not already mapped at user login
97 | # Also added a trigger when a user connects to VPN using the built in Windows VPN client.
98 | #######################################################################################################################################################
99 |
100 | $script= @'
101 | if ((Get-Printer | where name -like "\\PrintServer1.domain.local\Printer1"))
102 | {
103 | exit
104 | }
105 | $fp01= Test-Connection -ComputerName PrintServer1.domain.local -Quiet
106 | if ($fp01) {
107 | add-printer -ConnectionName "\\PrintServer1.domain.local\Printer1"
108 | add-printer -ConnectionName "\\PrintServer1.domain.local\Printer2"
109 | }
110 | ELSE
111 | {
112 | exit
113 | }
114 | '@
115 |
116 | # Create a directory for our login script
117 | if ( -not (Test-Path -Path c:\automation) )
118 | {
119 | new-item c:\automation -ItemType directory -force
120 | }
121 | set-content c:\automation\addprinters.ps1 $script
122 |
123 | if( -Not (Get-ScheduledTask -TaskName "Add Shared Printers" -ErrorAction SilentlyContinue -OutVariable task) )
124 | {
125 | $Params = @{
126 | Action = (New-ScheduledTaskAction -Execute 'powershell' -Argument '-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass c:\automation\addprinters.ps1')
127 | Trigger = (New-ScheduledTaskTrigger -AtLogOn)
128 | Principal = (New-ScheduledTaskPrincipal -UserId (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -expand UserName))
129 | TaskName = 'Add Shared Printers'
130 | Description = 'Add Shared Printers'
131 | }
132 | Register-ScheduledTask @Params
133 |
134 | # Add trigger for connection to VPN
135 | $CIMTriggerClass = Get-CimClass -ClassName MSFT_TaskEventTrigger -Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskEventTrigger
136 | $Trigger = @(
137 | (New-CimInstance -CimClass $CIMTriggerClass -ClientOnly),
138 | (New-ScheduledTaskTrigger -AtLogOn)
139 | )
140 | $Trigger[0].Subscription =
141 | @"
142 |
143 | "@
144 | $Trigger[0].Enabled = $True
145 |
146 | Set-Scheduledtask "Add Shared Printers" -Trigger $Trigger
147 |
148 | Start-ScheduledTask -TaskName "Add Shared Printers"
149 | }
150 | else
151 | {
152 | $CIMTriggerClass = Get-CimClass -ClassName MSFT_TaskEventTrigger -Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskEventTrigger
153 | $Trigger = @(
154 | (New-CimInstance -CimClass $CIMTriggerClass -ClientOnly),
155 | (New-ScheduledTaskTrigger -AtLogOn)
156 | )
157 | $Trigger[0].Subscription =
158 | @"
159 |
160 | "@
161 | $Trigger[0].Enabled = $True
162 |
163 | Set-Scheduledtask "Add Shared Printers" -Trigger $Trigger
164 |
165 | Start-ScheduledTask -TaskName "Add Shared Printers"
166 | }
167 |
168 |
--------------------------------------------------------------------------------
/AutoEnrollAlreadyAzureADJoined.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | Create a scheduled task and apply registry keys to force auto enrollment to MDM for already
3 | AzureAD joined devices. These are the same actions applied when applying the Auto enroll MDM GPO settings.
4 | #>
5 | $RegKey ="HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\"
6 |
7 | $RegKey1 ="HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\MDM"
8 |
9 | $ScheduleName ="Schedule created by enrollment client for automatically enrolling in MDM from AAD"
10 |
11 | $Date = Get-Date -Format "yyyy-MM-dd"
12 |
13 | $Time = (Get-date).AddMinutes(5).ToString("HH:mm:ss")
14 |
15 |
16 |
17 | $ST = @"
18 |
19 |
20 |
21 | Microsoft Corporation
22 | \Microsoft\Windows\EnterpriseMgmt\Schedule created by enrollment client for automatically enrolling in MDM from AAD
23 | D:P(A;;FA;;;BA)(A;;FA;;;SY)(A;;FRFX;;;LS)
24 |
25 |
26 |
27 |
28 | PT5M
29 | P1D
30 | true
31 |
32 | $($Date)T$($Time)
33 | true
34 |
35 |
36 |
37 |
38 | S-1-5-18
39 | LeastPrivilege
40 |
41 |
42 |
43 | Queue
44 | false
45 | false
46 | true
47 | true
48 | true
49 |
50 | false
51 | false
52 |
53 | true
54 | true
55 | false
56 | false
57 | false
58 | true
59 | false
60 | PT1H
61 | 7
62 |
63 |
64 |
65 | %windir%\system32\deviceenroller.exe
66 | /c /AutoEnrollMDM
67 |
68 |
69 |
70 |
71 | "@
72 |
73 |
74 |
75 |
76 |
77 | New-Item -Path $RegKey -Name MDM
78 |
79 | New-ItemProperty -Path $RegKey1 -Name AutoEnrollMDM -Value 1
80 |
81 | New-ItemProperty -Path $RegKey1 -Name UseAADCredentialType -Value 1
82 |
83 | (Register-ScheduledTask -XML $ST -TaskName $ScheduleName -Force) | Out-null
--------------------------------------------------------------------------------
/Create-AutoPilotDevicesDynamicGroup.ps1:
--------------------------------------------------------------------------------
1 | Install-Module azureadpreview -AllowClobber -Force -Confirm:$false
2 | Import-Module AzureADPreview
3 | Connect-AzureAD
4 |
5 | #Create Dynamic Device Group for Autopilot
6 |
7 | $AutoPilotGroup = @{
8 | DisplayName = "Autopilot Devices"
9 | Description ="Dynamic Group for Autpilot Devices"
10 | GroupTypes = "DynamicMembership"
11 | Membershiprule = '(device.devicePhysicalIDs -any _ -contains "[ZTDId]")'
12 | MailEnabled = $False
13 | MailNickName = 'AutopilotDevices'
14 | SecurityEnabled = $True
15 | MembershipRuleProcessingState = "On"
16 | }
17 | if ((Get-AzureADMSGroup | Where Displayname -like "Autopilot Devices") -eq $Null){
18 |
19 | New-AzureADMSGroup @AutopilotGroup
20 | }
21 | Disconnect-AzureAD
--------------------------------------------------------------------------------
/Create-IntuneUsersDynamicGroup.ps1:
--------------------------------------------------------------------------------
1 | Connect-MGGraph -Scope "Directory.ReadWrite.All"
2 | $GroupParams = @{
3 | DisplayName = "Intune Users"
4 | Description ="Dynamic Group for Intune Users"
5 | GroupTypes = "DynamicMembership"
6 | Membershiprule = '(user.assignedPlans -any (assignedPlan.servicePlanId -eq "c1ec4a95-1f05-45b3-a911-aa3fa01094f5" -and assignedPlan.capabilityStatus -eq "Enabled"))'
7 | MailEnabled = $False
8 | MailNickName = 'AutopilotDevices'
9 | SecurityEnabled = $True
10 | MembershipRuleProcessingState = "On"
11 | }
12 | New-MGGroup -BodyParameter $GroupParams
13 | Disconnect-MGGraph
--------------------------------------------------------------------------------
/CreateRegistryKeyForCurrentUserAsSystem.ps1:
--------------------------------------------------------------------------------
1 | #This script will load the HKU registry path for the current user and allow you to modify their hive as system/administrator
2 | #This is sometimes needed as user may not have permission to create keys/write values to their HKCU hive
3 |
4 | $UserSID = (New-Object -ComObject Microsoft.DiskQuota).TranslateLogonNameToSID((Get-WmiObject -Class Win32_ComputerSystem).Username)
5 |
6 | $Path = "HKU\$UserSID\PATH_TO_KEY_TO_CREATE"
7 | New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
8 | Reg Add $path /f
9 | reg add $path /v DWORDNAME /t REG_DWORD /d 1 /f
10 |
--------------------------------------------------------------------------------
/DriveMap+Logonscript.ps1:
--------------------------------------------------------------------------------
1 | $ServerName = #Enter the FQDN of the file server
2 | $DriveLetter = #Enter drive letter
3 | $TaskName = $DriveLetter + " Drive Map"
4 | $UNCPath = #Enter UNC file path for fileshare
5 |
6 | $tasks = get-scheduledtask -taskpath '\' | select -ExpandProperty taskname
7 | if ($tasks -like $TaskName){Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false ; write-host "Task Unregistered" }
8 | $gmapscript= @"
9 | sleep 20
10 | `$fp01 = Test-Connection -ComputerName $ServerName -ErrorAction SilentlyContinue
11 | `$UNCPath = $UNCPath
12 | if (`$fp01) {
13 | net use $($DriveLetter): /delete
14 | net use $($DriveLetter): `$UNCPath
15 | }
16 | "@
17 | if ( -not (Test-Path -Path c:\automation) )
18 | {
19 | new-item c:\automation -ItemType directory -force
20 | }
21 | set-content c:\automation\$($DriveLetter + 'drivemap.ps1') $gmapscript
22 |
23 | $action = New-ScheduledTaskAction -Execute 'powershell' -Argument "-ExecutionPolicy Bypass -NoProfile -WindowStyle Minimized -File $($DriveLetter + 'drivemap.ps1')"
24 | $trigger = New-ScheduledTaskTrigger -AtLogOn
25 | $principal = New-ScheduledTaskPrincipal -UserId (Get-CimInstance –ClassName Win32_ComputerSystem | Select-Object -expand UserName)
26 | $task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal
27 | Register-ScheduledTask $TaskName -InputObject $task
28 | Start-ScheduledTask -TaskName $TaskName
29 |
--------------------------------------------------------------------------------
/Install-WingetTools.intunewin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djust270/Intune-Scripts/62f388a7c8116c4f8c975bcd27d6e883c60e75c5/Install-WingetTools.intunewin
--------------------------------------------------------------------------------
/Install-WingetTools.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 8/22/2022 9:30 AM
6 | Created by: David Just
7 | Filename: Install-WingetTools
8 | ===========================================================================
9 | .DESCRIPTION
10 | This script will Install Winget and the WingetTools PowerShell module.
11 | #>
12 |
13 | #region functions
14 | function Install-VisualC #Install VisualC++ 2015-2022 x64
15 | {
16 | $url = 'https://aka.ms/vs/17/release/vc_redist.x64.exe'
17 | $WebClient = New-Object System.Net.WebClient
18 | $WebClient.DownloadFile('https://aka.ms/vs/17/release/vc_redist.x64.exe', "$env:Temp\vc_redist.x64.exe")
19 | $WebClient.Dispose()
20 | start-process "$env:temp\vc_redist.x64.exe" -argumentlist "/q /norestart" -Wait
21 | }
22 |
23 | function Get-RegUninstallKey #Enumerate registry uninstall keys
24 | {
25 | param (
26 | [string]$DisplayName
27 | )
28 | $ErrorActionPreference = 'Continue'
29 | $uninstallKeys = "registry::HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall", "registry::HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall"
30 | $softwareTable = @()
31 |
32 | foreach ($key in $uninstallKeys)
33 | {
34 | $softwareTable += Get-Childitem $key | Get-ItemProperty | where displayname | Sort-Object -Property displayname
35 | }
36 | if ($DisplayName)
37 | {
38 | $softwareTable | where displayname -Like "*$DisplayName*"
39 | }
40 | else
41 | {
42 | $softwareTable | Sort-Object -Property displayname -Unique
43 | }
44 |
45 | }
46 |
47 | function Install-WingetTools #Install the WingetTools module.
48 | {
49 | Install-PackageProvider -Name NuGet -Force
50 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
51 | Install-Module -Name WingetTools
52 | if (-Not [bool](Get-Module -ListAvailable -Name WingetTools))
53 | {
54 | $GithubURL = "https://github.com/jdhitsolutions/WingetTools/archive/refs/heads/main.zip"
55 | $ModuleZipFile = "$Env:TEMP\WingetTools.zip"
56 | $WebClient = [System.Net.WebClient]::new()
57 | $WebClient.DownloadFile($GithubURL, $ModuleZipFile)
58 | Expand-Archive -Path "$Env:TEMP\WingetTools.zip" -DestinationPath "$env:windir\System32\WindowsPowerShell\v1.0\Modules"
59 | Rename-Item -Path "$env:windir\System32\WindowsPowerShell\v1.0\Modules\WingetTools-main" -NewName "WingetTools"
60 | }
61 | }
62 |
63 | function Install-WingetAsSystem # Install WinGet as logged on user by creating a scheduled task
64 | {
65 | $script = @'
66 | # Adapted from https://github.com/microsoft/winget-pkgs/blob/master/Tools/SandboxTest.ps1 (better than my original code!)
67 | # This will install the latest version of WinGet and its dependancies
68 | $tempFolderName = 'WinGetInstall'
69 | $tempFolder = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $tempFolderName
70 | New-Item $tempFolder -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
71 |
72 | $apiLatestUrl = 'https://api.github.com/repos/microsoft/winget-cli/releases/latest'
73 |
74 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
75 | $WebClient = New-Object System.Net.WebClient
76 |
77 | function Get-LatestUrl {
78 | ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle$' }).browser_download_url
79 | }
80 |
81 | function Get-LatestHash {
82 | $shaUrl = ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt$' }).browser_download_url
83 |
84 | $shaFile = Join-Path -Path $tempFolder -ChildPath 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt'
85 | $WebClient.DownloadFile($shaUrl, $shaFile)
86 |
87 | Get-Content $shaFile
88 | }
89 |
90 | $desktopAppInstaller = @{
91 | fileName = 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle'
92 | url = $(Get-LatestUrl)
93 | hash = $(Get-LatestHash)
94 | }
95 |
96 | $vcLibsUwp = @{
97 | fileName = 'Microsoft.VCLibs.x64.14.00.Desktop.appx'
98 | url = 'https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx'
99 | hash = '9BFDE6CFCC530EF073AB4BC9C4817575F63BE1251DD75AAA58CB89299697A569'
100 | }
101 | $uiLibsUwp = @{
102 | fileName = 'Microsoft.UI.Xaml.2.7.zip'
103 | url = 'https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.0'
104 | hash = '422FD24B231E87A842C4DAEABC6A335112E0D35B86FAC91F5CE7CF327E36A591'
105 | }
106 |
107 | $dependencies = @($desktopAppInstaller, $vcLibsUwp, $uiLibsUwp)
108 |
109 | Write-Host '--> Checking dependencies'
110 |
111 | foreach ($dependency in $dependencies) {
112 | $dependency.file = Join-Path -Path $tempFolder -ChildPath $dependency.fileName
113 | #$dependency.pathInSandbox = (Join-Path -Path $tempFolderName -ChildPath $dependency.fileName)
114 |
115 | # Only download if the file does not exist, or its hash does not match.
116 | if (-Not ((Test-Path -Path $dependency.file -PathType Leaf) -And $dependency.hash -eq $(Get-FileHash $dependency.file).Hash)) {
117 | Write-Host @"
118 | - Downloading:
119 | $($dependency.url)
120 | "@
121 |
122 | try {
123 | $WebClient.DownloadFile($dependency.url, $dependency.file)
124 | } catch {
125 | #Pass the exception as an inner exception
126 | throw [System.Net.WebException]::new("Error downloading $($dependency.url).", $_.Exception)
127 | }
128 | if (-not ($dependency.hash -eq $(Get-FileHash $dependency.file).Hash)) {
129 | throw [System.Activities.VersionMismatchException]::new('Dependency hash does not match the downloaded file')
130 | }
131 | }
132 | }
133 |
134 | # Extract Microsoft.UI.Xaml from zip (if freshly downloaded).
135 | # This is a workaround until https://github.com/microsoft/winget-cli/issues/1861 is resolved.
136 |
137 | if (-Not (Test-Path (Join-Path -Path $tempFolder -ChildPath \Microsoft.UI.Xaml.2.7\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx))) {
138 | Expand-Archive -Path $uiLibsUwp.file -DestinationPath ($tempFolder + '\Microsoft.UI.Xaml.2.7') -Force
139 | }
140 | $uiLibsUwp.file = (Join-Path -Path $tempFolder -ChildPath \Microsoft.UI.Xaml.2.7\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx)
141 | Add-AppxPackage -Path $($desktopAppInstaller.file) -DependencyPath $($vcLibsUwp.file),$($uiLibsUwp.file)
142 | # Clean up files
143 | Remove-Item $tempFolder -recurse -force
144 | '@
145 | if (!(test-path "$env:systemdrive\automation")) { mkdir "$env:systemdrive\automation" }
146 | $script | out-file "$env:systemdrive\automation\script.ps1"
147 | $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-executionpolicy bypass -WindowStyle minimized -file %HOMEDRIVE%\automation\script.ps1"
148 | $trigger = New-ScheduledTaskTrigger -AtLogOn
149 | $principal = New-ScheduledTaskPrincipal -UserId (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -expand UserName)
150 | $task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal
151 | Register-ScheduledTask RunScript -InputObject $task
152 | Start-ScheduledTask -TaskName RunScript
153 | Start-Sleep -Seconds 120
154 | Unregister-ScheduledTask -TaskName RunScript -Confirm:$false
155 | Remove-Item C:\automation\script.ps1
156 | }
157 |
158 |
159 | function Write-Log($message) #Log script messages to temp directory
160 | {
161 | $LogMessage = ((Get-Date -Format "MM-dd-yy HH:MM:ss ") + $message)
162 | Out-File -InputObject $LogMessage -FilePath "$LogPath\$LogFullName" -Append -Encoding utf8
163 | }
164 |
165 | #endregion
166 | #region pre-requsites
167 | $LogName = 'WinGetToolsInstall'
168 | $LogDate = Get-Date -Format dd-MM-yy_HH-mm # go with the EU format day / month / year
169 | $LogFullName = "$LogName-$LogDate.log"
170 | $LogPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs"
171 |
172 | $InstalledModules = Get-Module -ListAvailable
173 | $WinGetToolsInstalled = [bool]($InstalledModules | Where-Object name -EQ "WingetTools")
174 | $ThreadJobInstalled = [bool]($InstalledModules | Where-Object name -EQ "ThreadJob")
175 |
176 | if (-Not $WinGetToolsInstalled) { Install-WingetTools } # Install WingetTools if not available
177 |
178 | if (-Not $ThreadJobInstalled) # Install ThreadJob module if not installed
179 | {
180 | Install-PackageProvider Nuget -Force
181 | Set-PackageSource -Name PSGallery -Trusted
182 | Install-Module -Name threadjob
183 | }
184 |
185 | Set-ExecutionPolicy bypass -Scope Process -Force
186 | Import-Module WingetTools
187 | $WingetPath = Get-WGPath
188 | $VisualC = Get-RegUninstallKey -DisplayName "Microsoft Visual C++ 2015-2022 Redistributable (x64)"
189 | $loggedOnUser = (Get-CimInstance win32_computersystem).username
190 |
191 | # If Visual C++ Redist. not installed, install it
192 | if (!$VisualC)
193 | {
194 | Write-Log -message "Visual C++ X64 not found. Attempting to install"
195 | try
196 | {
197 | Install-VisualC
198 | }
199 | Catch [System.InvalidOperationException]{
200 | Write-Log -message "Error installing visual c++ redistributable. Attempting install once more"
201 | Start-Sleep -Seconds 5
202 | Install-VisualC
203 | }
204 | Catch
205 | {
206 | Write-Log -message "Failed to install visual c++ redistributable!"
207 | Write-Log -message $_
208 | exit 1
209 | }
210 | $VisualC = Get-RegUninstallKey -DisplayName "Microsoft Visual C++ 2015-2022 Redistributable (x64)"
211 | if (-Not $VisualC) { Write-Log -message "Visual C++ Redistributable not found!"; exit 1 }
212 | else { Write-Log -message "Successfully installed Microsoft Visual C++ 2015-2022 Redistributable (x64)" }
213 | }
214 |
215 | if (-Not $WingetPath)
216 | {
217 | if ($loggedOnUser)
218 | {
219 | Write-Log -message "Attempting to install Winget as System under $($loggedOnUser)"
220 | Install-WingetAsSystem
221 | # If more than one version of Winget, select the latest
222 | $WingetPath = Get-WGPath
223 | if ($WingetPath.count -gt 1) { $WingetPath = $Winget[-1] }
224 | if (-Not $WingetPath) { "Winget not found after attempting install as system. Exiting."; exit 1 }
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/Install-WingetTools_Detection.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 8/22/2022 10:14 AM
6 | Created by: David Just
7 | Organization:
8 | Filename:
9 | ===========================================================================
10 | .DESCRIPTION
11 | Detection script for Install-WingetTools
12 | #>
13 |
14 | $WingetTools = [bool](Get-Module -ListAvailable -Name WingetTools)
15 | if ($WingetTools)
16 | {
17 | "WingetTools is installed"
18 | exit 0
19 | }
20 | else
21 | {
22 | "WingetTools is not installed!"
23 | exit 1
24 | }
25 |
--------------------------------------------------------------------------------
/Invoke-ADCSCertMappingNDES.ps1:
--------------------------------------------------------------------------------
1 | #requires -module PSPKI
2 | # Sourced from https://system32.blog/post/adsmapcertificates/
3 | #region Static Definitions
4 | [string]$CertAuthority = "CA"
5 | [array]$CertTemplates = 'Template Name'
6 | [bool]$DryRun = $true
7 | [string]$NDESServiceAccount = ''
8 | [string]$Domain = ''
9 | #endregion
10 |
11 | #region Modules
12 | Import-Module -Name 'PSPKI'
13 | #endregion
14 |
15 | #region Functions
16 |
17 | # Thanks to Reddit / Github User xxdcmast for this function @xxdcmast, if you want me to remove this, let me know
18 | function Reverse-CertificateIssuer {
19 | [CmdletBinding()]
20 | Param(
21 | [Parameter(Position = 0, mandatory = $true)]
22 | [string] $CertIssuer)
23 |
24 | #Split the issuer DN into parts by comma
25 | $CertIssuernospaces = $CertIssuer -replace ',\s',','
26 | $splitresults =$CertIssuernospaces -split "," -ne ''
27 |
28 | #Reverse the DN to create the reverse issuer
29 | $reversed =$splitresults[-1.. - $splitresults.Length] -join ', '
30 |
31 | $reversed.trimstart()
32 |
33 | #end function
34 | }
35 | # Thanks to Reddit / Github User xxdcmast for this function @xxdcmast, if you want me to remove this, let me know
36 | function Reverse-CertificateSerialNumber {
37 | [CmdletBinding()]
38 | Param(
39 | [Parameter(Position=0,mandatory=$true)]
40 | [string] $CertSerialNumber)
41 |
42 | #Split the string into two characters to represent the byte encoding
43 | $splitresults = $CertSerialNumber -split '(..)' -ne ''
44 |
45 | #Take the byte split serial number and reverse the digits to get the correct cert formatting
46 | $splitresults[-1..-$splitresults.Length] -join ''
47 |
48 | #end function
49 | }
50 | #endregion
51 |
52 | #region Retrieve Data
53 | $CAs = @{}
54 |
55 | # Retrieve all Certificate Templates and their OIDs
56 | Write-Host("[$(Get-Date)] Retrieving Certificate templates..")
57 | $CertTemplateOIDs = $CertTemplates | ForEach-Object {
58 | (Get-CertificateTemplate -Name $_).oid.Value
59 | }
60 |
61 | # Retrieve all trusted domains
62 | Write-Host("[$(Get-Date)] Retrieving all trusted domains..")
63 | $Domains = @{}
64 |
65 | Get-ADTrust -Filter * | ForEach-Object {
66 | [string]$DC = (Get-ADDomainController -Discover -DomainName $_.target).hostname
67 | $ADDomain = Get-ADDomain -Server $DC
68 | $NETBIOS = $ADDomain.NetBIOSName
69 | $Domains.$NETBIOS = @{
70 | DomainController = $DC
71 | }
72 | }
73 | [string]$DC = (Get-ADDomainController -Discover).hostname
74 | $ADDomain = Get-ADDomain -Server $DC
75 | $NETBIOS = $ADDomain.NetBIOSName
76 | $Domains.$NETBIOS = @{
77 | DomainController = $DC
78 | IsLocal = $true
79 | }
80 | # Retrieve all certificates that match our template
81 | Write-Host("[$(Get-Date)] Retrieving Certificates..")
82 | $certs = Get-IssuedRequest -CertificationAuthority $CertAuthority -Filter "NotAfter -ge $(Get-Date)" | Where-Object {
83 | $_.CertificateTemplate -in $CertTemplateOIDs
84 | }
85 | #endregion
86 |
87 | #region Map certificates
88 | Write-Host("[$(Get-Date)] Processing Certificates..")
89 | foreach($cert in ($certs | where request.requestername -eq $NDESServiceAccount | sort requestid)){
90 | $requester = $cert.'CommonName'
91 | $CN = $requester
92 |
93 | # Check if we found this domain
94 | if(
95 | ($DomainEntry = $Domains.GetEnumerator() | Where-Object { $_.Name -eq $Domain })
96 | ){
97 | # Build AD Cmdlet Splatting
98 | $ADCmdletSplat = @{
99 | Server = $DomainEntry.Value.DomainController
100 | }
101 |
102 | # Check if this is the local domain, otherwise ask for credentials
103 | if(
104 | !($DomainEntry.Value.IsLocal) -and
105 | !($DomainEntry.Value.Credentials)
106 | ){
107 | $Domains.$Domain.Credentials = Get-Credential -Message "Please enter Credentials for Domain `"$Domain`"."
108 | $DomainEntry.Value.Credentials = $Domains.$Domain.Credentials
109 | }
110 |
111 | # Add the credential to the splatting if we have one
112 | if(!($DomainEntry.Value.IsLocal)){
113 | $ADCmdletSplat.Credential = $DomainEntry.Value.Credentials
114 | }
115 |
116 | # Retrieve AD Object
117 | if($ADObject = Get-ADObject -Filter { UserPrincipalName -eq $CN } -Properties 'altSecurityIdentities' -ErrorAction SilentlyContinue @ADCmdletSplat){
118 | if(!($CAs.$($cert.ConfigString))){
119 | $CAs.$($cert.ConfigString) = Get-CA -ErrorAction SilentlyContinue | Where-Object { $_.ConfigString -eq $cert.ConfigString }
120 | }
121 |
122 | # Build CA Cert Subject
123 | $CACertSubject = (Reverse-CertificateIssuer -CertIssuer $CAs.$($cert.ConfigString).Certificate.Subject).Replace(" ","")
124 |
125 | # Build Serial Numbers
126 | $CertForwardSN = $cert.SerialNumber
127 | $CertBackwardSN = (Reverse-CertificateSerialNumber -CertSerialNumber $CertForwardSN).ToUpper()
128 |
129 | # Build X509 Address
130 | $X509IssuerSerialNumber = "X509:$CACertSubject$CertBackwardSN"
131 |
132 | # Check if the attribute is already set, otherwise initialize array
133 | if(!($altIDs = $ADObject.'altSecurityIdentities')){
134 | $altIDs = @()
135 | }
136 |
137 | # Check if our X509IssuerSerialNumber is already in it
138 | if($X509IssuerSerialNumber -notin $altIDs){
139 |
140 | # It is not, add it
141 | Write-Host("[$($cert.RequestID) - $CN] Adding X509: `"$X509IssuerSerialNumber`"")
142 | $altIDs += $X509IssuerSerialNumber
143 |
144 | if(!$DryRun){
145 | # Write out the AD Object
146 | $ADObject | Set-ADObject -Replace @{
147 | 'altSecurityIdentities' = $altIDs
148 | } @ADCmdletSplat
149 | }
150 | }
151 | }else{
152 | Write-Host("[$($cert.RequestID) - $CN] AD Object not found.")
153 | }
154 | }
155 | }
156 | #endregion
157 |
158 |
--------------------------------------------------------------------------------
/PinToTaskbar.ps1:
--------------------------------------------------------------------------------
1 | # Pin to taskbar adapted from Pinto10 script https://pinto10blog.wordpress.com/2016/09/10/pinto10/
2 | function Pin-ToTaskbar {
3 | [CmdletBinding()]
4 | param (
5 | [string]$targetfile,
6 | [validateset('PIN','UNPIN')]
7 | [String]$Action
8 | )
9 |
10 |
11 | function Masquerade-PEB {
12 | <#
13 | .SYNOPSIS
14 | Masquerade-PEB uses NtQueryInformationProcess to get a handle to powershell's
15 | PEB. From there itreplaces a number of UNICODE_STRING structs in memory to
16 | give powershell the appearance of a different process. Specifically, the
17 | function will overwrite powershell's "ImagePathName" & "CommandLine" in
18 | _RTL_USER_PROCESS_PARAMETERS and the "FullDllName" & "BaseDllName" in the
19 | _LDR_DATA_TABLE_ENTRY linked list.
20 |
21 | This can be useful as it would fool any Windows work-flows which rely solely
22 | on the Process Status API to check process identity. A practical example would
23 | be the IFileOperation COM Object which can perform an elevated file copy if it
24 | thinks powershell is really explorer.exe ;)!
25 |
26 | Notes:
27 | * Works on x32/64.
28 |
29 | * Most of these API's and structs are undocumented. I strongly recommend
30 | @rwfpl's terminus project as a reference guide!
31 | + http://terminus.rewolf.pl/terminus/
32 |
33 | * Masquerade-PEB is basically a reimplementation of two functions in UACME
34 | by @hFireF0X. My code is quite different because, unfortunately, I don't
35 | have access to all those c++ goodies and I could not get a callback for
36 | LdrEnumerateLoadedModules working!
37 | + supMasqueradeProcess: https://github.com/hfiref0x/UACME/blob/master/Source/Akagi/sup.c#L504
38 | + supxLdrEnumModulesCallback: https://github.com/hfiref0x/UACME/blob/master/Source/Akagi/sup.c#L477
39 |
40 | .DESCRIPTION
41 | Author: Ruben Boonen (@FuzzySec)
42 | License: BSD 3-Clause
43 | Required Dependencies: None
44 | Optional Dependencies: None
45 |
46 | .EXAMPLE
47 | C:\PS> Masquerade-PEB -BinPath "C:\Windows\explorer.exe"
48 | #>
49 |
50 | param (
51 | [Parameter(Mandatory = $True)]
52 | [string]$BinPath
53 | )
54 |
55 | Add-Type -TypeDefinition @"
56 | using System;
57 | using System.Diagnostics;
58 | using System.Runtime.InteropServices;
59 | using System.Security.Principal;
60 |
61 | [StructLayout(LayoutKind.Sequential)]
62 | public struct UNICODE_STRING
63 | {
64 | public UInt16 Length;
65 | public UInt16 MaximumLength;
66 | public IntPtr Buffer;
67 | }
68 |
69 | [StructLayout(LayoutKind.Sequential)]
70 | public struct _LIST_ENTRY
71 | {
72 | public IntPtr Flink;
73 | public IntPtr Blink;
74 | }
75 |
76 | [StructLayout(LayoutKind.Sequential)]
77 | public struct _PROCESS_BASIC_INFORMATION
78 | {
79 | public IntPtr ExitStatus;
80 | public IntPtr PebBaseAddress;
81 | public IntPtr AffinityMask;
82 | public IntPtr BasePriority;
83 | public UIntPtr UniqueProcessId;
84 | public IntPtr InheritedFromUniqueProcessId;
85 | }
86 |
87 | /// Partial _PEB
88 | [StructLayout(LayoutKind.Explicit, Size = 64)]
89 | public struct _PEB
90 | {
91 | [FieldOffset(12)]
92 | public IntPtr Ldr32;
93 | [FieldOffset(16)]
94 | public IntPtr ProcessParameters32;
95 | [FieldOffset(24)]
96 | public IntPtr Ldr64;
97 | [FieldOffset(28)]
98 | public IntPtr FastPebLock32;
99 | [FieldOffset(32)]
100 | public IntPtr ProcessParameters64;
101 | [FieldOffset(56)]
102 | public IntPtr FastPebLock64;
103 | }
104 |
105 | /// Partial _PEB_LDR_DATA
106 | [StructLayout(LayoutKind.Sequential)]
107 | public struct _PEB_LDR_DATA
108 | {
109 | public UInt32 Length;
110 | public Byte Initialized;
111 | public IntPtr SsHandle;
112 | public _LIST_ENTRY InLoadOrderModuleList;
113 | public _LIST_ENTRY InMemoryOrderModuleList;
114 | public _LIST_ENTRY InInitializationOrderModuleList;
115 | public IntPtr EntryInProgress;
116 | }
117 |
118 | /// Partial _LDR_DATA_TABLE_ENTRY
119 | [StructLayout(LayoutKind.Sequential)]
120 | public struct _LDR_DATA_TABLE_ENTRY
121 | {
122 | public _LIST_ENTRY InLoadOrderLinks;
123 | public _LIST_ENTRY InMemoryOrderLinks;
124 | public _LIST_ENTRY InInitializationOrderLinks;
125 | public IntPtr DllBase;
126 | public IntPtr EntryPoint;
127 | public UInt32 SizeOfImage;
128 | public UNICODE_STRING FullDllName;
129 | public UNICODE_STRING BaseDllName;
130 | }
131 |
132 | public static class Kernel32
133 | {
134 | [DllImport("kernel32.dll")]
135 | public static extern UInt32 GetLastError();
136 |
137 | [DllImport("kernel32.dll")]
138 | public static extern Boolean VirtualProtectEx(
139 | IntPtr hProcess,
140 | IntPtr lpAddress,
141 | UInt32 dwSize,
142 | UInt32 flNewProtect,
143 | ref UInt32 lpflOldProtect);
144 |
145 | [DllImport("kernel32.dll")]
146 | public static extern Boolean WriteProcessMemory(
147 | IntPtr hProcess,
148 | IntPtr lpBaseAddress,
149 | IntPtr lpBuffer,
150 | UInt32 nSize,
151 | ref UInt32 lpNumberOfBytesWritten);
152 | }
153 |
154 | public static class Ntdll
155 | {
156 | [DllImport("ntdll.dll")]
157 | public static extern int NtQueryInformationProcess(
158 | IntPtr processHandle,
159 | int processInformationClass,
160 | ref _PROCESS_BASIC_INFORMATION processInformation,
161 | int processInformationLength,
162 | ref int returnLength);
163 |
164 | [DllImport("ntdll.dll")]
165 | public static extern void RtlEnterCriticalSection(
166 | IntPtr lpCriticalSection);
167 |
168 | [DllImport("ntdll.dll")]
169 | public static extern void RtlLeaveCriticalSection(
170 | IntPtr lpCriticalSection);
171 | }
172 | "@
173 |
174 | # Flag architecture $x32Architecture/!$x32Architecture
175 | if ([System.IntPtr]::Size -eq 4) {
176 | $x32Architecture = 1
177 | }
178 |
179 | # Current Proc handle
180 | $ProcHandle = (Get-Process -Id ([System.Diagnostics.Process]::GetCurrentProcess().Id)).Handle
181 |
182 | # Helper function to overwrite UNICODE_STRING structs in memory
183 | function Emit-UNICODE_STRING {
184 | param(
185 | [IntPtr]$hProcess,
186 | [IntPtr]$lpBaseAddress,
187 | [UInt32]$dwSize,
188 | [String]$data
189 | )
190 |
191 | # Set access protections -> PAGE_EXECUTE_READWRITE
192 | [UInt32]$lpflOldProtect = 0
193 | $CallResult = [Kernel32]::VirtualProtectEx($hProcess, $lpBaseAddress, $dwSize, 0x40, [ref]$lpflOldProtect)
194 |
195 | # Create replacement struct
196 | $UnicodeObject = New-Object UNICODE_STRING
197 | $UnicodeObject_Buffer = $data
198 | [UInt16]$UnicodeObject.Length = $UnicodeObject_Buffer.Length*2
199 | [UInt16]$UnicodeObject.MaximumLength = $UnicodeObject.Length+1
200 | [IntPtr]$UnicodeObject.Buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($UnicodeObject_Buffer)
201 | [IntPtr]$InMemoryStruct = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($dwSize)
202 | [system.runtime.interopservices.marshal]::StructureToPtr($UnicodeObject, $InMemoryStruct, $true)
203 |
204 | # Overwrite PEB UNICODE_STRING struct
205 | [UInt32]$lpNumberOfBytesWritten = 0
206 | $CallResult = [Kernel32]::WriteProcessMemory($hProcess, $lpBaseAddress, $InMemoryStruct, $dwSize, [ref]$lpNumberOfBytesWritten)
207 |
208 | # Free $InMemoryStruct
209 | [System.Runtime.InteropServices.Marshal]::FreeHGlobal($InMemoryStruct)
210 | }
211 |
212 | # Process Basic Information
213 | $PROCESS_BASIC_INFORMATION = New-Object _PROCESS_BASIC_INFORMATION
214 | $PROCESS_BASIC_INFORMATION_Size = [System.Runtime.InteropServices.Marshal]::SizeOf($PROCESS_BASIC_INFORMATION)
215 | $returnLength = New-Object Int
216 | $CallResult = [Ntdll]::NtQueryInformationProcess($ProcHandle, 0, [ref]$PROCESS_BASIC_INFORMATION, $PROCESS_BASIC_INFORMATION_Size, [ref]$returnLength)
217 |
218 | # PID & PEB address
219 | # echo "`n[?] PID $($PROCESS_BASIC_INFORMATION.UniqueProcessId)"
220 | if ($x32Architecture) {
221 | # echo "[+] PebBaseAddress: 0x$("{0:X8}" -f $PROCESS_BASIC_INFORMATION.PebBaseAddress.ToInt32())"
222 | } else {
223 | # echo "[+] PebBaseAddress: 0x$("{0:X16}" -f $PROCESS_BASIC_INFORMATION.PebBaseAddress.ToInt64())"
224 | }
225 |
226 | # Lazy PEB parsing
227 | $_PEB = New-Object _PEB
228 | $_PEB = $_PEB.GetType()
229 | $BufferOffset = $PROCESS_BASIC_INFORMATION.PebBaseAddress.ToInt64()
230 | $NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
231 | $PEBFlags = [system.runtime.interopservices.marshal]::PtrToStructure($NewIntPtr, [type]$_PEB)
232 |
233 | # Take ownership of PEB
234 | # Not sure this is strictly necessary but why not!
235 | if ($x32Architecture) {
236 | [Ntdll]::RtlEnterCriticalSection($PEBFlags.FastPebLock32)
237 | } else {
238 | [Ntdll]::RtlEnterCriticalSection($PEBFlags.FastPebLock64)
239 | } # echo "[!] RtlEnterCriticalSection --> &Peb->FastPebLock"
240 |
241 | # &Peb->ProcessParameters->ImagePathName/CommandLine
242 | if ($x32Architecture) {
243 | # Offset to &Peb->ProcessParameters
244 | $PROCESS_PARAMETERS = $PEBFlags.ProcessParameters32.ToInt64()
245 | # x86 UNICODE_STRING struct's --> Size 8-bytes = (UInt16*2)+IntPtr
246 | [UInt32]$StructSize = 8
247 | $ImagePathName = $PROCESS_PARAMETERS + 0x38
248 | $CommandLine = $PROCESS_PARAMETERS + 0x40
249 | } else {
250 | # Offset to &Peb->ProcessParameters
251 | $PROCESS_PARAMETERS = $PEBFlags.ProcessParameters64.ToInt64()
252 | # x64 UNICODE_STRING struct's --> Size 16-bytes = (UInt16*2)+IntPtr
253 | [UInt32]$StructSize = 16
254 | $ImagePathName = $PROCESS_PARAMETERS + 0x60
255 | $CommandLine = $PROCESS_PARAMETERS + 0x70
256 | }
257 |
258 | # Overwrite PEB struct
259 | # Can easily be extended to other UNICODE_STRING structs in _RTL_USER_PROCESS_PARAMETERS(/or in general)
260 | $ImagePathNamePtr = New-Object System.Intptr -ArgumentList $ImagePathName
261 | $CommandLinePtr = New-Object System.Intptr -ArgumentList $CommandLine
262 | if ($x32Architecture) {
263 | # echo "[>] Overwriting &Peb->ProcessParameters.ImagePathName: 0x$("{0:X8}" -f $ImagePathName)"
264 | # echo "[>] Overwriting &Peb->ProcessParameters.CommandLine: 0x$("{0:X8}" -f $CommandLine)"
265 | } else {
266 | # echo "[>] Overwriting &Peb->ProcessParameters.ImagePathName: 0x$("{0:X16}" -f $ImagePathName)"
267 | # echo "[>] Overwriting &Peb->ProcessParameters.CommandLine: 0x$("{0:X16}" -f $CommandLine)"
268 | }
269 | Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $ImagePathNamePtr -dwSize $StructSize -data $BinPath
270 | Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $CommandLinePtr -dwSize $StructSize -data $BinPath
271 |
272 | # &Peb->Ldr
273 | $_PEB_LDR_DATA = New-Object _PEB_LDR_DATA
274 | $_PEB_LDR_DATA = $_PEB_LDR_DATA.GetType()
275 | if ($x32Architecture) {
276 | $BufferOffset = $PEBFlags.Ldr32.ToInt64()
277 | } else {
278 | $BufferOffset = $PEBFlags.Ldr64.ToInt64()
279 | }
280 | $NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
281 | $LDRFlags = [system.runtime.interopservices.marshal]::PtrToStructure($NewIntPtr, [type]$_PEB_LDR_DATA)
282 |
283 | # &Peb->Ldr->InLoadOrderModuleList->Flink
284 | $_LDR_DATA_TABLE_ENTRY = New-Object _LDR_DATA_TABLE_ENTRY
285 | $_LDR_DATA_TABLE_ENTRY = $_LDR_DATA_TABLE_ENTRY.GetType()
286 | $BufferOffset = $LDRFlags.InLoadOrderModuleList.Flink.ToInt64()
287 | $NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
288 |
289 | # Traverse doubly linked list
290 | # &Peb->Ldr->InLoadOrderModuleList->InLoadOrderLinks->Flink
291 | # This is probably overkill, powershell.exe should always be the first entry for InLoadOrderLinks
292 | # echo "[?] Traversing &Peb->Ldr->InLoadOrderModuleList doubly linked list"
293 | while ($ListIndex -ne $LDRFlags.InLoadOrderModuleList.Blink) {
294 | $LDREntry = [system.runtime.interopservices.marshal]::PtrToStructure($NewIntPtr, [type]$_LDR_DATA_TABLE_ENTRY)
295 |
296 | if ([System.Runtime.InteropServices.Marshal]::PtrToStringUni($LDREntry.FullDllName.Buffer) -like "*powershell.exe*") {
297 |
298 | if ($x32Architecture) {
299 | # x86 UNICODE_STRING struct's --> Size 8-bytes = (UInt16*2)+IntPtr
300 | [UInt32]$StructSize = 8
301 | $FullDllName = $BufferOffset + 0x24
302 | $BaseDllName = $BufferOffset + 0x2C
303 | } else {
304 | # x64 UNICODE_STRING struct's --> Size 16-bytes = (UInt16*2)+IntPtr
305 | [UInt32]$StructSize = 16
306 | $FullDllName = $BufferOffset + 0x48
307 | $BaseDllName = $BufferOffset + 0x58
308 | }
309 |
310 | # Overwrite _LDR_DATA_TABLE_ENTRY struct
311 | # Can easily be extended to other UNICODE_STRING structs in _LDR_DATA_TABLE_ENTRY(/or in general)
312 | $FullDllNamePtr = New-Object System.Intptr -ArgumentList $FullDllName
313 | $BaseDllNamePtr = New-Object System.Intptr -ArgumentList $BaseDllName
314 | if ($x32Architecture) {
315 | # echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.FullDllName: 0x$("{0:X8}" -f $FullDllName)"
316 | # echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.BaseDllName: 0x$("{0:X8}" -f $BaseDllName)"
317 | } else {
318 | # echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.FullDllName: 0x$("{0:X16}" -f $FullDllName)"
319 | # echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.BaseDllName: 0x$("{0:X16}" -f $BaseDllName)"
320 | }
321 | Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $FullDllNamePtr -dwSize $StructSize -data $BinPath
322 | Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $BaseDllNamePtr -dwSize $StructSize -data $BinPath
323 | }
324 |
325 | $ListIndex = $BufferOffset = $LDREntry.InLoadOrderLinks.Flink.ToInt64()
326 | $NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
327 | }
328 |
329 | # Release ownership of PEB
330 | if ($x32Architecture) {
331 | [Ntdll]::RtlLeaveCriticalSection($PEBFlags.FastPebLock32)
332 | } else {
333 | [Ntdll]::RtlLeaveCriticalSection($PEBFlags.FastPebLock64)
334 | } # echo "[!] RtlLeaveCriticalSection --> &Peb->FastPebLock`n"
335 | }
336 |
337 | # Check all the variables are correct before starting
338 | if (!(Test-Path "$TargetFile")){
339 | write-host "File not found. Exiting..."`r`n
340 | Break
341 | }
342 |
343 | # Set the arguments to the required verb actions
344 | if ($Action -eq "PIN"){$PinUnpin = "taskbarpin"}
345 | if ($Action -eq "UNPIN"){$PinUnpin = "taskbarunpin"}
346 |
347 | # Split the target path to folder, filename and filename with no extension
348 | $FileNameNoExt = (Get-ChildItem $TargetFile).BaseName
349 | $FileNameWithExt = (Get-ChildItem $TargetFile).Name
350 | $Directory = (Get-Childitem $TargetFile).Directory
351 |
352 | # Hide Powershell as Explorer...
353 | Masquerade-PEB -BinPath "C:\Windows\explorer.exe"
354 |
355 | # If target file is not a .lnk then create a shortcut, (un)pin that and then delete it
356 | if ((Get-ChildItem $TargetFile).Extension -ne ".lnk"){
357 |
358 | if (test-path "$env:TEMP\$FileNameNoExt.lnk"){Remove-Item -path "$env:TEMP\$FileNameNoExt.lnk"}
359 |
360 | $WshShell = New-Object -comObject WScript.Shell
361 | $Shortcut = $WshShell.CreateShortcut("$env:TEMP\$FileNameNoExt.lnk")
362 | $Shortcut.TargetPath = $TargetFile
363 | $Shortcut.Save()
364 |
365 | $TargetFile = "$env:TEMP\$FileNameNoExt.lnk"
366 | $FileNameWithExt = (Get-ChildItem $TargetFile).Name
367 | $Directory = (Get-Childitem $TargetFile).Directory
368 |
369 | (New-Object -ComObject shell.application).Namespace("$Directory\").parsename("$FileNameWithExt").invokeverb("$PinUnpin")
370 |
371 | if (test-path "$env:TEMP\$FileNameNoExt.lnk"){Remove-Item -path "$env:TEMP\$FileNameNoExt.lnk"}
372 |
373 | } else {
374 | (New-Object -ComObject shell.application).Namespace("$Directory\").parsename("$FileNameWithExt").invokeverb("$PinUnpin")
375 | }
376 |
377 | }
378 |
379 | function UnPin-AppFromTaskBar {
380 | param (
381 | $AppName
382 | )
383 | $Apps = (New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items()
384 | ($Apps | where name -like "$AppName").invokeverb("taskbarunpin")
385 | }
386 | #Examples:
387 | # Unpin Mail App and Windows Store
388 | UnPin-AppFromTaskBar -AppName "Microsoft Store" -Verb taskbarunpin
389 | UnPin-AppFromTaskBar -AppName Mail -Verb taskbarunpin
390 | # Pin Chrome and Office Apps to taskbar
391 | $StartMenuFolder = "$env:programdata\Microsoft\Windows\Start Menu\Programs"
392 | Pin-ToTaskbar -targetfile "$StartMenuFolder\Google Chrome.lnk" -Action pin
393 | Pin-ToTaskbar -targetfile "$StartMenuFolder\Excel.lnk" -Action pin
394 | Pin-ToTaskbar -targetfile "$StartMenuFolder\Word.lnk" -Action pin
395 | Pin-ToTaskbar -targetfile "$StartMenuFolder\Outlook.lnk" -Action pin
396 | Pin-ToTaskbar -targetfile "$StartMenuFolder\Firefox.lnk" -Action pin
397 |
398 |
399 |
--------------------------------------------------------------------------------
/Remove-LocalAdminPrivelageDETECTION.ps1:
--------------------------------------------------------------------------------
1 | # Proactive remediation detection script to determine if user is a local Administrator
2 | $group =[ADSI]"WinNT://$($env:COMPUTERNAME)/Administrators"
3 | $admins = @($group.Invoke("Members")) | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
4 | $user = ((gcim win32_computersystem).username -split '\\')[1]
5 | if ($admins -like $user)
6 | {
7 | Write-Host "User is Admin"
8 | exit 1
9 | }
10 | else
11 | {
12 | Write-Host "User is not Admin"
13 | exit 0
14 | }
--------------------------------------------------------------------------------
/Remove-LocalAdminPrivelageREMEDIATION.ps1:
--------------------------------------------------------------------------------
1 | $group =[ADSI]"WinNT://$($env:COMPUTERNAME)/Administrators"
2 | $admins = @($group.Invoke("Members")) | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
3 | $user = ((gcim win32_computersystem).username -split '\\')[1]
4 | Net Localgroup Administrators /delete (gcim win32_computersystem).username
5 |
6 | $adminspost = @($group.Invoke("Members")) | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
7 | if ($adminspost -like $user)
8 | {
9 | Write-Host "User is Admin"
10 | exit 1
11 | }
12 | else
13 | {
14 | Write-Host "User is not Admin"
15 | exit 0
16 | }
--------------------------------------------------------------------------------
/RemoveDuplicatedShortcuts_plustask.ps1:
--------------------------------------------------------------------------------
1 | #If you are enforcing One Drive Known File Move, redirecting the Desktop, its possible some shortcuts may be duplicated
2 | #between the time the computer enrolls in intune and one drive redirects the desktop. This script will create a
3 | #scheduled task to clear up and remove duplicated shortcuts if they exist at logon.
4 | #Just add in the shortcut name and your companies One Drive path.
5 |
6 | $dupe = '$UserSID = (New-Object -ComObject Microsoft.DiskQuota).TranslateLogonNameToSID((Get-WmiObject -Class Win32_ComputerSystem).Username)
7 | $Path = "HKLM\SOFTWARE\Microsoft\WIndows NT\CurrentVersion\Profilelist\$UserSID"
8 | $UserPath = Get-ItemProperty "Registry::$path" -name "ProfileImagePath" | select -ExpandProperty ProfileImagePath
9 |
10 |
11 | $duplicateshortcuts = "shortcut1.lnk","shortcut2.lnk","shortcut3.lnk" | foreach {test-path "$UserPath\OneDrive - YourCompany\Desktop\$_."}
12 | if ($duplicateshortcuts -eq $true)
13 | {
14 | $OldShortcuts = @("$UserPath\OneDrive - YourCompany\Desktop\shortcut1.lnk","$UserPath\OneDrive - YourCompany\Desktop\shortcut1.lnk.lnk","$UserPath\OneDrive - YourCompany\Desktop\shortcut3.lnk","$UserPath\OneDrive - YourCompany\Desktop\Microsoft Edge - Copy.lnk")
15 | Get-ChildItem $OldShortcuts | Remove-Item
16 | }'
17 |
18 | new-item c:\automation -ItemType directory -force
19 | set-content c:\automation\removedupshortcut.ps1 $dupe
20 |
21 | if( -Not (Get-ScheduledTask -TaskName "Remove Duplicate Shortcuts" -ErrorAction SilentlyContinue -OutVariable task) )
22 | {
23 | $Params = @{
24 | Action = (New-ScheduledTaskAction -Execute 'powershell' -Argument '-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass C:\Automation\removedupshortcut.ps1')
25 | Trigger = (New-ScheduledTaskTrigger -AtLogOn)
26 | Principal = (New-ScheduledTaskPrincipal -GroupId "System")
27 | TaskName = 'Remove Duplicate Shortcuts'
28 | Description = 'Remove Duplicate Shortcuts'
29 | }
30 | Register-ScheduledTask @Params
31 | Start-ScheduledTask -TaskName "Remove Duplicate Shortcuts"
32 | }
33 | else
34 | {
35 | Start-ScheduledTask -TaskName "Remove Duplicate Shortcuts"
36 | }
37 |
--------------------------------------------------------------------------------
/Volume_Shadow_Copy_Task.ps1:
--------------------------------------------------------------------------------
1 | ############## Set 3 daily Volume Shadow Copy Tasks #####################
2 |
3 | if( -Not (Get-ScheduledTask -TaskName "Volume Shadow Copy C" -ErrorAction SilentlyContinue -OutVariable task) )
4 | {
5 | $Params = @{
6 | Action = (New-ScheduledTaskAction -Execute 'cmd' -Argument '/c /c "wmic shadowcopy call create Volume=c:\" ')
7 | Trigger = (New-ScheduledTaskTrigger -Daily -At 8am)
8 | Principal = (New-ScheduledTaskPrincipal -GroupId "System")
9 | TaskName = 'Volume Shadow Copy C'
10 | Description = 'Volume Shadow Copy C'
11 | }
12 | Register-ScheduledTask @Params
13 | Start-ScheduledTask -TaskName "Volume Shadow Copy C"
14 | }
15 | else
16 | {
17 | Start-ScheduledTask -TaskName "Volume Shadow Copy C"
18 | }
19 |
20 | if( -Not (Get-ScheduledTask -TaskName "Volume Shadow Copy C 2" -ErrorAction SilentlyContinue -OutVariable task) )
21 | {
22 | $Params = @{
23 | Action = (New-ScheduledTaskAction -Execute 'cmd' -Argument '/c /c "wmic shadowcopy call create Volume=c:\" ')
24 | Trigger = (New-ScheduledTaskTrigger -Daily -At 1PM)
25 | Principal = (New-ScheduledTaskPrincipal -GroupId "System")
26 | TaskName = 'Volume Shadow Copy C 2'
27 | Description = 'Volume Shadow Copy C 2'
28 | }
29 | Register-ScheduledTask @Params
30 | }
31 |
32 | if( -Not (Get-ScheduledTask -TaskName "Volume Shadow Copy C 3" -ErrorAction SilentlyContinue -OutVariable task) )
33 | {
34 | $Params = @{
35 | Action = (New-ScheduledTaskAction -Execute 'cmd' -Argument '/c /c "wmic shadowcopy call create Volume=c:\" ')
36 | Trigger = (New-ScheduledTaskTrigger -Daily -At 6PM)
37 | Principal = (New-ScheduledTaskPrincipal -GroupId "System")
38 | TaskName = 'Volume Shadow Copy C 3'
39 | Description = 'Volume Shadow Copy C 3'
40 | }
41 | Register-ScheduledTask @Params
42 | }
43 |
44 | ######## Set Max Shadow Copies
45 |
46 | New-ItemProperty registry::HKLM\System\CurrentControlSet\Services\VSS\Settings -Name MaxShadowCopies -PropertyType DWORD -Value 16
47 |
48 | ############# Resize Shadow Storage max size
49 | vssadmin resize shadowstorage /for=C: /maxsize=5GB
--------------------------------------------------------------------------------
/Winget-InstallDetection.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 3/7/2022 2:14 PM
6 | Created by: Dave Just
7 | Organization:
8 | Filename: WingetInstallDetection.ps1
9 | ===========================================================================
10 | .DESCRIPTION
11 | Simple Win32App detection script. Detects the presence of an uninstall key matching the displayname of the variable $SoftwareName.
12 | If a key is matched, return to Intune that the software is installed.
13 | .EXAMPLE
14 | $SoftwareName = 'Chrome' # Search for an uninstall key with Displayname 'Chrome' for Google Chrome
15 | #>
16 | # Edit the software displayname below
17 |
18 | $SoftwareName = ''
19 |
20 | function Get-RegUninstallKey
21 | {
22 | param (
23 | [string]$DisplayName
24 | )
25 | $uninstallKeys = @(
26 | "registry::HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
27 | "registry::HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
28 | )
29 | $LoggedOnUser = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
30 | if ($LoggedOnUser){
31 | $UserSID = ([System.Security.Principal.NTAccount](Get-CimInstance -ClassName Win32_ComputerSystem).UserName).Translate([System.Security.Principal.SecurityIdentifier]).Value
32 | $UninstallKeys += @("registry::HKU\$UserSID\Software\Microsoft\Windows\CurrentVersion\Uninstall" , "registry::HKU\$UserSID\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
33 | }
34 | $softwareTable =@()
35 | foreach ($key in $uninstallKeys){
36 | if (-Not (Test-Path $Key)){
37 | Write-Warning "$Key not found"
38 | continue
39 | }
40 | $softwareTable += Get-Childitem $key |
41 | foreach {
42 | try {
43 | Get-ItemProperty $_.pspath | Where-Object { $_.displayname } | Sort-Object -Property displayname
44 | }
45 | catch [System.InvalidCastException] {
46 | # Ignore error as I was occasionally getting an invalid cast error on Get-ItemProperty
47 | }
48 | }
49 | }
50 | if ($DisplayName)
51 | {
52 | $softwareTable | Where-Object { $_.displayname -Like "*$DisplayName*" }
53 | }
54 | else
55 | {
56 | $softwareTable | Sort-Object -Property displayname -Unique
57 | }
58 |
59 | }
60 |
61 | $UninstallKey = Get-RegUninstallKey -DisplayName $SoftwareName
62 | if ($UninstallKey)
63 | {
64 | Write-Output "$($SoftwareName) is installed"
65 | exit 0
66 | }
67 | else
68 | {
69 | exit 1
70 | }
71 |
--------------------------------------------------------------------------------
/Winget-InstallPackage.intunewin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djust270/Intune-Scripts/62f388a7c8116c4f8c975bcd27d6e883c60e75c5/Winget-InstallPackage.intunewin
--------------------------------------------------------------------------------
/Winget-InstallPackage.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 3/7/2022 2:14 PM
6 | Created by: Dave Just
7 | Organization:
8 | Filename: Winget-InstallPackage.ps1
9 |
10 | Updated 07/15/2024 to support uninstallation, also handle scenario when WinGet is not installed
11 | but package installation is requested during autopilot / oobe without a user account. Moved log location
12 | to %programdata%\Microsoft\IntuneManagementExtension\Logs
13 |
14 | Updated 08/12/2024 to download and extract DesktopAppInstaller msixbundle to %ProgramData% if WinGet is not installed
15 | This allows WinGet to function in SYSTEM context during OOBE/Autopilot when installation under user context is not possbile.
16 | ===========================================================================
17 | .DESCRIPTION
18 | Installs any package within the WinGet public repository running as SYSTEM. Can be packaged and deployed as a Win32App in Intune
19 | Use as base for any install with WinGet. Simply specify the PackageID and log variables.
20 |
21 | If WinGet is not currently installed, a zipped copy will be extracted to the %PrograData% folder as installation in user context during OOBE/Autopilot was un-reliable.
22 | .PARAMETER PackageID
23 | Specify the WinGet ID. Use WinGet Search "SoftwareName" to locate the PackageID
24 | .PARAMETER PackageName
25 | Specify the Package Name in place of PackageID if preferred.
26 | .PARAMETER Mode
27 | Required parameter. Specify 'install' or 'uninstall' to perform that operation for the given package.
28 | .PARAMETER Log
29 | Required parameter. Specify the log file name. This will be logged to %programdata%\Microsoft\IntuneManagementExtension\Logs"
30 | .PARAMETER AdditionalInstallArgs
31 | Specify Additional Installation Arguments to pass to WinGet https://learn.microsoft.com/en-us/windows/package-manager/winget/install
32 | .EXAMPLE
33 | powershell.exe -executionpolicy bypass -file Winget-InstallPackage.ps1 -PackageID "Google.Chrome" -Log "ChromeWingetInstall.log"
34 | .EXAMPLE
35 | powershell.exe -executionpolicy bypass -file Winget-InstallPackage.ps1 -mode install -PackageID "Notepad++.Notepad++" -Log "NotepadPlusPlus.log"
36 | .EXAMPLE
37 | powershell.exe -executionpolicy bypass -file Winget-InstallPackage.ps1 -PackageID "Python.Python.3.11" -mode uninstall -Log "Python3Install.log" -AdditionalInstallArgs "--architecture x64"
38 | .EXAMPLE
39 | powershell.exe -executionpolicy bypass -file Winget-InstallPackage.ps1 -PackageName "Microsoft .NET Runtime 6.0" -mode install -Log "DotNetRuntime6.log"
40 | #>
41 |
42 | <#
43 | TODO:
44 | Add function to download zipped WinGet copy from blob storage in the event that WinGet is not installed
45 | Extract to %ProgramData% folder
46 | #>
47 | param (
48 | [string]$PackageID = 'Notepad++.Notepad++',
49 |
50 | [string]$PackageName,
51 |
52 | [string]$AdditionalInstallArgs,
53 |
54 | [parameter()]
55 | [ValidateSet('Install','Uninstall')]
56 | # Set default mode to install
57 | [string]$Mode = 'Install',
58 |
59 | [parameter(Mandatory)]
60 | [string]$Log
61 | )
62 |
63 | # Re-launch as 64bit process (source: https://z-nerd.com/blog/2020/03/31-intune-win32-apps-powershell-script-installer/)
64 | $argsString = ""
65 | If ($ENV:PROCESSOR_ARCHITEW6432 -eq "AMD64")
66 | {
67 | Try
68 | {
69 | foreach ($k in $MyInvocation.BoundParameters.keys)
70 | {
71 | switch ($MyInvocation.BoundParameters[$k].GetType().Name)
72 | {
73 | "SwitchParameter" { if ($MyInvocation.BoundParameters[$k].IsPresent) { $argsString += "-$k " } }
74 | "String" { $argsString += "-$k `"$($MyInvocation.BoundParameters[$k])`" " }
75 | "Int32" { $argsString += "-$k $($MyInvocation.BoundParameters[$k]) " }
76 | "Boolean" { $argsString += "-$k `$$($MyInvocation.BoundParameters[$k]) " }
77 | }
78 | }
79 | Start-Process -FilePath "$ENV:WINDIR\SysNative\WindowsPowershell\v1.0\PowerShell.exe" -ArgumentList "-File `"$($PSScriptRoot)\Winget-InstallPackage.ps1`" $($argsString)" -Wait -NoNewWindow
80 | }
81 | Catch
82 | {
83 | Throw "Failed to start 64-bit PowerShell"
84 | }
85 | Exit
86 | }
87 |
88 | #region HelperFunctions
89 |
90 | function Write-Log($message) #Log script messages to temp directory
91 | {
92 | $LogMessage = ((Get-Date -Format "MM-dd-yy HH:MM:ss ") + $message)
93 | if (Test-Path "$env:programdata\Microsoft\IntuneManagementExtension\Logs") {
94 | Out-File -InputObject $LogMessage -FilePath "$env:programdata\Microsoft\IntuneManagementExtension\Logs\$Log" -Append -Encoding utf8
95 | }
96 | Write-Host $message
97 | }
98 |
99 | function Download-Winget {
100 | <#
101 | .SYNOPSIS
102 | Download Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle and extract contents with 7zip cli to %ProgramData%
103 | #>
104 | $ProgressPreference = 'SilentlyContinue'
105 | $7zipFolder = "${env:WinDir}\Temp\7zip"
106 | try {
107 | Write-Log "Downloading WinGet..."
108 | # Create staging folder
109 | New-Item -ItemType Directory -Path "${env:WinDir}\Temp\WinGet-Stage" -Force
110 | # Download Desktop App Installer msixbundle
111 | Invoke-WebRequest -UseBasicParsing -Uri https://aka.ms/getwinget -OutFile "${env:WinDir}\Temp\WinGet-Stage\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
112 | }
113 | catch {
114 | Write-Log "Failed to download WinGet!"
115 | Write-Log $_.Exception.Message
116 | return
117 | }
118 | try {
119 | Write-Log "Downloading 7zip CLI executable..."
120 | # Create temp 7zip CLI folder
121 | New-Item -ItemType Directory -Path $7zipFolder -Force
122 | Invoke-WebRequest -UseBasicParsing -Uri https://www.7-zip.org/a/7zr.exe -OutFile "$7zipFolder\7zr.exe"
123 | Invoke-WebRequest -UseBasicParsing -Uri https://www.7-zip.org/a/7z2408-extra.7z -OutFile "$7zipFolder\7zr-extra.7z"
124 | Write-Log "Extracting 7zip CLI executable to ${7zipFolder}..."
125 | & "$7zipFolder\7zr.exe" x "$7zipFolder\7zr-extra.7z" -o"$7zipFolder" -y
126 | }
127 | catch {
128 | Write-Log "Failed to download 7zip CLI executable!"
129 | Write-Log $_.Exception.Message
130 | return
131 | }
132 | try {
133 | # Create Folder for DesktopAppInstaller inside %ProgramData%
134 | New-Item -ItemType Directory -Path "${env:ProgramData}\Microsoft.DesktopAppInstaller" -Force
135 | Write-Log "Extracting WinGet..."
136 | & "$7zipFolder\7za.exe" x "${env:WinDir}\Temp\WinGet-Stage\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -o"${env:WinDir}\Temp\WinGet-Stage" -y
137 | & "$7zipFolder\7za.exe" x "${env:WinDir}\Temp\WinGet-Stage\AppInstaller_x64.msix" -o"${env:ProgramData}\Microsoft.DesktopAppInstaller" -y
138 | }
139 | catch {
140 | Write-Log "Failed to extract WinGet!"
141 | Write-Log $_.Exception.Message
142 | return
143 | }
144 | if (-Not (Test-Path "${env:ProgramData}\Microsoft.DesktopAppInstaller\WinGet.exe")){
145 | Write-Log "Failed to extract WinGet!"
146 | exit 1
147 | }
148 | $Script:WinGet = "${env:ProgramData}\Microsoft.DesktopAppInstaller\WinGet.exe"
149 | }
150 |
151 | function Install-VisualC {
152 | try {
153 | $downloadurl = 'https://aka.ms/vs/17/release/vc_redist.x64.exe'
154 | $WebClient = New-Object System.Net.WebClient
155 | $WebClient.DownloadFile($downloadurl, "$env:Temp\vc_redist.x64.exe")
156 | $WebClient.Dispose()
157 | }
158 | catch {
159 | Write-Log "Failed to download Visual C++!"
160 | Write-Log $_.Exception.Message
161 | }
162 | # Check if another installation is in progress, then wait for it to complete
163 | $MSIExecCheck = Get-Process | Where-Object {$_.processname -eq 'msiexec'}
164 | if ($Null -ne $MSIExecCheck){
165 | Write-Log "another msi installation is in progress. Waiting for process to complete..."
166 | Wait-Process msiexec
167 | Write-Log "Continuing installation..."
168 | }
169 | try {
170 | $Install = start-process "$env:temp\vc_redist.x64.exe" -argumentlist "/q /norestart" -Wait -PassThru
171 | Write-Log "Installation completed with exit code $($Install.ExitCode)"
172 | return $Install.ExitCode
173 | }
174 | catch {
175 | Write-Log $_.Exception.Message
176 | }
177 | try {
178 | remove-item "$env:Temp\vc_redist.x64.exe"
179 | }
180 | catch {
181 | Write-Log "Failed to remove vc_redist.x64.exe after installation"
182 | }
183 | }
184 |
185 | function Get-RegUninstallKey
186 | {
187 | param (
188 | [string]$DisplayName
189 | )
190 | $uninstallKeys = @(
191 | "registry::HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
192 | "registry::HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
193 | )
194 | $LoggedOnUser = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
195 | if ($LoggedOnUser){
196 | $UserSID = ([System.Security.Principal.NTAccount](Get-CimInstance -ClassName Win32_ComputerSystem).UserName).Translate([System.Security.Principal.SecurityIdentifier]).Value
197 | $UninstallKeys += @("registry::HKU\$UserSID\Software\Microsoft\Windows\CurrentVersion\Uninstall" , "registry::HKU\$UserSID\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
198 | }
199 | $softwareTable =@()
200 | foreach ($key in $uninstallKeys){
201 | if (-Not (Test-Path $Key)){
202 | Write-Warning "$Key not found"
203 | continue
204 | }
205 | $softwareTable += Get-Childitem $key |
206 | ForEach-Object {
207 | try {
208 | Get-ItemProperty $_.pspath | Where-Object { $_.displayname } | Sort-Object -Property displayname
209 | }
210 | catch [System.InvalidCastException] {
211 | # Ignore error as I was occasionally getting an invalid cast error on Get-ItemProperty
212 | }
213 | }
214 | }
215 | if ($DisplayName)
216 | {
217 | $softwareTable | Where-Object { $_.displayname -Like "*$DisplayName*" }
218 | }
219 | else
220 | {
221 | $softwareTable | Sort-Object -Property displayname -Unique
222 | }
223 |
224 | }
225 |
226 | function WingetInstallPackage {
227 | param (
228 | $PackageID,
229 | $PackageName,
230 | $AdditionalInstallArgs
231 | )
232 | # Check if another msi install is in progress and wait
233 |
234 | $MSIExecCheck = Get-Process | Where-Object {$_.processname -eq 'msiexec'}
235 | if ($Null -ne $MSIExecCheck){
236 | Write-Log "another msi installation is in progress. Waiting for process to complete..."
237 | Wait-Process msiexec
238 | Write-Log "Continuing installation..."
239 | }
240 | if ($PackageID){
241 | & $Winget install --id $PackageID --source Winget --silent $AdditionalInstallArgs --accept-package-agreements --accept-source-agreements
242 | }
243 | elseif ($PackageName){
244 | & $Winget install --name $PackageName --source Winget --silent $AdditionalInstallArgs --accept-package-agreements --accept-source-agreements
245 | }
246 | }
247 |
248 | function Resolve-WinGetPath {
249 | # Look for Winget install in WindowsApps folder
250 | $WinAppFolderPath = Get-ChildItem -path "$env:ProgramFiles/WindowsApps" -recurse -filter "winget.exe" | where {$_.VersionInfo.FileVersion -ge 1.23}
251 | if ($WinAppFolderPath){
252 | $script:WinGet = $WinAppFolderPath | Select-Object -ExpandProperty Fullname | Sort-Object -Descending | Select-Object -First 1
253 | Write-Log "WinGet.exe found at path $Winget"
254 | }
255 | else {
256 | # Check if WinGet copy has already been extracted to ProgramData folder
257 | if (Test-Path "${env:ProgramData}\Microsoft.DesktopAppInstaller\WinGet.exe"){
258 | Write-Log "WinGet.exe found in ${env:ProgramData}\Microsoft.DesktopAppInstaller}"
259 | $Script:WinGet = "${env:ProgramData}\Microsoft.DesktopAppInstaller\WinGet.exe"
260 | }
261 | else {
262 | # Download WinGet MSIX bundle and extract files to ProgramData folder
263 | Write-Log "WinGet.exe not found in ${env:ProgramData}\Microsoft.DesktopAppInstaller"
264 | Download-Winget
265 | }
266 | }
267 | }
268 |
269 | function Test-WinGetOutput {
270 | if (-Not (Test-Path $Winget)){
271 | Write-Log "WinGet path not found at Test-WinGetOutput function!"
272 | Write-Log "WinGet variable : $WinGet"
273 | exit 1
274 | }
275 | $OutputTest = & $WinGet
276 | if ([string]::IsNullOrEmpty($OutputTest)){
277 | Write-Log "WinGet executable test failed to produce output!"
278 | exit 1
279 | }
280 | }
281 |
282 | #endregion HelperFunctions
283 | #region Script
284 |
285 | $VisualC = Get-RegUninstallKey -DisplayName "Microsoft Visual C++ 2015-2022 Redistributable (x64)"
286 |
287 | # Get path for Winget executible
288 | Resolve-WinGetPath
289 |
290 | # If Visual C++ Redist. not installed, install it
291 | if (-Not $VisualC){
292 | Write-Log -message "Visual C++ X64 not found. Attempting to install"
293 | try {
294 | $VisualCInstall = Install-VisualC
295 | }
296 | catch [System.InvalidOperationException]{
297 | Write-Log -message "Error installing visual c++ redistributable. Attempting install once more"
298 | Start-Sleep -Seconds 30
299 | $VisualCInstall = Install-VisualC
300 | }
301 | catch {
302 | Write-Log -message "Failed to install visual c++ redistributable!"
303 | Write-Log -message $_
304 | exit 1
305 | }
306 | if ($VisualCInstall -ne 0){
307 | Write-Log -message "Visual C++ X64 install failed. Exit code : $VisualCInstall"
308 | exit 1
309 | }
310 | Test-WinGetOutput
311 | }
312 | try
313 | {
314 | switch ($Mode){
315 | 'Install'{
316 | if ($PackageID){
317 | Write-Log -message "executing $Mode on $PackageID"
318 | $Install = WingetInstallPackage -PackageID $PackageID -AdditionalArgs $AdditionalInstallArgs
319 | }
320 | elseif ($PackageName){
321 | Write-Log -message "executing $Mode on $PackageName"
322 | $Install = WingeInstallPackage -PackageName $PackageName -AdditionalArgs $AdditionalInstallArgs
323 | }
324 | Write-Log $Install
325 | }
326 | 'Uninstall'{
327 | if ($PackageID){
328 | Write-Log -message "executing $Mode on $PackageID"
329 | $Uninstall = & $Winget uninstall --id $PackageID --source WinGet --silent
330 | }
331 | elseif ($PackageName){
332 | Write-Log -message "executing $Mode on $PackageName"
333 | $Uninstall = & $Winget uninstall --name $PackageName --source WinGet --silent
334 |
335 | }
336 | Write-Log $Uninstall
337 | }
338 | }
339 | }
340 | Catch
341 | {
342 | Write-Log $error[0]
343 | exit 1
344 | }
345 | #endregion
346 |
--------------------------------------------------------------------------------
/Winget-InstallStorePackage-Detection.ps1:
--------------------------------------------------------------------------------
1 | $PackageID = '9WZDNCRFJB13' #Enter package ID here
2 |
3 | # DO NOT MODIFY ANYTHING BELOW
4 | # Leverage task scheduler to create a scheduled task as the logged on user
5 | # Task will export all installed packages to file using Winget
6 | winget export -o .\installedpackages.txt | out-null
7 |
8 |
9 | $PackageList = ".\installedpackages.txt"
10 | if (-Not (Test-Path $PackageList)){
11 | Write-Host "Wignet package list not found!"
12 | exit 1
13 | }
14 | $InstalledPackages = Get-Content $PackageList | ConvertFrom-Json
15 | $IsInstalled = ($InstalledPackages).sources.packages | Where-Object {$_.packageidentifier -eq $PackageID}
16 | if ($IsInstalled){
17 | Write-Host $PackageID " was detected!"
18 | remove-item $PackageList
19 | #exit 0
20 | }
21 | else {
22 | remove-item $PackageList
23 | #exit 1
24 | }
--------------------------------------------------------------------------------
/Winget-InstallStorePackage.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 12/6/2022 2:14 PM
6 | Created by: Dave Just
7 | Organization:
8 | Filename: Winget-InstallStorePackage.ps1
9 | ===========================================================================
10 | .DESCRIPTION
11 | Installs any package from the MSStore. You must run this as the logged on user!
12 | Can be packaged and deployed as a Win32App in Intune.
13 | Use as base for any install with WinGet. Simply specify the PackageID and log variables.
14 | .PARAMETER PackageID
15 | Specify the WinGet ID. Use WinGet Search "SoftwareName" to locate the PackageID
16 | .EXAMPLE
17 | powershell.exe -executionpolicy bypass -file Winget-InstallStorePackage.ps1 -PackageID "9WZDNCRFJB13" -Log "FreshPaintWingetInstall.log"
18 | #>
19 | param (
20 | $PackageID,
21 | $Log
22 | )
23 |
24 | # Re-launch as 64bit process (source: https://z-nerd.com/blog/2020/03/31-intune-win32-apps-powershell-script-installer/)
25 | $argsString = ""
26 | If ($ENV:PROCESSOR_ARCHITEW6432 -eq "AMD64")
27 | {
28 | Try
29 | {
30 | foreach ($k in $MyInvocation.BoundParameters.keys)
31 | {
32 | switch ($MyInvocation.BoundParameters[$k].GetType().Name)
33 | {
34 | "SwitchParameter" { if ($MyInvocation.BoundParameters[$k].IsPresent) { $argsString += "-$k " } }
35 | "String" { $argsString += "-$k `"$($MyInvocation.BoundParameters[$k])`" " }
36 | "Int32" { $argsString += "-$k $($MyInvocation.BoundParameters[$k]) " }
37 | "Boolean" { $argsString += "-$k `$$($MyInvocation.BoundParameters[$k]) " }
38 | }
39 | }
40 | Start-Process -FilePath "$ENV:WINDIR\SysNative\WindowsPowershell\v1.0\PowerShell.exe" -ArgumentList "-File `"$($PSScriptRoot)\Winget-InstallStorePackage.ps1`" $($argsString)" -Wait -NoNewWindow
41 | }
42 | Catch
43 | {
44 | Throw "Failed to start 64-bit PowerShell"
45 | }
46 | Exit
47 | }
48 |
49 | #region HelperFunctions
50 |
51 |
52 | function Install-WinGet # Adapted from https://github.com/microsoft/winget-pkgs/blob/master/Tools/SandboxTest.ps1 (better than my original code!)
53 | # This function will install the latest version of WinGet and its dependancies
54 | {
55 | $tempFolderName = 'WinGetInstall'
56 | $tempFolder = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $tempFolderName
57 | New-Item $tempFolder -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
58 |
59 | $apiLatestUrl = if ($Prerelease) { 'https://api.github.com/repos/microsoft/winget-cli/releases?per_page=1' }
60 | else { 'https://api.github.com/repos/microsoft/winget-cli/releases/latest' }
61 |
62 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
63 | $WebClient = New-Object System.Net.WebClient
64 |
65 | function Get-LatestUrl
66 | {
67 | ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle$' }).browser_download_url
68 | }
69 |
70 | function Get-LatestHash
71 | {
72 | $shaUrl = ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt$' }).browser_download_url
73 |
74 | $shaFile = Join-Path -Path $tempFolder -ChildPath 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt'
75 | $WebClient.DownloadFile($shaUrl, $shaFile)
76 |
77 | Get-Content $shaFile
78 | }
79 |
80 | $desktopAppInstaller = @{
81 | fileName = 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle'
82 | url = $(Get-LatestUrl)
83 | hash = $(Get-LatestHash)
84 | }
85 |
86 | $vcLibsUwp = @{
87 | fileName = 'Microsoft.VCLibs.x64.14.00.Desktop.appx'
88 | url = 'https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx'
89 | hash = '9BFDE6CFCC530EF073AB4BC9C4817575F63BE1251DD75AAA58CB89299697A569'
90 | }
91 | $uiLibsUwp = @{
92 | fileName = 'Microsoft.UI.Xaml.2.7.zip'
93 | url = 'https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.0'
94 | hash = '422FD24B231E87A842C4DAEABC6A335112E0D35B86FAC91F5CE7CF327E36A591'
95 | }
96 |
97 | $dependencies = @($desktopAppInstaller, $vcLibsUwp, $uiLibsUwp)
98 |
99 | Write-Host '--> Checking dependencies'
100 |
101 | foreach ($dependency in $dependencies)
102 | {
103 | $dependency.file = Join-Path -Path $tempFolder -ChildPath $dependency.fileName
104 | #$dependency.pathInSandbox = (Join-Path -Path $tempFolderName -ChildPath $dependency.fileName)
105 |
106 | # Only download if the file does not exist, or its hash does not match.
107 | if (-Not ((Test-Path -Path $dependency.file -PathType Leaf) -And $dependency.hash -eq $(Get-FileHash $dependency.file).Hash))
108 | {
109 | Write-Host @"
110 | - Downloading:
111 | $($dependency.url)
112 | "@
113 |
114 | try
115 | {
116 | $WebClient.DownloadFile($dependency.url, $dependency.file)
117 | }
118 | catch
119 | {
120 | #Pass the exception as an inner exception
121 | throw [System.Net.WebException]::new("Error downloading $($dependency.url).", $_.Exception)
122 | }
123 | if (-not ($dependency.hash -eq $(Get-FileHash $dependency.file).Hash))
124 | {
125 | throw [System.Activities.VersionMismatchException]::new('Dependency hash does not match the downloaded file')
126 | }
127 | }
128 | }
129 |
130 | # Extract Microsoft.UI.Xaml from zip (if freshly downloaded).
131 | # This is a workaround until https://github.com/microsoft/winget-cli/issues/1861 is resolved.
132 |
133 | if (-Not (Test-Path (Join-Path -Path $tempFolder -ChildPath \Microsoft.UI.Xaml.2.7\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx)))
134 | {
135 | Expand-Archive -Path $uiLibsUwp.file -DestinationPath ($tempFolder + '\Microsoft.UI.Xaml.2.7') -Force
136 | }
137 | $uiLibsUwp.file = (Join-Path -Path $tempFolder -ChildPath \Microsoft.UI.Xaml.2.7\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx)
138 | Add-AppxPackage -Path $($desktopAppInstaller.file) -DependencyPath $($vcLibsUwp.file), $($uiLibsUwp.file)
139 | # Clean up files
140 | Remove-Item $tempFolder -recurse -force
141 | }
142 |
143 | #endregion HelperFunctions
144 | #region Install
145 | Start-Transcript -Path "C:\logs\$Log"
146 | #Test if Winget is installed. If not, try and install it.
147 | try {
148 | WinGet | Out-Null
149 | }
150 | catch {
151 | Install-WinGet
152 | }
153 | try {
154 | Winget | Out-Null
155 | }
156 | Catch {
157 | Write-Host "Winget not found after attempting to install. Stopping operation"
158 | exit 1
159 | }
160 |
161 | Winget install --id $PackageID --source msstore --silent --accept-package-agreements --accept-source-agreements
162 | Stop-Transcript
163 | #endregion
164 |
--------------------------------------------------------------------------------
/Winget-UpgradeSelect.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 1/18/2022 8:39 AM
6 | Created by: Dave Just
7 | Organization:
8 | Filename: Winget-UpgradeSelect.ps1
9 | ===========================================================================
10 | .DESCRIPTION
11 | Use the Windows Package Manager (Winget) to selectively install application updates. Edit the WinGetApprovedPackages hashtables with the packages
12 | you would like to keep updated
13 | #>
14 | param (
15 | [string]$ClientName
16 | )
17 | $LogName = 'WinGetPackageUpgrade'
18 | $LogDate = (Get-Date).ToFileTime()
19 | $Log = "$LogName-$LogDate.log"
20 | $results = [System.Collections.Generic.List[PsObject]]::new()
21 | $loggedOnUser = (GCIM Win32_ComputerSystem).Username
22 |
23 | #region HelperFunctions
24 |
25 | function Get-RegUninstallKey #List all system-wide installed software
26 | {
27 | param (
28 | [string]$DisplayName
29 | )
30 | $ErrorActionPreference = 'SilentlyContinue'
31 | $UserSID = ([System.Security.Principal.NTAccount](Get-CimInstance -ClassName Win32_ComputerSystem).UserName).Translate([System.Security.Principal.SecurityIdentifier]).Value
32 | $uninstallKeys = "registry::HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall", "registry::HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
33 | $softwareTable = @()
34 |
35 | foreach ($key in $uninstallKeys)
36 | {
37 | $softwareTable += Get-Childitem $key | Get-ItemProperty | where displayname | Sort-Object -Property displayname
38 | }
39 | if ($DisplayName)
40 | {
41 | $softwareTable | where displayname -Like "*$DisplayName*"
42 | }
43 | else
44 | {
45 | $softwareTable | Sort-Object -Unique
46 | }
47 | Return $softwareTable
48 |
49 | }
50 |
51 | function LogWrite($message) #Log script messages
52 | {
53 | $LogMessage = ((Get-Date -Format "MM-dd-yy HH:MM:ss ") + $message)
54 | Out-File -InputObject $message -FilePath "$env:TEMP\$Log" -Append -Encoding utf8
55 | #[System.IO.File]::AppendAllText("$env:TEMP\$Log","`n $($LogMessage)")
56 | }
57 |
58 | function InstallWinget # Install WinGet as logged on user
59 | {
60 | $script = @'
61 | $hasPackageManager = Get-AppPackage -name "Microsoft.DesktopAppInstaller"
62 |
63 | if(!$hasPackageManager)
64 | {
65 | $releases_url = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
66 |
67 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
68 | $releases = Invoke-RestMethod -uri "$($releases_url)"
69 | $latestRelease = $releases.assets | Where { $_.browser_download_url.EndsWith("msixbundle") } | Select -First 1
70 |
71 | Add-AppxPackage -Path $latestRelease.browser_download_url
72 | }
73 | '@
74 | if (!(test-path C:\automation)) { mkdir C:\automation }
75 | $script | out-file C:\automation\script.ps1
76 | $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-executionpolicy bypass -file C:\automation\script.ps1"
77 | $trigger = New-ScheduledTaskTrigger -AtLogOn
78 | $principal = New-ScheduledTaskPrincipal -UserId (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -expand UserName)
79 | $task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal
80 | Register-ScheduledTask RunScript -InputObject $task
81 | Start-ScheduledTask -TaskName RunScript
82 | Start-Sleep -Seconds 2
83 | Unregister-ScheduledTask -TaskName RunScript -Confirm:$false
84 | Remove-Item C:\automation\script.ps1
85 |
86 | # Get path for Winget executible
87 | $Global:Winget = gci "C:\Program Files\WindowsApps" -Recurse -File | where {$_.name -like "AppInstallerCLI.exe" -or $_.name -like "WinGet.exe"} | select -ExpandProperty fullname
88 |
89 | # If there are multiple versions, select latest
90 | if ($Winget.count -gt 1){$Winget = $Winget[-1]}
91 | if (!($Winget)){LogWrite "AppInstallerCLI.exe not found after InstallWinget function. Aborting!"
92 | Write-Output "AppInstallerCLI.exe not found after InstallWinget function. Aborting!"
93 | Exit 1}
94 |
95 | }
96 |
97 |
98 | #endregion HelperFunctions
99 |
100 | #region Script
101 |
102 |
103 | # Get path for Winget executible
104 | $Winget = gci "C:\Program Files\WindowsApps" -Recurse -File | where {$_.name -like "AppInstallerCLI.exe" -or $_.name -like "WinGet.exe"} | select -ExpandProperty fullname
105 | # If there are multiple versions, select latest
106 | if ($Winget.count -gt 1){$Winget = $Winget[-1]}
107 | $WingetTemp = gci $env:TEMP -Recurse -File | where name -like AppInstallerCLI.exe | select -ExpandProperty fullname
108 | # Try to install Winget if not already installed
109 | if (!($Winget))
110 | {
111 | if ($WingetTemp) { LogWrite "Winget found in $($env:TEMP)";$Winget = $WingetTemp }
112 | elseif ($loggedOnUser) { InstallWinget }
113 | else
114 | {
115 | try
116 | {
117 |
118 | LogWrite "Winget not found, attempting to download now to $($env:TEMP)"
119 | $WebClient = New-Object System.Net.WebClient
120 | $WebClient.DownloadFile('https://djstorage2.blob.core.windows.net/scriptsupport/WinGet.zip', "$env:Temp\WinGet.zip")
121 | $WebClient.Dispose()
122 | Expand-Archive $env:TEMP\WinGet.zip -destination $Env:Temp
123 | $Winget = "$Env:TEMP\WinGet\AppInstallerCLI.exe"
124 | }
125 | Catch
126 | {
127 | LogWrite "Unable to initialize Winget. Exiting"
128 | Write-Output $Error[0]
129 | exit 1
130 | }
131 | }
132 |
133 | }
134 |
135 | $Winrar = (Get-RegUninstallKey | where displayname -Like "*WinRAR*" | select -ExpandProperty Displayname)
136 | if (!($Winrar)) { $Winrar = "Null-1" }
137 | $7Zip = (Get-RegUninstallKey | where displayname -Like "*7-zip*" | select -ExpandProperty Displayname)
138 | if (!($7zip)) { $7zip = "Null-2" }
139 |
140 | # Hash table to translate installed software to Winget Package IDs
141 | $WinGetApprovedPackages = @{
142 | 'Google Chrome' = 'Google.Chrome'
143 | 'Mozilla Firefox (x64 en-US)' = 'Mozilla.Firefox'
144 | 'Microsoft OneDrive' = 'Microsoft.OneDrive'
145 | 'Notepad++' = 'Notepad++.Notepad++'
146 | 'Microsoft Edge' = 'Microsoft.Edge'
147 | 'Lenovo System Update' = 'Lenovo.SystemUpdate'
148 | "$($7Zip)" = '7zip.7zip'
149 | "$($WinRar)" = 'RARLab.WinRAR'
150 | "Adobe Acrobat Reader DC" = 'Adobe.Acrobat.Reader.32-bit'
151 | "CCleaner" = "Piriform.CCleaner"
152 | "PuTTY" = "PuTTY.PuTTY"
153 | }
154 |
155 | $InstalledSoftware = Get-RegUninstallKey
156 | $UpgradeList = foreach ($Package in $WinGetApprovedPackages.Keys) { $InstalledSoftware | where displayname -Like $Package }
157 |
158 | LogWrite "Client: $($ClientName)"
159 | LogWrite "Hostname: $($env:COMPUTERNAME)"
160 | LogWrite "Found the following installed packages:"
161 | $UpgradeList | foreach {LogWrite "Name: $($_.Displayname) Version: $($_.DisplayVersion)"}
162 |
163 | # Index software displaynames in hash table
164 | $WingetPackages = $WinGetApprovedPackages[$UpgradeList.DisplayName]
165 |
166 | # Remove null values from array
167 | $WingetPackages = $WinGetPackages | where { $_ }
168 |
169 | # Run the upgrade command for installed software only based on our package list
170 | foreach ($Package in $WinGetPackages)
171 | {
172 | LogWrite "Upgrading $($Package)"
173 | try
174 | {
175 | $UpgradeRun = & $Winget upgrade --id $Package -h --accept-package-agreements --accept-source-agreements | Tee-Object "$env:TEMP\$log" -Append
176 | }
177 | Catch
178 | {
179 | LogWrite $Error[0]
180 | Write-Output $Error[0]
181 | }
182 |
183 | }
184 | # Adding Hashtable here again as 7zip and Winrar have the version number in the displayname
185 | # Need the new displayname to compare to the old
186 |
187 | $Winrar = (Get-RegUninstallKey | where displayname -Like "*WinRAR*" | select -ExpandProperty Displayname)
188 | if (!($Winrar)) { $Winrar = "Null-1" }
189 | $7Zip = (Get-RegUninstallKey | where displayname -Like "*7-zip*" | select -ExpandProperty Displayname)
190 | if (!($7zip)) { $7zip = "Null-2" }
191 |
192 | # Hash table to translate installed software to Winget Package IDs
193 | $WinGetApprovedPackages = @{
194 | 'Google Chrome' = 'Google.Chrome'
195 | 'Mozilla Firefox (x64 en-US)' = 'Mozilla.Firefox'
196 | 'Microsoft OneDrive' = 'Microsoft.OneDrive'
197 | 'Notepad++' = 'Notepad++.Notepad++'
198 | 'Microsoft Edge' = 'Microsoft.Edge'
199 | 'Lenovo System Update' = 'Lenovo.SystemUpdate'
200 | "$($7Zip)" = '7zip.7zip'
201 | "$($WinRar)" = 'RARLab.WinRAR'
202 | "Adobe Acrobat Reader DC" = 'Adobe.Acrobat.Reader.32-bit'
203 | "CCleaner" = "Piriform.CCleaner"
204 | "PuTTY" = "PuTTY.PuTTY"
205 | }
206 |
207 |
208 |
209 | $InstalledSoftware = Get-RegUninstallKey
210 | $PostUpgradeList = foreach ($Package in $WinGetApprovedPackages.Keys) { $InstalledSoftware | where displayname -Like $Package }
211 |
212 | #Compare results
213 | $UpgradeListHash = @{ }
214 | $PostUpgradeHash = @{ }
215 | foreach ($i in $UpgradeList) { $UpgradeListHash.Add($i.displayname , $i.displayversion) }
216 | foreach ($i in $PostUpgradeList) { $PostUpgradeHash.Add($i.displayversion, $i.displayname) }
217 | $compare = Compare-Object $UpgradeList.displayversion -DifferenceObject $PostUpgradeList.displayversion | where sideindicator -eq "=>" | select -ExpandProperty InputObject
218 | if ($compare) { $UpgradedSoftware = $PostUpgradeHash[$compare] }
219 |
220 | # Log what software was updated and create custom object
221 | if (!($UpgradedSoftware))
222 | {
223 | LogWrite "No software was eligable for upgrade"
224 | }
225 |
226 | else{
227 | foreach ($i in $compare)
228 | {
229 | $SoftwareName = $PostUpgradeHash[$i]
230 | if ($SoftwareName -match "7-Zip*")
231 | {
232 | $OldVersion = $UpgradeList | where displayname -Like "7-zip*" | select -ExpandProperty displayversion
233 | }
234 | elseif ($SoftwareName -match "WinRAR*")
235 | {
236 | $OldVersion = $UpgradeList | where displayname -Like "WinRAR*" | select -ExpandProperty displayversion
237 | }
238 | else { $OldVersion = $UpgradeListHash[$SoftwareName] }
239 | LogWrite "$($SoftwareName) was upgraded to version $($i) from version $($OldVersion)"
240 | $results = [pscustomobject]@{
241 | Computername = hostname
242 | Client = $ClientName
243 | UpgradedSoftware = $SoftwareName
244 | NewVersion = $i
245 | OldVersion = $OldVersion
246 | Time = (get-date -Format MM-dd_HH:m:ss.ff)
247 | }
248 | function ResultToAzureTable
249 | {
250 | $header = @{ 'Content-Type' = "application/json" }
251 | $flow = 'https://prod-126.westus.logic.azure.com:443/workflows/*' #URI for Power Automate Flow
252 | $flowheader = $results | ConvertTo-Json -Compress
253 | try
254 | {
255 | Invoke-RestMethod -Method Post -Body $flowheader -uri $flow -Headers $header -ErrorAction 'Stop'
256 | LogWrite "POST to Azure Table Successful!"
257 | }
258 | Catch
259 | {
260 | LogWrite "Error logging to Azure Table"; $global:RESTFailure = $true
261 | }
262 | Start-Sleep 2
263 | }
264 | ResultToAzureTable
265 |
266 | if ($RESTFailure){ResultToAzureTable} #Attempt to send REST POST to Azure table a second time
267 |
268 | }
269 | }
270 |
271 | Get-Content $env:TEMP\$Log #Write Log to Console
272 | #endregion Script
273 |
274 |
--------------------------------------------------------------------------------
/WingetUpgrade-ProactiveDetection.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 8/22/2022 3:08 PM
6 | Created by: David Just
7 | Website: davidjust.com
8 | Filename: WingetUpgrade-ProactiveDetection.ps1
9 | ===========================================================================
10 | .DESCRIPTION
11 | Proactive Remediation detection script for applications with updates
12 | #>
13 |
14 | $Blacklisted = @(
15 | 'Microsoft.Teams'
16 | 'Microsoft.Office'
17 | 'Microsoft.VC++2015-2022Redist-x64'
18 | )
19 | Import-Module -Name WingetTools
20 | $AvailableUpdates = Get-WGInstalled | where-object { $_.id -notin $Blacklisted -and $_.update }
21 |
22 | if ($AvailableUpdates.count -gt 0)
23 | {
24 | "There are applications with Updates available"
25 | $AvailableUpdates | Select-Object -Property Name, ID, InstalledVersion, OnlineVersion
26 | exit 1
27 | }
28 | else
29 | {
30 | "There are no apps to update"
31 | Exit 0
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/WingetUpgrade-Remediation.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 8/22/2022 10:46 AM
6 | Created by: David Just
7 | Website: david.just.com
8 | Filename: WingetUpgrade-Remediation.ps1
9 | ===========================================================================
10 | .DESCRIPTION
11 | A description of the file.
12 | #>
13 | function Write-Log($message) #Log script messages to temp directory
14 | {
15 | $LogMessage = ((Get-Date -Format "MM-dd-yy HH:MM:ss ") + $message)
16 | Out-File -InputObject $LogMessage -FilePath "$LogPath\$Log" -Append -Encoding utf8
17 | }
18 |
19 | $LogName = 'WinGetPackageUpgrade'
20 | $LogDate = Get-Date -Format dd-MM-yy_HH-mm # go with the EU format day / month / year
21 | $Log = "$LogName-$LogDate.log"
22 | $LogPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs"
23 | Import-Module WingetTools
24 | $WingetPath = Get-WGPath
25 |
26 | # Add any apps you do not wish to get updated here (for instance apps that auto-update). Use the Winget ID
27 | $Blacklisted = @(
28 | 'Microsoft.Teams'
29 | 'Microsoft.Office'
30 | 'Microsoft.VC++2015-2022Redist-x64'
31 | )
32 | $AvailableUpdates = Get-WGInstalled | where-object { $_.id -notin $Blacklisted -and $_.update }
33 | Write-Log -message "Packages with Updates Available:"
34 | $AvailableUpdates | select Name, Version | Out-File -FilePath "$logpath\$Log" -Append -Encoding utf8
35 |
36 |
37 | foreach ($App in $AvailableUpdates) # Invoke upgrade for each updatable app and log results
38 | {
39 | [void](Get-Process | Where-Object { $_.name -Like "*$App.Name*" } | Stop-Process -Force)
40 | $UpgradeRun = & $WingetPath upgrade --id $App.id -h --accept-package-agreements --accept-source-agreements
41 | $UpgradeRun | Out-File -FilePath "$logpath\$log" -Append -Encoding utf8
42 | $Status = [bool]($UpgradeRun | select-string -SimpleMatch "Successfully installed")
43 | if ($Status -eq $true)
44 | {
45 | $Success += $App
46 | }
47 | else
48 | {
49 | $Failed += $App
50 | }
51 |
52 | }
53 |
54 |
55 | if ($Success.count -gt 0)
56 | {
57 | Write-Log -message "Successful Upgraded the following:"
58 | $Success | Out-File -FilePath "$logpath\$log" -Append -Encoding utf8
59 | "Sucessfully Updated the following apps:`n{0}" -f $($Success | Select-Object -Property name)
60 | }
61 |
62 | if ($Failed.count -gt 0)
63 | {
64 | Write-Log -message "Failed to Upgrade the following:"
65 | $Failed | Out-File -FilePath "$logpath\$log" -Append -Encoding utf8
66 | }
67 |
68 | # Cleanup any logfiles 14 days old or older
69 | $Limit = (Get-Date).AddDays(-14)
70 | $OldLogs = Get-ChildItem $logpath | Where-Object {$_.name -like "WingetPackageUpgrade*.log" -and ($Limit - $_.CreationTime).days -ge 14 }
71 | $OldLogs | Foreach-Object { Remove-Item -FilePath $_.FullName }
72 |
--------------------------------------------------------------------------------
/WingetUpgradeTask.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 | ===========================================================================
4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
5 | Created on: 8/23/2022 8:30 AM
6 | Created by: David Just
7 | Website: davidjust.com
8 | Filename: WingetDailyUpgradeTask.ps1
9 | ===========================================================================
10 | .DESCRIPTION
11 | Create a scheduled task running as System to update applications daily using WinGet.
12 | #>
13 |
14 | $script = @'
15 | <#
16 | .NOTES
17 | ===========================================================================
18 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.195
19 | Created on: 8/22/2022 10:46 AM
20 | Created by: David Just
21 | Website: david.just.com
22 | Filename: WingetUpgrade-Remediation.ps1
23 | ===========================================================================
24 | .DESCRIPTION
25 | A description of the file.
26 | #>
27 | function Write-Log($message) #Log script messages to temp directory
28 | {
29 | $LogMessage = ((Get-Date -Format "MM-dd-yy HH:MM:ss ") + $message)
30 | Out-File -InputObject $LogMessage -FilePath "$LogPath\$Log" -Append -Encoding utf8
31 | }
32 |
33 | $LogName = 'WinGetPackageUpgrade'
34 | $LogDate = Get-Date -Format dd-MM-yy_HH-mm # go with the EU format day / month / year
35 | $Log = "$LogName-$LogDate.log"
36 | $LogPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs"
37 | Import-Module WingetTools
38 | $WingetPath = Get-WGPath
39 |
40 | # Add any apps you do not wish to get updated here (for instance apps that auto-update). Use the Winget ID
41 | $Blacklisted = @(
42 | 'Microsoft.Teams'
43 | 'Microsoft.Office'
44 | 'Microsoft.VC++2015-2022Redist-x64'
45 | )
46 | $AvailableUpdates = Get-WGInstalled | where-object { $_.id -notin $Blacklisted -and $_.update }
47 | Write-Log -message "Packages with Updates Available:"
48 | $AvailableUpdates | select Name, Version | Out-File -FilePath "$logpath\$Log" -Append -Encoding utf8
49 |
50 |
51 | foreach ($App in $AvailableUpdates) # Invoke upgrade for each updatable app and log results
52 | {
53 | [void](Get-Process | Where-Object { $_.name -Like "*$App.Name*" } | Stop-Process -Force)
54 | $UpgradeRun = & $WingetPath upgrade --id $App.id -h --accept-package-agreements --accept-source-agreements
55 | $UpgradeRun | Out-File -FilePath "$logpath\$log" -Append -Encoding utf8
56 | $Status = [bool]($UpgradeRun | select-string -SimpleMatch "Successfully installed")
57 | if ($Status -eq $true)
58 | {
59 | $Success += $App
60 | }
61 | else
62 | {
63 | $Failed += $App
64 | }
65 |
66 | }
67 |
68 |
69 | if ($Success.count -gt 0)
70 | {
71 | Write-Log -message "Successful Upgraded the following:"
72 | $Success | Out-File -FilePath "$logpath\$log" -Append -Encoding utf8
73 | "Sucessfully Updated the following apps:`n{0}" -f $($Success | Select-Object -Property name)
74 | }
75 |
76 | if ($Failed.count -gt 0)
77 | {
78 | Write-Log -message "Failed to Upgrade the following:"
79 | $Failed | Out-File -FilePath "$logpath\$log" -Append -Encoding utf8
80 | }
81 |
82 | '@
83 | if (!(test-path "$env:SystemDrive\automation")) { mkdir "$env:SystemDrive\automation" }
84 | $script | out-file -FilePath "$env:SystemDrive\automation\WingetAutomatedUpgrade.ps1"
85 | $Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-executionpolicy bypass -file %SystemDrive%\automation\WingetAutomatedUpgrade.ps1 -windowstyle hidden"
86 | # Edit the schedule variable to adjust the desired schedule.
87 | # Weekly schedule example : $Schedule = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 6AM
88 | $Schedule = New-ScheduledTaskTrigger -Daily -At 6am
89 | $principal = New-ScheduledTaskPrincipal -UserId "NT Authority\SYSTEM" -RunLevel Highest
90 | $Settings = New-ScheduledTaskSettingsSet
91 | $Settings.DisallowStartIfOnBatteries = $false
92 | $Settings.StopIfGoingOnBatteries = $false
93 | $Settings.IdleSettings.StopOnIdleEnd = $false
94 | $CreateTask = New-ScheduledTask -Action $Action -Trigger $Schedule -Principal $principal -Settings $Settings
95 | Register-ScheduledTask "Winget Automated Upgrade Task" -InputObject $CreateTask
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/chromebookmarks.ps1:
--------------------------------------------------------------------------------
1 | $jsonRepresentation = '{
2 | "checksum": "8a83fd48cdea66f88b0dcf708bceae47",
3 | "roots": {
4 | "bookmark_bar": {
5 | "children": [ {
6 | "date_added": "13218554400308142",
7 | "guid": "278dff65-0d68-4b8d-9cf8-60ea3b2dbe9d",
8 | "id": "5",
9 | "name": "Amazon",
10 | "type": "url",
11 | "url": "http://amazon.com/"
12 | }, {
13 | "date_added": "13218554442843596",
14 | "guid": "3d87584d-a71f-4ff0-aa18-0c79efcc29c7",
15 | "id": "6",
16 | "name": "CNN",
17 | "type": "url",
18 | "url": "http://cnn.com"
19 | }, {
20 | "date_added": "13218554452536920",
21 | "guid": "179fa996-6b4b-4d9a-beb7-de96fa0d848a",
22 | "id": "7",
23 | "name": "Adobe",
24 | "type": "url",
25 | "url": "http://adobe.com"
26 | }, {
27 | "date_added": "13218554465874578",
28 | "guid": "c03a072c-9956-4429-9737-cc770ecd34c5",
29 | "id": "8",
30 | "name": "Office 365 Portal",
31 | "type": "url",
32 | "url": "http://portal.office.com/"
33 | }, {
34 | "date_added": "13218554481458818",
35 | "guid": "a567e83d-8560-4de0-a03d-53c0dbb90cb4",
36 | "id": "9",
37 | "name": "My Apps",
38 | "type": "url",
39 | "url": "http://myapps.microsoft.com/"
40 | } ],
41 | "date_added": "13218553204407005",
42 | "date_modified": "13218554481458818",
43 | "guid": "00000000-0000-4000-A000-000000000002",
44 | "id": "1",
45 | "name": "Bookmarks bar",
46 | "type": "folder"
47 | },
48 | "other": {
49 | "children": [ ],
50 | "date_added": "13218553204407488",
51 | "date_modified": "0",
52 | "guid": "00000000-0000-4000-A000-000000000003",
53 | "id": "2",
54 | "name": "Other bookmarks",
55 | "type": "folder"
56 | },
57 | "synced": {
58 | "children": [ ],
59 | "date_added": "13218553204407497",
60 | "date_modified": "0",
61 | "guid": "00000000-0000-4000-A000-000000000004",
62 | "id": "3",
63 | "name": "Mobile bookmarks",
64 | "type": "folder"
65 | }
66 | },
67 | "version": 1
68 | }'
69 |
70 | $users = Get-ChildItem "C:\Users" -Exclude Public
71 | $users | ForEach-Object {
72 | New-Item -ItemType Directory -Path "C:\Users\$($_.Name)\AppData\Local\Google\chrome\User Data\default" -force}
73 |
74 | $users | ForEach-Object {
75 | Add-Content -path "C:\Users\$($_.Name)\AppData\Local\Google\chrome\User Data\default\bookmarks" $jsonRepresentation }
76 |
--------------------------------------------------------------------------------
/map-printers-scheduledtask.ps1:
--------------------------------------------------------------------------------
1 | #Tests Connection to Print Server
2 | $tpscript= '$fp01 = Test-Connection -ComputerName printserver.domain.com -ErrorAction SilentlyContinue
3 |
4 | #Checks if driver is installed. Installed via win32 intune app using pnputil.exe
5 | $toshiba= test-path C:\Windows\System32\DriverStore\FileRepository\esf6u.inf_amd64_10e58d367838d6a3
6 |
7 | if ($toshiba -eq $true -and $fp01 -eq $true)
8 | {add-printer -ConnectionName "\\printserver.domain.com\Printer Share Name 1"
9 | add-printer -ConnectionName "\\printserver.domain.com\Printer Share Name 2"
10 | add-printer -ConnectionName "\\printserver.domain.com\Printer Share Name 3" }'
11 |
12 | #create mapping script
13 | new-item c:\automation -ItemType directory -force
14 | set-content c:\automation\addprinters.ps1 $tpscript
15 |
16 | if( -Not (Get-ScheduledTask -TaskName "Map Printers" -ErrorAction SilentlyContinue -OutVariable task) )
17 | {
18 | $Params = @{
19 | Action = (New-ScheduledTaskAction -Execute 'powershell' -Argument '-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass c:\automation\addprinters.ps1')
20 | Trigger = (New-ScheduledTaskTrigger -AtLogOn)
21 | Principal = (New-ScheduledTaskPrincipal -UserId (Get-CimInstance –ClassName Win32_ComputerSystem | Select-Object -expand UserName))
22 | TaskName = 'Map Printers'
23 | Description = 'Map Printers'
24 | }
25 | Register-ScheduledTask @Params
26 | Start-ScheduledTask -TaskName "Map Printers"
27 | }
28 | else
29 | {
30 | Start-ScheduledTask -TaskName "Map Printers"
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/powersettings.ps1:
--------------------------------------------------------------------------------
1 | #simple script to set powersettings for the current user. Run in the users context and adjust values as desired
2 | #As of 11/23/19 OMA-URI power policy CSP settings do no appear to work with intune.
3 |
4 | powercfg.exe -x -monitor-timeout-ac 15
5 | powercfg.exe -x -monitor-timeout-dc 10
6 | powercfg.exe -x -standby-timeout-dc 30
7 | powercfg.exe -x -standby-timeout-ac 0
8 | powercfg.exe -x -disk-timeout-ac 0
9 | powercfg.exe -x -disk-timeout-dc 0
10 |
--------------------------------------------------------------------------------
/remove-localadmins.ps1:
--------------------------------------------------------------------------------
1 | #simple script to remove any local admins not approved. Just change the names you are filtering by. Can be combined with a
2 | #scheduled task to run more than once
3 |
4 | $admins = Get-LocalGroupMember administrators | where {$_.name -notmatch "dave" -and $_.name -notmatch "domain admins"} | select -ExpandProperty name
5 | $admins | foreach {Remove-LocalGroupMember -group "administrators" -member $_}
6 |
--------------------------------------------------------------------------------
/set_startmenu_taskbar_layout.ps1:
--------------------------------------------------------------------------------
1 | #this script will create the layoutmodification.xml file and force a refresh of startmenu/taskbar. Modify the xml to your liking
2 | #currently pins office apps, chrome, company portal
3 |
4 | $layout = '
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | '
35 |
36 |
37 | Set-content $env:LOCALAPPDATA\Microsoft\Windows\Shell\LayoutModification.xml $layout -Force
38 | Remove-Item 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\*$start.tilegrid$windows.data.curatedtilecollection.tilecollection' -Force -Recurse
39 | Get-Process Explorer | Stop-Process
40 |
--------------------------------------------------------------------------------
/sharepoint_trustedsites.ps1:
--------------------------------------------------------------------------------
1 | New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\sharepoint.com\TENANTNAME-myfiles" -force | New-ItemProperty -name Https -Value 2
2 | New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\sharepoint.com\TENANTNAME-files" -force | New-ItemProperty -name Https -Value 2
--------------------------------------------------------------------------------
/startmenu_layout_plus_scheduledtask.ps1:
--------------------------------------------------------------------------------
1 | #This section creates our layoutmodification xml
2 |
3 | $layout = '
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | '
34 |
35 | $UserSID = (New-Object -ComObject Microsoft.DiskQuota).TranslateLogonNameToSID((Get-WmiObject -Class Win32_ComputerSystem).Username)
36 | $Path = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Profilelist\$UserSID"
37 | $UserPath = Get-ItemProperty "Registry::$path" -name "ProfileImagePath" | select -ExpandProperty ProfileImagePath
38 |
39 | Set-content $userpath\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml $layout -Force
40 |
41 | #This Section Creates the powershell script that will be used by our scheduled task and save to c:\automation
42 |
43 | $content = 'New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
44 | $UserSID = (New-Object -ComObject Microsoft.DiskQuota).TranslateLogonNameToSID((Get-WmiObject -Class Win32_ComputerSystem).Username)
45 | $Path = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Profilelist\$UserSID"
46 | $UserPath = Get-ItemProperty "Registry::$path" -name "ProfileImagePath" | select -ExpandProperty ProfileImagePath
47 | $time = Get-Date -Format "dddd MM/dd/yyyy HH:mm K"
48 |
49 | #This Modifies the time stamp of the layoutmodification xml
50 |
51 | Get-Item $userpath\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml | % {$_.CreationTime = $time}
52 | Get-Item $userpath\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml | % {$_.LastWriteTime = $time}
53 |
54 | # Remove-Item HKU:\$UserSID\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\*$start.tilegrid$windows.data.curatedtilecollection.tilecollection -Force -Recurse
55 | Remove-Item HKU:\$UserSID\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store -Force -recurse
56 | Get-Process Explorer | Stop-Process -force
57 |
58 | sleep 5
59 |
60 | $explorer = get-process explorer
61 |
62 | if ($explorer -eq $false)
63 | {
64 | start-process explorer
65 | }
66 | remove-psdrive -Name HKU'
67 |
68 | new-item c:\automation -ItemType directory -force
69 | set-content c:\automation\startlayout.ps1 $content
70 |
71 | #This Section Creates the Scheduled task to run our startlayout script
72 |
73 | if( -Not (Get-ScheduledTask -TaskName "Start Menu Layout" -ErrorAction SilentlyContinue -OutVariable task) )
74 | {
75 | $Params = @{
76 | Action = (New-ScheduledTaskAction -Execute 'powershell' -Argument '-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass C:\Automation\startlayout.ps1')
77 | Trigger = (New-ScheduledTaskTrigger -once -At ([DateTime]::Now.AddMinutes(1)) -RepetitionInterval (New-TimeSpan -Minutes 15) -RepetitionDuration (New-TimeSpan -Hours 3))
78 | Principal = (New-ScheduledTaskPrincipal -GroupId "System")
79 | TaskName = 'Start Menu Layout'
80 | Description = 'Start Menu Layout'
81 | }
82 | Register-ScheduledTask @Params
83 | Start-ScheduledTask -TaskName "Start Menu Layout"
84 | }
85 | else
86 | {
87 | Start-ScheduledTask -TaskName "Start Menu Layout"
88 | }
89 |
--------------------------------------------------------------------------------
/teams_firewallrules.ps1:
--------------------------------------------------------------------------------
1 | $UserSID = (New-Object -ComObject Microsoft.DiskQuota).TranslateLogonNameToSID((Get-CIMInstance -Class Win32_ComputerSystem).Username)
2 | $ProfilePath = Get-Itemproperty registry::"HKU\$UserSID\Volatile Environment" | select-object -ExpandProperty "USERPROFILE"
3 | New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
4 |
5 |
6 | $TeamsDir = $profilepath + '\appdata\local\Microsoft\Teams\current\teams.exe'
7 | $firewallRuleName = 'teams.exe'
8 |
9 | $ruleExist = Get-NetFirewallRule -DisplayName $firewallRuleName -ErrorAction SilentlyContinue
10 |
11 | if($ruleExist)
12 | {
13 | Set-NetFirewallRule -DisplayName $firewallRuleName -Profile Any -Action Allow
14 | }
15 | else
16 | {
17 | New-NetfirewallRule -DisplayName $firewallRuleName -Direction Inbound -Protocol TCP -Profile Any -Program $TeamsDir -Action Allow
18 | New-NetfirewallRule -DisplayName $firewallRuleName -Direction Inbound -Protocol UDP -Profile Any -Program $TeamsDir -Action Allow
19 | }
--------------------------------------------------------------------------------