This is an update to the last CMTrace installer I wrote for Windows 7. This installer has been completely rewritten that allows it to function both for installing and configuring CMTrace. I included all of the requirements within the same script for installing as an administrator and configuring CMTrace to be the default .log file viewer under the user context. Thanks to Sapien's PowerShell Studio, the script was a breeze to write!
The script can be executed to both install CMTrace and configure it under user context if the end user has local administrator privileges. This can be done by including both -SystemInstall and -UserConfig when executing the script. I have it configured in our build to execute the script with the -SystemInstall. When a user logs in for the first time, the script executes and configures CMTrace as the default viewer. The user configuration is not completed until the system is rebooted. This can be done by several methods. You could use SCCM to execute the script one time unpon user logon, which is what I have configured. It could also be setup to execute from the HKCU runonce key. I have also included error checking within the script. If any errors are encountered, the script will return an error code 1 thereby reporting it to MDT/SCCM. One more thing I found and have not been able to get around is that the user will still get the following message the first time they open a .log file:
It does not matter if they click Yes or No. CMTrace remains as the default viewer.
It does not matter if they click Yes or No. CMTrace remains as the default viewer.
Here is a video of the script executing during a system install:
Here is a picture of the script after it completes configuring a user profile:
Here are examples on how to execute the script:
- Install CMTrace with administrator privileges during a build process or SCCM deployment
- powershell.exe -executionpolicy bypass -file Install_CMTrace.ps1 -SystemInstall
- Configure CMTrace as default .log file viewer via user context
- powershell.exe -executionpolicy bypass -windowstyle hidden -file Install_CMTrace.ps1 -UserConfig
- Specify a different installation directory to place CMTrace.exe
- powershell.exe -executionpolicy bypass -file Install_CMTrace.ps1 -SystemInstall -InstallLocation 'C:\Temp'
- Install CMTrace on a machine where users also have local administrator privileges
- powershell.exe -executionpolicy bypass -file Install_CMTrace.ps1 -SystemInstall -UserConfig
Install_CMTrace_Win10.ps1
1: <#
2: .SYNOPSIS
3: SystemInstall CMTrace
4:
5: .DESCRIPTION
6: This script will SystemInstall CMTrace on a system. It will make the appropriate registry changes necessary for the association of .log files with CMTrace. The script will run an initial check on the system to see if CMTrace is already installed. This is so the script can function both for installing CMTrace from an administrator perspective and associating CMTrace with .log files from a user perspective. If so, it will then make the appropriate changes to the HKCU.
7:
8: .PARAMETER SystemInstall
9: This puts the script into SystemInstall mode thereby installing the CMTrace.exe with no user association of .log extensions to CMTrace.exe
10:
11: .PARAMETER InstallLocation
12: Directory where to install CMTrace.exe
13:
14: .PARAMETER UserConfig
15: This tells the script to associate .log files with CMTrace for the current logged on user
16:
17: .PARAMETER PSConsoleTitle
18: Title of the PowerShell Console
19:
20: .EXAMPLE
21: Install CMTrace with administrator privileges during a build process or SCCM deployment
22: powershell.exe -executionpolicy bypass -file Install_CMTrace.ps1 -SystemInstall
23:
24: Install CMTrace on a machine where users also have local administrator privileges
25: powershell.exe -executionpolicy bypass -file Install_CMTrace.ps1 -SystemInstall -UserConfig
26:
27: Configure CMTrace as default for user(s)
28: powershell.exe -executionpolicy bypass -windowstyle hidden -file Install_CMTrace.ps1 -UserConfig
29:
30: Specify a different installation directory to place CMTrace.exe
31: powershell.exe -executionpolicy bypass -file Install_CMTrace.ps1 -SystemInstall -InstallLocation 'C:\Temp'
32:
33: .NOTES
34: ===========================================================================
35: Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.124
36: Created on: 7/6/2016 10:37 AM
37: Created by: Mick Pletcher
38: Organization:
39: Filename: InstallCMTrace.ps1
40: ===========================================================================
41: #>
42: [CmdletBinding()]
43: param
44: (
45: [switch]$SystemInstall,
46: [ValidateNotNullOrEmpty()][string]$InstallLocation = 'C:\windows\system32',
47: [switch]$UserConfig,
48: [ValidateNotNullOrEmpty()][string]$PSConsoleTitle = 'CMTrace Installation'
49: )
50:
51: function Close-Process {
52: <#
53: .SYNOPSIS
54: Close Process if running
55:
56: .DESCRIPTION
57: Check if specified process is running and close if true.
58:
59: .PARAMETER ProcessName
60: Name of the process. Do not include the extension such as .exe.
61:
62: .EXAMPLE
63: PS C:\> Close-Process -Process 'Value1'
64:
65: .NOTES
66: Additional information about the function.
67: #>
68:
69: [CmdletBinding()]
70: param
71: (
72: [ValidateNotNullOrEmpty()][string]$ProcessName
73: )
74:
75: $Process = Get-Process $ProcessName -ErrorAction SilentlyContinue
76: If ($Process) {
77: Do {
78: $Count++
79: Write-Host "Closing"$Process.ProcessName"....." -NoNewline
80: $Process | Stop-Process -Force
81: Start-Sleep -Seconds 5
82: $Process = Get-Process $ProcessName -ErrorAction SilentlyContinue
83: If ($Process) {
84: Write-Host "Failed" -ForegroundColor Red
85: } else {
86: Write-Host "Success" -ForegroundColor Yellow
87: }
88: } while (($Process) -and ($Count -lt 5))
89: }
90: }
91:
92: function Set-ConsoleTitle {
93: <#
94: .SYNOPSIS
95: Console Title
96:
97: .DESCRIPTION
98: Sets the title of the PowerShell Console
99:
100: .PARAMETER ConsoleTitle
101: Title of the PowerShell Console
102:
103: .NOTES
104: Additional information about the function.
105: #>
106:
107: [CmdletBinding()]
108: param
109: (
110: [Parameter(Mandatory = $true)][String]$ConsoleTitle
111: )
112:
113: $host.ui.RawUI.WindowTitle = $ConsoleTitle
114: }
115:
116: function Get-RelativePath {
117: <#
118: .SYNOPSIS
119: Get the relative path
120:
121: .DESCRIPTION
122: Returns the location of the currently running PowerShell script
123:
124: .NOTES
125: Additional information about the function.
126: #>
127:
128: [CmdletBinding()][OutputType([string])]
129: param ()
130:
131: $Path = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"
132: Return $Path
133: }
134:
135: function Install-CMTraceExecutable {
136: <#
137: .SYNOPSIS
138: Install CMTrace
139:
140: .DESCRIPTION
141: This function will install the CMTrace to the system32 directory, thereby giving access to CMTrace to the entire operating system.
142:
143: .EXAMPLE
144: PS C:\> Install-CMTrace
145:
146: .NOTES
147: Additional information about the function.
148: #>
149:
150: [CmdletBinding()]
151: param ()
152:
153: Close-Process -ProcessName 'CMTrace'
154: $RelativePath = Get-RelativePath
155: $SourceFile = $RelativePath + 'CMTrace.exe'
156: Write-Host "Installing CMTrace.exe....." -NoNewline
157: Copy-Item -Path $SourceFile -Destination $InstallLocation -Force
158: If ((Test-Path $InstallLocation) -eq $true) {
159: Write-Host "Success" -ForegroundColor Yellow
160: $Success = $true
161: } else {
162: Write-Host "Failed" -ForegroundColor Red
163: $Success = $false
164: }
165: Return $Success
166: }
167:
168: function Register-CMTraceToHKCR {
169: <#
170: .SYNOPSIS
171: Add CMTrace registry keys to the HKCR
172:
173: .DESCRIPTION
174: This will associate CMTrace with .log files within the HKCR hive
175:
176: .EXAMPLE
177: PS C:\> Register-CMTraceToHKCR
178:
179: .NOTES
180: Additional information about the function.
181: #>
182:
183: [CmdletBinding()][OutputType([boolean])]
184: param ()
185:
186: New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null
187: $Success = $true
188: $MUICacheRegKey = 'HKCR:\Local Settings\Software\Microsoft\Windows\Shell\MuiCache'
189: $ApplicationCompany = $InstallLocation + '.ApplicationCompany'
190: $ApplicationCompanyValue = 'Microsoft Corporation'
191: $FriendlyName = $InstallLocation + '.FriendlyAppName'
192: $FriendlyNameValue = "CMTrace.exe"
193: $LogfileRegKey = "HKCR:\Logfile\Shell\Open\Command"
194: $TestKey = Get-ItemProperty $MUICacheRegKey -Name $ApplicationCompany -ErrorAction SilentlyContinue
195: Write-Host 'Register HKCR Application Company.....' -NoNewline
196: If ($TestKey.$ApplicationCompany -ne $ApplicationCompanyValue) {
197: New-ItemProperty -Path $MUICacheRegKey -Name $ApplicationCompany -Value $ApplicationCompanyValue -PropertyType String | Out-Null
198: $TestKey = Get-ItemProperty -Path $MUICacheRegKey -Name $ApplicationCompany -ErrorAction SilentlyContinue
199: If ($TestKey.$ApplicationCompany -eq $ApplicationCompanyValue) {
200: Write-Host 'Success' -ForegroundColor Yellow
201: } else {
202: Write-Host 'Failed' -ForegroundColor Red
203: $Success = $false
204: }
205: } else {
206: Write-Host 'Already Registered' -ForegroundColor Yellow
207: }
208: Write-Host 'Register HKCR Friendly Application Name.....' -NoNewline
209: $TestKey = Get-ItemProperty $MUICacheRegKey -Name $FriendlyName -ErrorAction SilentlyContinue
210: If ($TestKey.$FriendlyName -ne $FriendlyNameValue) {
211: New-ItemProperty -Path $MUICacheRegKey -Name $FriendlyName -Value $FriendlyNameValue -PropertyType String -ErrorAction SilentlyContinue | Out-Null
212: $TestKey = Get-ItemProperty -Path $MUICacheRegKey -Name $FriendlyName -ErrorAction SilentlyContinue
213: If ($TestKey.$FriendlyName -eq $FriendlyNameValue) {
214: Write-Host 'Success' -ForegroundColor Yellow
215: } else {
216: Write-Host 'Failed' -ForegroundColor Red
217: $Success = $false
218: }
219: } else {
220: Write-Host 'Already Registered' -ForegroundColor Yellow
221: }
222: If ((Test-Path $LogfileRegKey) -eq $true) {
223: Write-Host "Removing HKCR:\Logfile....." -NoNewline
224: Remove-Item -Path "HKCR:\Logfile" -Recurse -Force
225: If ((Test-Path "HKCR:\Logfile") -eq $false) {
226: Write-Host "Success" -ForegroundColor Yellow
227: } else {
228: Write-Host "Failed" -ForegroundColor Red
229: }
230: }
231: Write-Host 'Register HKCR Logfile Classes Root.....' -NoNewline
232: New-Item -Path $LogfileRegKey -Force | Out-Null
233: New-ItemProperty -Path $LogfileRegKey -Name '(Default)' -Value $InstallLocation -Force | Out-Null
234: $TestKey = Get-ItemProperty -Path $LogfileRegKey -Name '(Default)' -ErrorAction SilentlyContinue
235: If ($TestKey.'(Default)' -eq $InstallLocation) {
236: Write-Host 'Success' -ForegroundColor Yellow
237: } else {
238: Write-Host 'Failed' -ForegroundColor Red
239: $Success = $false
240: }
241: Return $Success
242: }
243:
244: function Register-CMTraceToHKCU {
245: <#
246: .SYNOPSIS
247: Add CMTrace registry keys to the HKLM
248:
249: .DESCRIPTION
250: This will associate CMTrace with .log files within the HKLM hive
251:
252: .NOTES
253: Additional information about the function.
254: #>
255:
256: [CmdletBinding()][OutputType([boolean])]
257: param ()
258:
259: $Success = $true
260: #HKCU:\SOFTWARE\Classes\Log.file\Shell\Open\Command Key
261: $ClassesLogFileRegKey = "HKCU:\SOFTWARE\Classes\Log.file\Shell\Open\Command"
262: $ClassesLogFileRegKeyValue = [char]34 + $InstallLocation + [char]34 + [char]32 + [char]34 + "%1" + [char]34
263: If ((Test-Path "HKCU:\SOFTWARE\Classes\Log.file") -eq $true) {
264: Write-Host "Removing HKCU Log.File association....." -NoNewline
265: Remove-Item -Path "HKCU:\SOFTWARE\Classes\Log.file" -Recurse -Force
266: If ((Test-Path $ClassesLogFileRegKey) -eq $false) {
267: Write-Host "Success" -ForegroundColor Yellow
268: } else {
269: Write-Host "Failed" -ForegroundColor Red
270: $Success = $false
271: }
272: }
273: Write-Host "Register HKCU Log.File association....." -NoNewline
274: New-Item -Path $ClassesLogFileRegKey -Force | Out-Null
275: New-ItemProperty -Path $ClassesLogFileRegKey -Name '(Default)' -Value $ClassesLogFileRegKeyValue -Force | Out-Null
276: $TestKey = Get-ItemProperty -Path $ClassesLogFileRegKey -Name '(Default)' -ErrorAction SilentlyContinue
277: If ($TestKey.'(Default)' -eq $ClassesLogFileRegKeyValue) {
278: Write-Host 'Success' -ForegroundColor Yellow
279: } else {
280: Write-Host 'Failed' -ForegroundColor Red
281: $Success = $false
282: }
283: #HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log
284: $FileExtsRegKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log"
285: If ((Test-Path $FileExtsRegKey) -eq $true) {
286: Write-Host "Removing HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log....." -NoNewline
287: Remove-Item -Path $FileExtsRegKey -Recurse -Force
288: If ((Test-Path $FileExtsRegKey) -eq $false) {
289: Write-Host "Success" -ForegroundColor Yellow
290: } else {
291: Write-Host "Failed" -ForegroundColor Red
292: $Success = $false
293: }
294: }
295: Write-Host "Registering .log key....." -NoNewline
296: New-Item -Path $FileExtsRegKey -Force | Out-Null
297: If ((Test-Path $FileExtsRegKey) -eq $true) {
298: Write-Host "Success" -ForegroundColor Yellow
299: } else {
300: Write-Host "Failed" -ForegroundColor Red
301: $Success = $false
302: }
303: #HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\OpenWithList
304: $OpenWithList = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\OpenWithList"
305: Write-Host "Registering HKCU OpenWithList....." -NoNewline
306: New-Item -Path $OpenWithList -Force | Out-Null
307: New-ItemProperty -Path $OpenWithList -Name "a" -Value "CMTrace.exe" -PropertyType String -Force | Out-Null
308: New-ItemProperty -Path $OpenWithList -Name "b" -Value "NOTEPAD.EXE" -PropertyType String -Force | Out-Null
309: New-ItemProperty -Path $OpenWithList -Name "MRUList" -Value "ab" -PropertyType String -Force | Out-Null
310: $TestKeyA = Get-ItemProperty -Path $OpenWithList -Name 'a' -ErrorAction SilentlyContinue
311: $TestKeyB = Get-ItemProperty -Path $OpenWithList -Name 'b' -ErrorAction SilentlyContinue
312: $TestKeyMRUList = Get-ItemProperty -Path $OpenWithList -Name 'MRUList' -ErrorAction SilentlyContinue
313: If (($TestKeyA.a -eq "CMTrace.exe") -and ($TestKeyB.b -eq "NOTEPAD.EXE") -and ($TestKeyMRUList.MRUList -eq "ab")) {
314: Write-Host "Success" -ForegroundColor Yellow
315: } else {
316: Write-Host "Failed" -ForegroundColor Red
317: $Success = $false
318: }
319: #HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\OpenWithProgids
320: $OpenWithProgids = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\OpenWithProgids"
321: Write-Host "Registering HKCU OpenWithProgids....." -NoNewline
322: New-Item -Path $OpenWithProgids -Force | Out-Null
323: New-ItemProperty -Path $OpenWithProgids -Name "txtfile" -PropertyType Binary -Force | Out-Null
324: New-ItemProperty -Path $OpenWithProgids -Name "Log.File" -PropertyType Binary -Force | Out-Null
325: #HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\UserChoice
326: $UserChoice = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.log\UserChoice"
327: Write-Host "Setting CMTrace as default viewer....." -NoNewline
328: New-Item -Path $UserChoice -Force | Out-Null
329: New-ItemProperty -Path $UserChoice -Name "Progid" -Value "Applications\CMTrace.exe" -PropertyType String -Force | Out-Null
330: $TestKey = Get-ItemProperty -Path $UserChoice -Name "Progid"
331: If ($TestKey.Progid -eq "Applications\CMTrace.exe") {
332: Write-Host "Success" -ForegroundColor Yellow
333: } else {
334: Write-Host "Failed" -ForegroundColor Red
335: $Success = $false
336: }
337: Return $Success
338: }
339:
340: function Register-CMTraceToHKLM {
341: <#
342: .SYNOPSIS
343: Add CMTrace registry keys to the HKLM
344:
345: .DESCRIPTION
346: This will associate CMTrace with .log files within the HKLM hive
347:
348: .NOTES
349: Additional information about the function.
350: #>
351:
352: [CmdletBinding()][OutputType([boolean])]
353: param ()
354:
355: $Success = $true
356: $LogFileRegKey = "HKLM:\SOFTWARE\Classes\Logfile\Shell\Open\Command"
357: If ((Test-Path $LogFileRegKey) -eq $true) {
358: Remove-Item -Path "HKLM:\SOFTWARE\Classes\Logfile" -Recurse -Force
359: }
360: Write-Host 'Register HKLM Logfile Classes Root.....' -NoNewline
361: New-Item -Path $LogFileRegKey -Force | Out-Null
362: New-ItemProperty -Path $LogFileRegKey -Name '(Default)' -Value $InstallLocation -Force | Out-Null
363: $TestKey = Get-ItemProperty -Path $LogFileRegKey -Name '(Default)' -ErrorAction SilentlyContinue
364: If ($TestKey.'(Default)' -eq $InstallLocation) {
365: Write-Host 'Success' -ForegroundColor Yellow
366: } else {
367: Write-Host 'Failed' -ForegroundColor Red
368: $Success = $false
369: }
370: Return $Success
371: }
372:
373: function Set-CMTraceFileLocation {
374: <#
375: .SYNOPSIS
376: Set the CMTrace File Location
377:
378: .DESCRIPTION
379: Set the location and filename of CMTrace.exe
380:
381: .EXAMPLE
382: PS C:\> Set-CMTraceFileLocation
383:
384: .NOTES
385: Additional information about the function.
386: #>
387:
388: [CmdletBinding()][OutputType([string])]
389: param ()
390:
391: If ($InstallLocation -notlike '*CMTrace.exe*') {
392: If ($InstallLocation[$InstallLocation.count - 1] -eq '\') {
393: $NewLocation = $InstallLocation + 'CMTrace.exe'
394: } else {
395: $NewLocation = $InstallLocation + '\CMTrace.exe'
396: }
397: } else {
398: $NewLocation = $InstallLocation
399: }
400: Return $NewLocation
401: }
402:
403:
404: Set-ConsoleTitle -ConsoleTitle $PSConsoleTitle
405: Clear-Host
406: $Success = $true
407: $InstallLocation = Set-CMTraceFileLocation
408: If ($SystemInstall.IsPresent) {
409: $Status = Install-CMTraceExecutable
410: If ($Status = $false) {
411: $Success = $false
412: }
413: $Status = Register-CMTraceToHKCR
414: If ($Status = $false) {
415: $Success = $false
416: }
417: $Status = Register-CMTraceToHKLM
418: If ($Status = $false) {
419: $Success = $false
420: }
421: }
422: If ($UserConfig.IsPresent) {
423: $Status = Register-CMTraceToHKCU
424: If ($Status = $false) {
425: $Success = $false
426: }
427: }
428: If ($Success -eq $false) {
429: Exit 1
430: }
431:
Thanks for the script man, it seems like a bunch of code though to accomplish a task that should be done in a couple of lines. Do you have a stripped down block of this code without all of the prompting and host output?
ReplyDeleteIt should not prompt you if you pre-populate the parameters at the command line. Most of the code there was reusable code. The script goes through and verifies all processes required to install and register CMTrace are successful.
DeleteLove this... I have been baking CM Trace into WIMs, it's a must have for admins...
ReplyDelete