12 December 2014

Replicate Permissioning

Here is a script I have written that will replicate the permissions between two folders including all subfolders and file permissions. Execute the script and you will be prompted for the source and destination folders. It will first parse through and set folder permissions, followed by parsing through file permissions.

You can download the script here.


 <#  
 .Author  
   Mick Pletcher  
 .SYNOPSIS  
   Copy Permissions  
 .DESCRIPTION  
   This script will replication permissions for both files and folders using  
   robocopy. Change the $SourceDrive and $DestinationDrive variables to match what  
   you need to replicate.  
 #>  
   
 cls  
 $Errors = 0  
   
   
 $SourceDrive = Read-Host 'Enter source folder'  
 $DestinationDrive = Read-Host 'Enter destination folder'  
   
 #Match capitalization with directories  
 $TempDrive = Get-Item -Path $SourceDrive  
 $SourceDrive = $TempDrive.FullName  
 $TempDrive = Get-Item -Path $DestinationDrive  
 $DestinationDrive = $TempDrive.FullName  
   
 $SourceFolders = Get-ChildItem $SourceDrive -Recurse | ?{ $_.PSIsContainer }  
 $SourceFiles = Get-ChildItem $SourceDrive -Recurse -Force | where { ! $_.PSIsContainer }  
 $DestinationFolders = Get-ChildItem $DestinationDrive -Recurse | ?{ $_.PSIsContainer }  
 $DestinationFiles = Get-ChildItem $DestinationDrive -Recurse -Force | where { ! $_.PSIsContainer }  
   
 #Copy permissions for folders  
 $Output = robocopy $SourceDrive $DestinationDrive /ZB /E /LEV:0 /COPY:SOU /XF *.* /R:5 /W:5  
   
 #Verify Folder Permissions Match  
 Write-Host "Folders:"  
 Write-Host "========"  
 For ($Count=0; $Count -le $SourceFolders.Count; $Count++) {  
      If ($SourceFolders[$Count].FullName -ne $null) {  
           $SourceFolder = $SourceFolders[$Count].FullName  
           $DestinationFolder = $DestinationFolders[$Count].FullName  
           Write-Host $SourceFolder"....." -NoNewline  
           $SourceFolderACL = Get-Acl -Path $SourceFolder  
           $DestinationFolderACL = Get-Acl -Path $DestinationFolder  
           For ($Count1=0; $Count1 -le $SourceFolderACL.Access.Count; $Count1++) {  
                If ($SourceFolderACL.Access[$Count1].FileSystemRights -ne $DestinationFolderACL.Access[$Count1].FileSystemRights) {  
                     $Errors++  
                }  
           }  
           If ($Errors -eq 0) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed" -ForegroundColor Red  
           }  
      }  
      $Errors = 0  
 }  
   
 $Output = robocopy $SourceDrive $DestinationDrive /ZB /E /LEV:0 /COPY:SOU /XD *.* /R:5 /W:5  
 #Copy permissions for files  
 Write-Host "Files:"  
 Write-Host "======"  
 For ($Count=0; $Count -le $SourceFiles.Count; $Count++) {  
      If ($SourceFiles[$Count].FullName -ne $null) {  
           $SourceFile = $SourceFiles[$Count].FullName  
           $DestinationFile = $DestinationFiles[$Count].FullName  
           Write-Host $SourceFile"....." -NoNewline  
           $SourceFileACL = Get-Acl -Path $SourceFile  
           $DestinationFileACL = Get-Acl -Path $DestinationFile  
           For ($Count1=0; $Count1 -le $SourceFileACL.Access.Count; $Count1++) {  
                If ($SourceFileACL.Access[$Count1].FileSystemRights -ne $DestinationFileACL.Access[$Count1].FileSystemRights) {  
                     $Errors++  
                }  
           }  
           If ($Errors -eq 0) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed" -ForegroundColor Red  
           }  
      }  
      $Errors = 0  
 }  
   

11 December 2014

Uninstall All Printers

Recently, we upgraded our print servers and needed to reinstall all of the printers. This script will uninstall all printers. I deployed this script out and had it run as the user and a GPO reinstalled the printer with the new network location.

You can download the script from here: UninstallPrinters.ps1


 <#  
 .SYNOPSIS  
   Uninstall Printers  
 .DESCRIPTION  
   This script will uninstall all printers for a user  
 .PARAMETER <paramName>  
   <Description of script parameter>  
 .EXAMPLE  
   powershell.exe -executionpolicy bypass -file UninstallPrinters.ps1  
 #>  
   
 cls  
 $Printers = Get-WmiObject Win32_Printer  
 $EXE = $env:windir + "\system32\printui.exe"  
 $PrintUI = "/dn /n "  
 Foreach ($Printer in $Printers) {  
      If ($Printer.ShareName -ne $null) {  
           Write-Host "Uninstall"$Printer.ShareName"....." -NoNewline  
           $Parameters = $PrintUI + [char]34+ $Printer.Name + [char]34  
           $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Parameters -Wait -Passthru).ExitCode  
           If ($ErrCode -eq 0) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed" -ForegroundColor Red  
           }  
      }  
 }  
   

08 December 2014

Deployment Module

This module is designed to make automating the installation of software a breeze. It also provides logging that makes it easy to check and see if there were errors during an installation. The logging has been designed so that there is an installation log file that records all steps in the installation, an application log file that the installer creates, and finally a build.log file that records if the application was successfully installed. The build.log file provides a goto location for checking to see if all applications are installed while generating a golden image. It sequentially numbers easy application that makes it a snap to go and check if all apps are there.


The application log will give a step-by-step logging of the installation as shown below:

In order to properly install the module, it is suggested that you create the following folder: %programfiles%\windowspowershell\modules\Deployment. Next, copy the .PSD1 and PSM1 files to that folder. That is all that is needed to install the module.

The next step to using the module is the use the template I created called install.ps1. The global variables are in an array called $GlobalVariables. The function InitializeVariables is where you go in and make the appropriate modifications to the $Global:LogFile, $Global:Phase, $Global:Sequence, and $Global:Title. The Sequence is populated only if this is an installation that occurs during an image processs. If it is an image process, change Phase to Software Deployment.

Once the InitializationVariables is populated, you will insert the appropriate functions in the field that reads #<Insert Functions to install/uninstall applications>. That is all that is to this. I have been testing this out for a few months and it has made my life as an SCCM administrator much easier. I hope it does the same for you.

The module includes the following functions:


  • Copy-Files
  • Disable-WindowsFeature
  • Enable-WindowsFeature
  • Exit-PowerShell
  • Get-Architecture
  • Get-OSVersion
  • Import-RegistryFile
  • Install-EXE
  • Install-Fonts
  • Install-MSI
  • Install-MSP
  • Install-MSU
  • New-Directory
  • New-FileShortcut
  • New-LogFile
  • New-StartMenuShortcut
  • New-TaskbarShortcut
  • New-URLShortcut
  • Remove-Directory
  • Remove-DirectoryFromUserProfiles
  • Remove-File
  • Remove-FileFromUserProfiles
  • Remove-HKUKey
  • Remove-RegistryKey
  • Remove-StartMenuShortcut
  • Remove-TaskbarShortcut
  • Remove-Variables
  • Set-ConsoleTitle
  • Set-FolderPermissions
  • Set-Variables
  • Start-Task
  • Stop-Task
  • Uninstall-EXE
  • Uninstall-MSI
  • Uninstall-MSIByGUID
  • Uninstall-MSIByName
  • Wait-ProcessEnd
  • Write-LogFile

You can download the module, installer template, and manifest here:
Here is a Youtube tutorial video on how to implement the module:


03 October 2014

Windows Reboot Verification Script

The firm I work for does a weekly reboot. As we revamped our SCCM and AD, it was time to revisit the reboot process. I decided to use PowerShell in conjunction with SCCM to handle this process. To make the process easier to maintain and verify, I split it into two parts. There is the reboot script and the verification script. The reboot script creates an empty log file called NotRebooted.log and reboots the PC. It also deletes any file that is from the previous successful reboot. The verification script looks for the NotRebooted.log file and renames it to Rebooted--02-Oct-2014.log for instance. The filename tells that it was rebooted and the date it happened. This provides for an easy verification without having to search through the event viewer logs. To set this up in SCCM, I created two deployments, Reboot and RebootVerify. I setup RebootVerify to run Reboot first. Of course the Reboot is also set to look for a reboot by the program and not SCCM. That is all that is to doing this. IMO, this makes it much easier to track reboots, at least it has here where I work.

Here are the links to download the scripts:


22 August 2014

Enable Bitlocker on a Dell System

After much research and troubleshooting, here is how to enable bitlocker on a Dell system, including clearing the TPM. The documentation by Dell, Trusted Computing Group, and advice from this thread and this one say that it must be done with physical presence through the BIOS screen. There is a way to do this without having to go through the BIOS. Dell has added three additional settings in the BIOS, tpmppiacpi, tpmppipo, and tpmppidpo. If you enable all three of these settings, then you can clear the TPM ownership without having to physically go into the BIOS. There is a catch. When you clear the TPM, you will be prompted with the screenshot below if you want to accept clearing the TPM when the machine reboots. Once you hit F12, the system will continue. I didn't actually find this to be an issue because the Bitlocker process is next to the last process in the build, so once a technician hits F12, it is only a couple more minutes before the build process is complete. Here is a screenshot of what appears:

In the script that I wrote to clear the TPM, I discovered that it only requires one command to clear it. This documentation from Microsoft's developers center has the list of values for SetPhysicalPresenceRequest and what each value does. Unlike what others were posting, I found that I only needed to use value 5, which is clear TPM.

Now to the actual process. I have created a Powershell script for each step in the process with the script sequentially numbered so you know the process to execute them. Here is the process of enabling TPM, including clearing ownership with a hyperlink to each script in the process:

  1. Enable BIOS Password
  2. Restart
  3. Turn TPM On
  4. Restart
  5. Activate TPM ACPI Support
  6. Restart
  7. Activate PPI Provision
  8. Activate PPI Deprovision
  9. Restart
  10. Clear TPM Ownership
  11. Restart
  12. Activate TPM
  13. Restart
  14. Enable Bitlocker (Manual through Control Panel of MDT/SCCM Task Sequence)

21 August 2014

Windows Could Not parse or process unattend answer file for pass

This error message was caused, at least in my situation, by the addition of Internet Explorer 11 into the build. It was not integrated, but installed in the golden image as an application. When applying the golden image, the above mentioned error occurred. Luckily, this thread came up with the resolution to comment out <IEWelcomeMsg>false</IEWelcomeMsg> located in the unattend.xml file in the %deployroot%\control\<ImageName> folder. Once I did that, the issue was resolved. You can comment it out by changing the line as follows:

<IEWelcomeMsg>false</IEWelcomeMsg>

TO

<!-- <IEWelcomeMsg>false</IEWelcomeMsg> -->

18 August 2014

Transferring data between user profiles

Sometimes when you use USMT, it fails for one reason or another. This script is here to transfer user files from one profile to another. It was written so that in the event USMT fails, there is still a means to automate the transfer of user data.

The first step is to login as the end user, or have then login, on the new machine. They can log right back out. This is to create the user profile on the new PC. Once the user has done this, you can now proceed with running the script. It uses robocopy to move the files over. I have also incorporated using PSEXEC to initiate the robocopy command so that the data goes directly from the source to the destination, with no intermediary to slow down the transfer, especially if you are transferring data in a remote office. 

One more feature I have included in the script is the capability of transferring data from an old, renamed profile to a newly created profile on the same machine. 

Before you run this script, you will need to install PSEXEC at some network location for the script to use and also go through and select what you want excluded in the transfer. I have also made the transfer create a log file, which will also need to be customized to your environment. 

You can download the script from here.



 <#   
   Author: Mick Pletcher  
   Date: 04 March 2014  
   Synopsis: This script will robocopy specific user data from one profile to another on  
                   the same machine, or to a new machine. It will require user input in the following  
                 format:  
                 1) Have the user logout  
                 2) Rename the user profile to <profile>.old  
                 3) Have the user log back in  
                 1) Define Global Memory  
                 2) Get the relative path  
                 3) User input  
                      a) User profile to copy  
                     b) Is the profile to be copied to a new machine  
                     c) If yes, what is the computer name of the new machine  
                 4) Get the OS version of the source machine  
                 5) If copying to a new machine, get the OS version of destination machine  
                 6)   
 #>   
   
 #Define Global Variables  
 Set-Variable -Name AdminPassword -Scope Global -Force  
 Set-Variable -Name AdminUsername -Scope Global -Force  
 Set-Variable -Name DestinationComputer -Scope Global -Force  
 Set-Variable -Name DestinationProfile -Scope Global -Force  
 Set-Variable -Name RelativePath -Scope Global -Force  
 Set-Variable -Name SourceComputer -Scope Global -Force  
 Set-Variable -Name SourceProfile -Scope Global -Force  
   
 Function GetRelativePath {   
      $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"   
 }   
   
 Function GetUserInput {  
   
      #Define Local Memory  
      Set-Variable -Name Message -Scope Local -Force  
      Set-Variable -Name No -Scope Local -Force  
      Set-Variable -Name Options -Scope Local -Force  
      Set-Variable -Name Result -Scope Local -Force  
      Set-Variable -Name Title -Scope Local -Force  
      Set-Variable -Name Username -Scope Local -Force  
      Set-Variable -Name Yes -Scope Local -Force  
   
      $Username = Read-Host "Enter the username"  
      $Global:SourceComputer = Read-Host "Enter the computer name of the source system"  
      $Title = ""  
      $message = "Is the profile to be copied to a different machine?"  
      $Yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Copy files to profile on different machine"  
      $No = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Copy files to new profile on same machine"  
      $Options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)  
      $Result = $host.ui.PromptForChoice($title, $message, $options, 0)   
      If ($Result -eq 1) {  
           $Global:DestinationComputer = $Global:SourceComputer  
           $Global:SourceProfile = Read-Host "Enter renamed profile name"  
           $Global:SourceProfile = "\\"+$Global:SourceComputer+"\c$\users\"+$Global:SourceProfile  
           $Global:DestinationProfile = "\\"+$Global:DestinationComputer+"\c$\users\"+$Username  
      } else {  
           $Global:DestinationComputer = Read-Host "Enter the computer name of the new machine"  
           #$Global:SourceProfile = $Env:systemdrive+"\users\"+$Username  
           $Global:SourceProfile = $Username  
           $Global:DestinationProfile = "\\"+$Global:DestinationComputer+"\c$\users\"+$Username  
   
      }  
      $Global:AdminUsername = Read-Host "Enter administrator username"  
      $Global:AdminPassword = Read-Host -AsSecureString "Enter administrator account password"  
      $Global:AdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Global:AdminPassword))  
      $Global:AdminUsername = "[Domain]\"+$Global:AdminUsername  
   
      #Cleanup Local Memory  
      Remove-Variable -Name Message -Scope Local -Force  
      Remove-Variable -Name No -Scope Local -Force  
      Remove-Variable -Name Options -Scope Local -Force  
      Remove-Variable -Name Result -Scope Local -Force  
      Remove-Variable -Name Title -Scope Local -Force  
      Remove-Variable -Name Username -Scope Local -Force  
      Remove-Variable -Name Yes -Scope Local -Force  
   
 }  
   
 Function RoboCopyFiles {  
   
      #Define Local Memory  
      Set-Variable -Name ErrCode -Scope Local -Force  
      Set-Variable -Name ExcludeDir -Scope Local -Force  
      Set-Variable -Name ExcludeFiles -Scope Local -Force  
      Set-Variable -Name EXE -Scope Local -Force  
      Set-Variable -Name Logs -Scope Local -Force  
      Set-Variable -Name Parameters -Scope Local -Force  
      Set-Variable -Name RemoteExec -Scope Local -Force  
      Set-Variable -Name Robocopy -Scope Local -Force  
      Set-Variable -Name Switches -Scope Local -Force  
   
      $EXE = "\\BNASANIS01\SupportServices\Tools\PSTools\PsExec.exe"  
      $RemoteExec = "\\"+$Global:SourceComputer+[char]32+"-accepteula -u $Global:AdminUsername -p $Global:AdminPassword"+[char]32  
      $Switches = [char]32+"/e /eta /r:1 /w:0"  
      $ExcludeDir = [char]32+"/xd AppData Application* Downloads LocalService *Games* NetworkService *Links* *temp *TEMPOR~1 *cache Local*"  
      $ExcludeFiles = [char]32+"/xf ntuser.* *.exd *.nk2 *.srs extend.dat *cache* *.oab index.* {* *.ost UsrClass.* SharePoint*.pst history* *tmp*"  
      $Logs = [char]32+"/log:"+$Env:windir+"\waller\Logs\ApplicationLogs\ProfileCopy.log"  
      $Parameters = $Switches+$ExcludeDir+$ExcludeFiles+$Logs  
      $Arguments = $RemoteExec+$Env:windir+"\system32\robocopy.exe"+[char]32+$Env:systemdrive+"\users\"+$Global:SourceProfile+[char]32+$Global:DestinationProfile+$Parameters  
      $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Arguments -Wait -Passthru).ExitCode  
   
      #Cleanup Local Memory  
      Remove-Variable -Name ErrCode -Scope Local -Force  
      Remove-Variable -Name ExcludeDir -Scope Local -Force  
      Remove-Variable -Name ExcludeFiles -Scope Local -Force  
      Remove-Variable -Name EXE -Scope Local -Force  
      Remove-Variable -Name Logs -Scope Local -Force  
      Remove-Variable -Name Parameters -Scope Local -Force  
      Remove-Variable -Name RemoteExec -Scope Local -Force  
      Remove-Variable -Name Robocopy -Scope Local -Force  
      Remove-Variable -Name Switches -Scope Local -Force  
   
 }  
   
 Function CopyFiles ($FileSource,$FileDest,$FileFilter) {  
      $Dest = $FileDest  
      $Files = Get-ChildItem $FileSource -Filter $FileFilter  
      If ($Files.Count -eq $null) {  
           Write-Host "Copy "$Files.Name"....." -NoNewline  
           Copy-Item $Files.FullName -Destination $Dest -Force  
           $Test = $Dest + "\"+$Files.Name  
           If (Test-Path $Test) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed" -ForegroundColor Red  
           }  
      } else {  
           For ($i = 0; $i -lt $Files.Count; $i++) {  
                $File = $Files[$i].FullName  
                Write-Host "Copy"$Files[$i].Name"....." -NoNewline  
                Copy-Item $File -Destination $Dest -Force  
                $Test = $Dest + "\"+$Files[$i].Name  
                If (Test-Path $Test) {  
                     Write-Host "Success" -ForegroundColor Yellow  
                } else {  
                     Write-Host "Failed" -ForegroundColor Red  
                }  
           }  
      }  
 }  
   
 cls  
 GetRelativePath  
 GetUserInput  
 RoboCopyFiles  
 #Copy Outlook Signatures  
 $TempSource = "\\"+$SourceComputer+"\c$\users\"+$SourceProfile+"\AppData\Roaming\Microsoft\Signatures"  
 $TempDestination = "\\"+$DestinationComputer+"\c$\users\"+$DestinationProfile+"\AppData\Roaming\Microsoft\Signatures"  
 CopyFiles $TempSource $TempDestination "*.*"  
   

13 August 2014

Removing Outlook Data Files

Automating the removal of Outlook data files is a tedious process that is difficult to automate. The registry key is a data hash that is unique on each system. Here is a script I wrote that will do just that. This script will remove the data file from Outlook when run under the end-user's credentials. The script parses through the HKU and removes the registry entry for that key. The complete description is in the code below and you can download it from here.


 <#  
 .Author  
      Mick Pletcher  
 .SYNOPSIS  
   Outlook Data Folder  
 .DESCRIPTION  
   This script will remove the Outlook data folder. In order to use this script,  
   you will need to obtain the powershell translated hexadecimal key. The very first  
   thing to do is to go into regedit and manually find the registry key associated with  
   the outlook data folder. You do this by opening up each registry key and to the right  
   is the ASCII translated data. Once you have found this, the next thing to do is to note  
   the name of the key containing the data. Now run the GetHKUBinaryKeyValue function with  
   the DeleteHKUBinaryKeyValue commented out. This will generate the list of keys and  
   give you the translated value that PowerShell is reading. copy the translated value. Now  
   comment out the GetHKUBinaryKeyValue and uncomment the DeleteHKUBinaryKeyValue. Pass the  
   translated value into the function as the second variable. You can see the examples below.  
   This is intended to run as the end user. I ended up running it via a GPO as the user, under  
   their credentials. It worked like a charm.  
 .EXAMPLE  
      GetHKUBinaryKeyValue "Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Default Outlook Profile"  
      DeleteHKUBinaryKeyValue "Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Default Outlook Profile" "101 0 68 0 79 0 67 0 83 0 32 0 68 0 77 0 0 0"  
 #>  
   
 Function GetHKUBinaryKeyValue ($RegKey, $KeyVal) {  
      Set-Variable -Name HKUsers -Scope Local -Force  
        
      Set-Variable -Name i -Scope Local -Force  
      Set-Variable -Name Key -Scope Local -Force  
      Set-Variable -Name SubKey -Scope Local -Force  
      Set-Variable -Name SubKeys -Scope Local -Force  
      Set-Variable -Name Temp -Scope Local -Force  
      Set-Variable -Name Value -Scope Local -Force  
        
      $Temp = New-PSDrive HKU Registry HKEY_USERS  
      $HKUsers = Get-ChildItem HKU:\ -ErrorAction SilentlyContinue  
      ForEach ($User in $HKUsers) {  
           [string]$Key = $User.Name  
           $Key = $Key -replace "HKEY_USERS", "HKU:"  
           $Key = $Key+"\"+$RegKey  
           If (Test-Path $Key) {  
                $Subkeys = Get-ChildItem $Key -ErrorAction SilentlyContinue  
                Foreach ($SubKey in $SubKeys) {  
                     Write-host $SubKey  
                     For ($i=0; $i -lt $Subkey.ValueCount; $i++) {  
                          [string]$Value = $Subkey.GetValue($Subkey.Property[$i])  
                          Write-Host "  "$Subkey.Property[$i]" : "$Value  
                          If ($Value -eq $KeyVal) {  
                               $DeleteKey = $true  
                          }  
                     }  
                     Write-Host  
                }  
           }  
      }  
   
      Remove-Variable -Name HKUsers -Scope Local -Force  
      Remove-Variable -Name i -Scope Local -Force  
      Remove-Variable -Name Key -Scope Local -Force  
      Remove-Variable -Name SubKey -Scope Local -Force  
      Remove-Variable -Name SubKeys -Scope Local -Force  
      Remove-Variable -Name Temp -Scope Local -Force  
      Remove-Variable -Name Value -Scope Local -Force  
 }  
   
 Function DeleteHKUBinaryKeyValue ($RegKey, $KeyVal) {  
      Set-Variable -Name HKUsers -Scope Local -Force  
      Set-Variable -Name i -Scope Local -Force  
      Set-Variable -Name Key -Scope Local -Force  
      Set-Variable -Name SubKey -Scope Local -Force  
      Set-Variable -Name SubKeys -Scope Local -Force  
      Set-Variable -Name Temp -Scope Local -Force  
      Set-Variable -Name Value -Scope Local -Force  
        
      $Temp = New-PSDrive HKU Registry HKEY_USERS  
      $HKUsers = Get-ChildItem HKU:\ -ErrorAction SilentlyContinue  
      ForEach ($User in $HKUsers) {  
           [string]$Key = $User.Name  
           $Key = $Key -replace "HKEY_USERS", "HKU:"  
           $Key = $Key+"\"+$RegKey  
           If (Test-Path $Key) {  
                $Subkeys = Get-ChildItem $Key -ErrorAction SilentlyContinue  
                Foreach ($SubKey in $SubKeys) {  
                     For ($i=0; $i -lt $Subkey.ValueCount; $i++) {  
                          [string]$Value = $Subkey.GetValue($Subkey.Property[$i])  
                          If ($Value -eq $KeyVal) {  
                               $DeleteKey = $true  
                          }  
                     }  
                     If ($DeleteKey -eq $true) {  
                          [string]$SubKey1 = $SubKey  
                          $SubKey1 = $SubKey1 -replace "HKEY_USERS", "HKU:"  
                          If (Test-Path $SubKey1) {  
                               Remove-Item $SubKey1 -Force  
                          }  
                          $DeleteKey = $false  
                     }  
                }  
           }  
      }  
   
      Remove-Variable -Name HKUsers -Scope Local -Force  
      Remove-Variable -Name i -Scope Local -Force  
      Remove-Variable -Name Key -Scope Local -Force  
      Remove-Variable -Name SubKey -Scope Local -Force  
      Remove-Variable -Name SubKeys -Scope Local -Force  
      Remove-Variable -Name Temp -Scope Local -Force  
      Remove-Variable -Name Value -Scope Local -Force  
 }  
   
 cls  
 #GetHKUBinaryKeyValue "Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Default Outlook Profile"  
 DeleteHKUBinaryKeyValue "Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Default Outlook Profile" "101 0 68 0 79 0 67 0 83 0 32 0 68 0 77 0 0 0"  
   

05 August 2014

Moving a Computer to different OUs through using PowerShell scripts

NOTE: You can find the new methodology and code in my later post located here

I know there have been a lot of blogs out here showing how to move a computer to an OU, but I have taken a different approach. This is a suitable process for a small to mid-size company that doesn't have a lot of OUs to move machines to during a build. If it is a company the size of HCA, Dell, GM, etc., this isn't a good process because they likely have hundreds of OUs and you would be creating hundreds of PowerShell scripts. The way this process works is that the PowerShell script does not read anything from MDT or SCCM. It is executed, but does the move process on the system and not through MDT or SCCM.

The first thing to do is to get a drop-down window for the organization unit prompt under the join domain portion of the MDT setup process. Andrew provides two different ways of doing this. I ended up using the first one by applying the settings to the customsettings.ini file. When populating this field, it is going to be for informational purposes only. The field itself does not move a system to the new, selected OU.

The next thing to do is to create a separate PowerShell script for each OU you want to move a machine to. This is a straightforward process. The script below is what I wrote and use. All you have to do is to change the $NewOU variable to whatever OU you desire.

 Set-Variable -Name CurrentOU -Scope Global -Force  
 Set-Variable -Name NewOU -Scope Global -Force  
   
 cls  
 Import-Module activedirectory  
 [string]$NewOU = "OU=BNA, OU=Computers, OU=Front Office, DC=ACME, DC=COM"  
 $CurrentOU = get-adcomputer $env:computername  
 Write-Host "Computer Name:"$env:computername  
 Write-Host "Current OU:"$CurrentOU  
 Write-Host "Target OU:"$NewOU  
 Move-ADObject -identity $CurrentOU -TargetPath $NewOU  
 $CurrentOU = get-adcomputer $env:computername  
 Write-Host "New OU:"$CurrentOU  
   

You can download this script from my GitHub site located here.

This script does require that remote server administration toolkit is installed and the AD PowerShell feature is enabled. That is what the import-module activedirectory requires. If your security is setup correctly, users will not be able to see or do anything even if they go in and enable other features in RSAT. The list below are the commands for enabling the AD PowerShell on the machines. This really comes in handy for other uses. I am currently deploying a huge upgrade package that requires users be moved to new OUs once the package is installed. RSAT has given me that capability.

 dism.exe /online /enable-feature /featurename:RemoteServerAdministrationTools  
 dism.exe /online /enable-feature /featurename:RemoteServerAdministrationTools-Roles  
 dism.exe /online /enable-feature /featurename:RemoteServerAdministrationTools-Roles-AD  
 dism.exe /online /enable-feature /featurename:RemoteServerAdministrationTools-Roles-AD-Powershell  
   

The next step is to create the MDT or SCCM Applications. The way to do this is to go in and create an application for each OU to execute the powershell script associated with that OU. The catch is that the powershell script will not move the machine under the credentials of MDT because it uses the system account for installing applications and it will not have access to AD. To get around this, you will need to use psexec to run the powershell script as a different user. Here is the command line I use to execute the scripts from an MDT Application:

 \\NetworkLocationOfPsexec\psexec \\%computername% -accepteula -u domain\username -p Password cmd.exe /c "echo . | powershell.exe -executionpolicy bypass -file \\NetworkLocationOfPowerShellScript\MoveOU_AUS.ps1"  
   

The final step is to put the applications into the task sequence. I created a folder and put an individual application task for each OU and associated the matching application with it. Here is an example:



You will need to filter each task sequence by creating a conditional statement in the options of the task sequence application. You will create a Task sequence variable, use MachineObjectOU, and associate with the matching OU in the customsettings.ini file. This will limit them to run only if the selected OU in the Windows Deployment Wizard matches.

That is everything you need to do to get this process to work. 

25 July 2014

MSI Error 1325: is not a valid short file name

This error in my case was being caused because the MSI was being executed through SCCM. The MSI file had to be executed locally and not from a network source. It would install with no issues if you double-clicked on the MSI. It only happened when SCCM tried to install it. During my troubleshooting, I tried a few different alternatives:

  • I use a PowerShell script to install the package. I thought it could be causing the issue, so I created a new SCCM package that only executed the MSI with the following command line, but the error persisted: msiexec.exe /I iDocID_for_32bit_Office.msi /qb-
  • I created a GPO that installed the MSI

These options did not resolve the issue. I then decided that if the issue was because the MSI needs to execute locally, then why not use psexec? I created the following command line to incorporate into an SCCM program. It failed the first time I ran it. The second time was successful after I went back into the environment tab and ran it with user rights. Basically this executes the package on the local machine under the user profile of the logged on user but runs the installer with the SCCM admin account. This resolved my issue.


\\    <network share>\psexec.exe \\%computername% -accepteula -u <username> -p <password> cmd.exe /c "echo . | powershell.exe -executionpolicy bypass -file <network share>\install.ps1"

07 July 2014

Adjust Screen Resolution during Build

Sometimes the screen resolution in a build does not set to the maximum. Resolution can be set with PowerShell, but the scripting requirements and complexity is too much, IMO. AutoIT offers an easy way to automate this process. I have written this script to do just that. There is documentation within the script. You will need to have the AutoIT compiler for this. Here is the link to download it.


 #Region ;**** Directives created by AutoIt3Wrapper_GUI ****  
 #AutoIt3Wrapper_Outfile=install.exe  
 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****  
 ; Open Screen Resolution  
 Run( "control desk.cpl" )  
 Sleep( 2000 )  
 ; Tab to Resolution  
 Send( "{TAB}" )  
 Sleep( 250 )  
 Send( "{TAB}" )  
 Sleep( 250 )  
 ; Open Resolution Drop Down  
 Send( "{Enter}" )  
 Sleep( 250 )  
 ; Move Resolution Up to max. You may need to add more up arrows.  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 Send( "{UP}" )  
 Sleep( 250 )  
 ; Accept resolution  
 Send( "{Enter}" )  
 Sleep( 250 )  
 ; Move to OK button  
 Send( "{TAB}" )  
 Sleep( 250 )  
 Send( "{TAB}" )  
 Sleep( 250 )  
 Send( "{TAB}" )  
 Sleep( 250 )  
 Send( "{TAB}" )  
 Sleep( 250 )  
 Send( "{TAB}" )  
 Sleep( 250 )  
 ; Apply New Resolution  
 Send( "{Enter}" )  
 Sleep( 5000 )  
 ; Accept New Resolution  
 Send( "k" )  
   

27 June 2014

SCCM Client Installer

Installing the SCCM client takes a few minutes. This script was written so that it will wait for the ccmsetup.exe to complete. I have encountered issues with the setup not completing before the system reboots during a build process. That is the reason I wrote this script. There are verifications in this script and it does write a log file. If you don't want the logs, just remove those parts of the script. This script was originally written for SCCM 2007, but it will work on 2012 too. You can download it from here.


 <#  
 .NAME  
   Mick Pletcher  
 .DATE  
   13 June 2014  
 .SYNOPSIS  
   SCCM 2007  
 .DESCRIPTION  
   <A detailed description of the script>  
 .PARAMETER <paramName>  
   <Description of script parameter>  
 .EXAMPLE  
   <An example of using the script>  
 #>  
   
 #Declare Global Memory  
 Set-Variable -Name BuildLog -Scope Global -Force  
 Set-Variable -Name Errors -Value $null -Scope Global -Force  
 Set-Variable -Name LogFile -Scope Global -Force  
 Set-Variable -Name RelativePath -Scope Global -Force  
 Set-Variable -Name Sequence -Scope Global -Force  
 Set-Variable -Name Title -Scope Global -Force  
   
 Function DeclareGlobalVariables {  
      $Global:BuildLog = $Env:windir+"\Logs\BuildLogs\Build.log"  
      $Global:LogFile = $Env:windir+"\Logs\BuildLogs\SCCM2007Client.log"  
      $Global:Sequence = "01"  
      $Global:Title = "SCCM 2007 Client"  
 }  
   
 Function ConsoleTitle ($Title){  
      $host.ui.RawUI.WindowTitle = $Title  
 }  
   
 Function GetRelativePath {   
      $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"   
 }  
   
 Function UninstallMSI ($ProgName,$GUID) {  
      $EXE = $Env:windir+"\system32\msiexec.exe"  
      $Switches = [char]32+"/qb- /norestart"  
      $Parameters = "/x "+$GUID+$Switches  
      $Output = "Uninstall"+$ProgName+"....."  
      Write-Host "Uninstall"$ProgName"....." -NoNewline  
      $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Parameters -Wait -Passthru).ExitCode  
      If (($ErrCode -eq 0) -or ($ErrCode -eq 3010)) {  
           $Output = $Output+"Success"  
           Write-Host "Success" -ForegroundColor Yellow  
      } elseIf ($ErrCode -eq 1605) {  
           $Output = $Output+"Not Present"  
           Write-Host "Not Present" -ForegroundColor Green  
      } else {  
           $Output = $Output+"Failed with error code "+$ErrCode  
           Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
           $Global:Errors++  
      }  
      Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force  
 }  
   
 Function InstallMSI ($ProgName,$MSI,$Switches) {  
      $EXE = $Env:windir+"\system32\msiexec.exe"  
      $Parameters = "/i "+[char]34+$MSI+[char]34+[char]32+$Switches  
      $Output = "Install"+$ProgName+"....."  
      Write-Host "Install"$ProgName"....." -NoNewline  
      $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Parameters -Wait -Passthru).ExitCode  
      If (($ErrCode -eq 0) -or ($ErrCode -eq 3010)) {  
           $Output = $Output+"Success"  
           Write-Host "Success" -ForegroundColor Yellow  
      } else {  
           $Output = $Output+"Failed with error code "+$ErrCode  
           Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
           $Global:Errors++  
      }  
      Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force  
 }  
   
 Function InstallEXE ($ProgName,$EXE,$Switches){  
      $Output = "Install "+$ProgName+"....."  
      Write-Host "Install "$ProgName"....." -NoNewline  
      $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Switches -Wait -Passthru).ExitCode  
      If (($ErrCode -eq 0) -or ($ErrCode -eq 3010)) {  
           $Output = $Output+"Success"  
           Write-Host "Success" -ForegroundColor Yellow  
      } else {  
           $Output = $Output+"Failed with error code "+$ErrCode  
           Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
           $Global:Errors++  
      }  
      Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force  
 }  
   
 Function InstallMSP ($ProgName,$MSP,$Switches) {  
      $EXE = $Env:windir+"\system32\msiexec.exe"  
      $Parameters = "/p "+[char]34+$MSP+[char]34+[char]32+$Switches  
      $Output = "Install"+$ProgName+"....."  
      Write-Host "Install"$ProgName"....." -NoNewline  
      $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Parameters -Wait -Passthru).ExitCode  
      If (($ErrCode -eq 0) -or ($ErrCode -eq 3010)) {  
           $Output = $Output+"Success"  
           Write-Host "Success" -ForegroundColor Yellow  
      } else {  
           $Output = $Output+"Failed with error code "+$ErrCode  
           Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
           $Global:Errors++  
      }  
      Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force  
 }  
   
 Function WaitForProcessEnd ($Process) {  
      $Proc = Get-Process $Process -ErrorAction SilentlyContinue  
      $Output = "Waiting for"+$Process+"to complete....."  
      Write-Host "Waiting for"$Process" to complete....." -NoNewline  
      If ($Proc -ne $null) {  
           Do {  
                Start-Sleep -Seconds 5  
                $Proc = Get-Process $Process -ErrorAction SilentlyContinue  
           } While ($Proc -ne $null)  
           $Output = $Output+"Completed"  
           Write-Host "Completed" -ForegroundColor Yellow  
      } else {  
           $Output = $Output+"Already Completed"  
           Write-Host "Already Completed" -ForegroundColor Yellow  
      }  
      Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force  
 }  
   
 Function ProcessLogFile {  
      If ((Test-Path $Env:windir"\Logs") -eq $false) {  
           New-Item -ItemType Directory -Path $Env:windir"\Logs"  
      }  
      If ((Test-Path $Env:windir"\Logs\ApplicationLogs") -eq $false) {  
           New-Item -ItemType Directory -Path $Env:windir"\Logs\ApplicationLogs"  
      }  
      If ((Test-Path $Env:windir"Logs\BuildLogs") -eq $false) {  
           New-Item -ItemType Directory -Path $Env:windir"\Logs\BuildLogs"  
      }  
      If ($Global:Errors -eq $null) {  
           If (Test-Path $Global:LogFile) {  
                Remove-Item $Global:LogFile -Force  
           }  
           $File1 = $Global:LogFile.Split(".")  
           $Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]  
           If (Test-Path $Filename1) {  
                Remove-Item $Filename1 -Force  
           }  
           $Global:Errors = 0  
      } elseIf ($Global:Errors -ne 0) {  
           If (Test-Path $Global:LogFile) {  
                $Global:LogFile.ToString()  
                $File1 = $Global:LogFile.Split(".")  
                $Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]  
                Rename-Item $Global:LogFile -NewName $Filename1 -Force  
           }  
      } else {  
           $LogTitle = $Global:Sequence+" - "+$Global:Title  
           Out-File -FilePath $Global:BuildLog -InputObject $LogTitle -Append -Force  
      }  
 }  
   
 cls  
 DeclareGlobalVariables  
 GetRelativePath  
 ConsoleTitle $Global:Title  
 ProcessLogFile  
 UninstallMSI "Microsoft SCCM 2007 Client" $Global:RelativePath"i386\client.msi"  
 InstallMSI "Microsoft XML 6" $Global:RelativePath"i386\msxml6.msi" "/qb- /norestart"  
 InstallEXE "Microsoft SCCM 2007" $Global:RelativePath"ccmsetup.exe" "SMSSITECODE=ENT SMSCACHESIZE=5120"  
 WaitForProcessEnd "CCMSETUP"  
 InstallMSP "KB977203" $Global:RelativePath"i386\sccm2007ac-sp2-kb977203-x86.msp" "/qb- /norestart"  
 InstallMSP "KB2659258" $Global:RelativePath"i386\sccm2007ac-sp2-kb2659258-x86-enu.msp" "/qb- /norestart"  
 ProcessLogFile  
 Start-Sleep -Seconds 5  
   

Pinning Shortcuts to the Taskbar and Start Menu

There are already scripts out there that will do this, but I have taken it a little further. I have added checking to make sure the application is installed first so that the script does not error out. I have also added on-screen display to show if it was successful or not. I originally started off of the answer here and then expanded. One weird thing I encountered while writing this was that it treated excel 2010 differently than all other shortcuts. That is why you will see the extra three lines of code specifically for excel. You can download the script from here.

You can download the script from here.

There is a newer version located here.


 <#  
 .NAME  
   Mick Pletcher  
 .DATE  
   11 May 2014  
 .SYNOPSIS  
   Taskbar Shortcuts  
 .DESCRIPTION  
   Create taskbar shortcuts  
 .PARAMETER <paramName>  
   <Description of script parameter>  
 .EXAMPLE  
   <An example of using the script>  
 #>  
   
 #Declare Global Memory  
 Set-Variable -Name Architecture -Scope Global -Force  
 Set-Variable -Name RelativePath -Scope Global -Force  
 Set-Variable -Name Title -Value "Application Shortcuts" -Scope Global -Force  
   
 Function ConsoleTitle ($Title){  
      $host.ui.RawUI.WindowTitle = $Title  
 }  
   
 Function GetRelativePath {   
      $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"   
 }  
   
 Function GetArchitecture {  
      $Global:Architecture = Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture  
      $Global:Architecture = $Global:Architecture.OSArchitecture  
      #Returns 32-bit or 64-bit  
 }  
   
 Function PinToStartMenu ($AppName,$PinnedApp,$App) {  
      Write-Host "Pin"$AppName" on Start Menu....." -NoNewline  
      If ((Test-Path $App) -eq $true) {  
           If ((Test-Path $PinnedApp) -eq $false) {  
                $sa = new-object -c shell.application  
                $AppSplit = $App.split("\")  
                $AppSplitCount = $AppSplit.Count  
                $Filename = $AppSplit[$AppSplitCount-1]  
                For ($i=0; $i -lt $AppSplitCount-1) {  
                     $DirectoryPath = $DirectoryPath+$AppSplit[$i]  
                     If ($i -ne $AppSplitCount-2) {  
                          $DirectoryPath = $DirectoryPath+"\"  
                     }  
                     $i++  
                }  
                $pn = $sa.namespace($DirectoryPath).parsename($Filename)  
                $pn.invokeverb('startpin')  
                If ((Test-Path $PinnedApp) -eq $true) {  
                     Write-Host "Success" -ForegroundColor Yellow  
                } else {  
                     Write-Host "Failed " -ForegroundColor Red  
                }  
           } else {  
                Write-Host "Already Present" -ForegroundColor Yellow  
           }  
      } else {  
           Write-Host "Application not installed" -ForegroundColor Green  
      }  
 }  
   
 Function PinToTaskbar ($AppName,$PinnedApp,$App) {  
      Write-Host "Pin"$AppName" to Taskbar....." -NoNewline  
      If ((Test-Path $App) -eq $true) {  
           If ((Test-Path $PinnedApp) -eq $false) {  
                $sa = new-object -c shell.application  
                $AppSplit = $App.split("\")  
                $AppSplitCount = $AppSplit.Count  
                $Filename = $AppSplit[$AppSplitCount-1]  
                For ($i=0; $i -lt $AppSplitCount-1) {  
                     $DirectoryPath = $DirectoryPath+$AppSplit[$i]  
                     If ($i -ne $AppSplitCount-2) {  
                          $DirectoryPath = $DirectoryPath+"\"  
                     }  
                     $i++  
                }  
                $pn = $sa.namespace($DirectoryPath).parsename($Filename)  
                $pn.invokeverb('taskbarpin')  
                If ((Test-Path $PinnedApp) -eq $true) {  
                     Write-Host "Success" -ForegroundColor Yellow  
                } else {  
                     Write-Host "Failed " -ForegroundColor Red  
                }  
           } else {  
                Write-Host "Already Present" -ForegroundColor Yellow  
           }  
      } else {  
           Write-Host "Application not installed" -ForegroundColor Green  
      }  
 }  
   
 Function UnpinFromStartMenu ($AppName,$PinnedApp,$App) {  
      Write-Host "Unpin"$AppName" from Start Menu....." -NoNewline  
      If ((Test-Path $PinnedApp) -eq $true) {  
           $sa = new-object -c shell.application  
           $AppSplit = $App.split("\")  
           $AppSplitCount = $AppSplit.Count  
           $Filename = $AppSplit[$AppSplitCount-1]  
           For ($i=0; $i -lt $AppSplitCount-1) {  
                $DirectoryPath = $DirectoryPath+$AppSplit[$i]  
                If ($i -ne $AppSplitCount-2) {  
                     $DirectoryPath = $DirectoryPath+"\"  
                }  
                $i++  
           }  
           $pn = $sa.namespace($DirectoryPath).parsename($Filename)  
           $pn.invokeverb('startunpin')  
           If ((Test-Path $PinnedApp) -eq $false) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed " -ForegroundColor Red  
           }  
      } else {  
           Write-Host "Already Removed" -ForegroundColor Yellow  
      }  
 }  
   
 Function UnpinFromTaskbar ($AppName,$PinnedApp,$App) {  
      Write-Host "Unpin"$AppName" from Taskbar....." -NoNewline  
      If ((Test-Path $PinnedApp) -eq $true) {  
           $AppSplit = $App.split("\")  
           $AppSplitCount = $AppSplit.Count  
           $Filename = $AppSplit[$AppSplitCount-1]  
           $DirectoryPath = $App.Trim($Filename)  
           $DirectoryPath = $DirectoryPath.Trim("\")  
           If ($Filename -eq "EXCEL.EXE") {  
                $DirectoryPath = "c"+$DirectoryPath  
           }  
           $sa = new-object -c shell.application  
           $pn = $sa.namespace($DirectoryPath).parsename($Filename)  
           $pn.invokeverb('taskbarunpin')  
           If ((Test-Path $PinnedApp) -eq $false) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed " -ForegroundColor Red  
           }  
      } else {  
           Write-Host "Already Removed" -ForegroundColor Yellow  
      }  
 }  
   
 cls  
 GetRelativePath  
 ConsoleTitle $Global:Title  
 GetArchitecture  
 If ($Global:Architecture -eq "32-bit") {  
      UnpinFromStartMenu "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Outlook.lnk" "C:\Program Files\Microsoft Office\Office14\OUTLOOK.EXE"  
      UnpinFromStartMenu "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Word.lnk" "C:\Program Files\Microsoft Office\Office14\WINWORD.EXE"  
      UnpinFromStartMenu "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Excel.lnk" "C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"  
      UnpinFromStartMenu "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft PowerPoint.lnk" "C:\Program Files\Microsoft Office\Office14\POWERPNT.EXE"  
      UnpinFromStartMenu "eDocs DM" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Open Text eDocs Email Marker.lnk" "C:\Program Files\Open Text\Email Filing\DMMarkEmail.exe"  
      PinToStartMenu "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Outlook.lnk" "C:\Program Files\Microsoft Office\Office14\OUTLOOK.EXE"  
      PinToStartMenu "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Word.lnk" "C:\Program Files\Microsoft Office\Office14\WINWORD.EXE"  
      PinToStartMenu "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Excel.lnk" "C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"  
      PinToStartMenu "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft PowerPoint.lnk" "C:\Program Files\Microsoft Office\Office14\POWERPNT.EXE"  
      UnpinFromTaskbar "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Outlook 2010.lnk" "C:\Program Files\Microsoft Office\Office14\OUTLOOK.EXE"  
      UnpinFromTaskbar "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Word 2010.lnk" "C:\Program Files\Microsoft Office\Office14\WINWORD.EXE"  
      UnpinFromTaskbar "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Excel 2010.lnk" "C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"  
      UnpinFromTaskbar "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft PowerPoint 2010.lnk" "C:\Program Files\Microsoft Office\Office14\POWERPNT.EXE"  
      PinToTaskbar "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Outlook 2010.lnk" "C:\Program Files\Microsoft Office\Office14\OUTLOOK.EXE"  
      PinToTaskbar "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Word 2010.lnk" "C:\Program Files\Microsoft Office\Office14\WINWORD.EXE"  
      PinToTaskbar "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Excel 2010.lnk" "C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"  
      PinToTaskbar "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft PowerPoint 2010.lnk" "C:\Program Files\Microsoft Office\Office14\POWERPNT.EXE"  
 } else {  
      UnpinFromStartMenu "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Outlook.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\OUTLOOK.EXE"  
      UnpinFromStartMenu "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Word.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"  
      UnpinFromStartMenu "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Excel.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE"  
      UnpinFromStartMenu "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft PowerPoint.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE"  
      PinToStartMenu "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Outlook.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\OUTLOOK.EXE"  
      PinToStartMenu "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Word.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"  
      PinToStartMenu "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft Excel.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE"  
      PinToStartMenu "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\Microsoft PowerPoint.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE"  
      UnpinFromTaskbar "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Outlook 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\OUTLOOK.EXE"  
      UnpinFromTaskbar "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Word 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"  
      UnpinFromTaskbar "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Excel 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE"  
      UnpinFromTaskbar "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft PowerPoint 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE"  
      PinToTaskbar "Outlook" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Outlook 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\OUTLOOK.EXE"  
      PinToTaskbar "Word" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Word 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"  
      PinToTaskbar "Excel" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Excel 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE"  
      PinToTaskbar "PowerPoint" $Env:APPDATA"\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft PowerPoint 2010.lnk" "C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE"  
 }  
 

29 May 2014

Enable Wake-On-LAN

NOTE: This is an old script. I have a newer and more efficient one located here.

This script will enable WOL and test to make sure it has been set. It will return whether it was a success or failure both to a log file and the screen. This script was written to also be incorporated with my new build logging process that I am getting ready to release soon. If you do not want this, just delete the buildlog and sequence variables out, along with their use in the ProcessLogFile function.


You can download the script from here.


 <#  
 .SYNOPSIS  
   Wake-On-LAN  
 .DESCRIPTION  
   Enable Wake-On-LAN  
 .PARAMETER <paramName>  
   <Description of script parameter>  
 .EXAMPLE  
   <An example of using the script>  
 #>  
 #Declare Global Memory  
 Set-Variable -Name AppLog -Scope Global -Force  
 Set-Variable -Name BuildLog -Scope Global -Force  
 Set-Variable -Name Errors -Value $null -Scope Global -Force  
 Set-Variable -Name LogFile -Scope Global -Force  
 Set-Variable -Name RelativePath -Scope Global -Force  
 Set-Variable -Name Sequence -Scope Global -Force  
 Set-Variable -Name Title -Scope Global -Force  
 Function ConsoleTitle ($Title){  
      $host.ui.RawUI.WindowTitle = $Title  
 }  
 Function DeclareGlobalVariables {  
      $Global:AppLog = "/lvx "+$Env:windir + "\Logs\ApplicationLogs\WakeOnLAN.log"  
      $Global:BuildLog = $Env:windir + "\Logs\BuildLogs\Build.log"  
      $Global:LogFile = $Env:windir + "\Logs\BuildLogs\WakeOnLAN.log"  
      $Global:Sequence = "08"  
      $Global:Title = "Wake On LAN"  
 }  
 Function GetRelativePath {   
      $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"   
 }  
 Function EnableWOL {  
      # Get all physical ethernet adaptors  
      $nics = Get-WmiObject Win32_NetworkAdapter -filter "AdapterTypeID = '0' `  
      AND PhysicalAdapter = 'true' `  
      AND NOT Description LIKE '%Centrino%' `  
      AND NOT Description LIKE '%wireless%' `  
      AND NOT Description LIKE '%virtual%' `  
      AND NOT Description LIKE '%WiFi%' `  
      AND NOT Description LIKE '%Bluetooth%'"  
      foreach ($nic in $nics) {  
           $nicName = $nic.Name  
           $Output = "NIC:"+$nicName+[char]10  
           Write-Host "NIC:"$nicName  
           $Output = $Output + "Allow the computer to turn off this device....."  
           Write-Host "Allow the computer to turn off this device....." -NoNewline  
           $nicPower = Get-WmiObject MSPower_DeviceEnable -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }  
           If ($nicPower.Enable -ne $True) {  
                $nicPower.Enable = $True  
                $Temp = $nicPower.psbase.Put()  
           }  
           If ($nicPower.Enable -eq $True) {  
                $Output = $Output + "Enabled"  
                Write-Host "Enabled" -ForegroundColor Yellow  
           } else {  
                $Output = $Output + "Failed"  
                Write-Host "Failed" -ForegroundColor Red  
           }  
           $Output = $Output + [char]10  
           $Output = $Output + "Allow this device to wake the computer....."  
           Write-Host "Allow this device to wake the computer....." -NoNewline  
           $nicPowerWake = Get-WmiObject MSPower_DeviceWakeEnable -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }  
           If ($nicPowerWake.Enable -ne $True) {  
                $nicPowerWake.Enable = $True  
                $Temp = $nicPowerWake.psbase.Put()  
           }  
           If ($nicPowerWake.Enable -eq $True) {  
                $Output = $Output + "Enabled"  
                Write-Host "Enabled" -ForegroundColor Yellow  
           } else {  
                $Output = $Output + "Failed"  
                Write-Host "Failed" -ForegroundColor Red  
           }  
           $Output = $Output + [char]10  
           $Output = $Output + "Only allow a magic packet to wake the computer....."  
           Write-Host "Only allow a magic packet to wake the computer....." -NoNewline  
           $nicMagicPacket = Get-WmiObject MSNdis_DeviceWakeOnMagicPacketOnly -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }  
           If ($nicMagicPacket.EnableWakeOnMagicPacketOnly -ne $True) {  
                $nicMagicPacket.EnableWakeOnMagicPacketOnly = $True  
                $Temp = $nicMagicPacket.psbase.Put()  
           }  
           If ($nicMagicPacket.EnableWakeOnMagicPacketOnly -eq $True) {  
                $Output = $Output + "Enabled"  
                Write-Host "Enabled" -ForegroundColor Yellow  
           } else {  
                $Output = $Output + "Failed"  
                Write-Host "Failed" -ForegroundColor Red  
           }  
      }  
      Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force  
 }  
 Function ProcessLogFile {  
      If ((Test-Path $Env:windir"\Logs") -eq $false) {  
           New-Item -ItemType Directory -Path $Env:windir"\Logs"  
      }  
      If ((Test-Path $Env:windir"\Logs\ApplicationLogs") -eq $false) {  
           New-Item -ItemType Directory -Path $Env:windir"\Logs\ApplicationLogs"  
      }  
      If ((Test-Path $Env:windir"\Logs\BuildLogs") -eq $false) {  
           New-Item -ItemType Directory -Path $Env:windir"\Logs\BuildLogs"  
      }  
      If ($Global:Errors -eq $null) {  
           If (Test-Path $Global:LogFile) {  
                Remove-Item $Global:LogFile -Force  
           }  
           $File1 = $Global:LogFile.Split(".")  
           $Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]  
           If (Test-Path $Filename1) {  
                Remove-Item $Filename1 -Force  
           }  
           $Global:Errors = 0  
      } elseIf ($Global:Errors -ne 0) {  
           If (Test-Path $Global:LogFile) {  
                $Global:LogFile.ToString()  
                $File1 = $Global:LogFile.Split(".")  
                $Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]  
                Rename-Item $Global:LogFile -NewName $Filename1 -Force  
           }  
      } else {  
           $LogTitle = $Global:Sequence + " - "+$Global:Title  
           Out-File -FilePath $Global:BuildLog -InputObject $LogTitle -Append -Force  
      }  
 }  
 Function ExitPowerShell {  
      If ($Global:Errors -ne $null) {  
           Exit 1  
      }  
 }  
 cls  
 GetRelativePath  
 DeclareGlobalVariables  
 ConsoleTitle $Global:Title  
 ProcessLogFile  
 EnableWOL  
 ProcessLogFile  
 ExitPowerShell  
 Start-Sleep -Seconds 10  

22 May 2014

Executing Command Line on Remote Systems

I have been a huge fan of PsExec ever since I became and SCCM Administrator. The problem with PsExec is that it transmits credentials in clear text. There is a great alternative to this and it is PAExec. It is freeware and can be redistributed. It has all of the same functionality as PsExec with a few additional minor features. You can get the software at PowerAdmin.

02 May 2014

Enable or Disable Internet Explorer Active X Components

This script will enable or disable Internet Explorer Active X components. All you have to do is pass the user friendly name of the component, component's GUID, and the flag. The app will verify if the change actually takes place and returns a success or failure status.

You can download this from here.


<#
.SYNOPSIS
   Enable/Disable IE Active X Components
.DESCRIPTION
   
.PARAMETER <paramName>
   <Description of script parameter>
.EXAMPLE
   EnableIEActiveXControl "Application Name" "GUID" "Value"
   EnableIEActiveXControl "Flash for IE" "{D27CDB6E-AE6D-11CF-96B8-444553540000}" "0x00000000"
#>

#Declare Global Memory
Set-Variable -Name Errors -Value $null -Scope Global -Force
Set-Variable -Name LogFile -Value "c:\windows\waller\Logs\BuildLogs\AdobeFlashPlayer.log" -Scope Global -Force
Set-Variable -Name RelativePath -Scope Global -Force

Function ConsoleTitle ($Title){
    $host.ui.RawUI.WindowTitle = $Title
}

Function GetRelativePath { 
    $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\" 
}

Function DisableIEActiveXControl ($AppName,$GUID,$Flag) {
    $Key = "HKLM:\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility\"+$GUID
    If ((Test-Path $Key) -eq $true) {
        Write-Host $AppName"....." -NoNewline
        Set-ItemProperty -Path $Key -Name "Compatibility Flags" -Value $Flag -Force
        $Var = Get-ItemProperty -Path $Key -Name "Compatibility Flags"
        If ($Var."Compatibility Flags" -eq 1024) {
            Write-Host "Disabled" -ForegroundColor Yellow
        } else {
            Write-Host "Enabled" -ForegroundColor Red
        }
    }
}

Function EnableIEActiveXControl ($AppName,$GUID,$Flag) {
    $Key = "HKLM:\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility\"+$GUID
    If ((Test-Path $Key) -eq $true) {
        Write-Host $AppName"....." -NoNewline
        Set-ItemProperty -Path $Key -Name "Compatibility Flags" -Value $Flag -Force
        $Var = Get-ItemProperty -Path $Key -Name "Compatibility Flags"
        If ($Var."Compatibility Flags" -eq 0) {
            Write-Host "Enabled" -ForegroundColor Yellow
        } else {
            Write-Host "Disabled" -ForegroundColor Red
        }
    }
}

cls
#DisableIEActiveXControl "Flash for IE" "{D27CDB6E-AE6D-11CF-96B8-444553540000}" "0x00000400"
EnableIEActiveXControl "Flash for IE" "{D27CDB6E-AE6D-11CF-96B8-444553540000}" "0x00000000"
Start-Sleep -Seconds 5

01 May 2014

Installing Dell CCTK and Configuring BIOS Settings

This script will install the Dell CCTK and set specified BIOS settings. Unlike the CCTK that allows you to create a multiplatform file to run against any Dell model machine, this script takes a different approach so that there is a description, logging, and verification of each BIOS setting. This script will first install the CCTK that needs to be in the same directory as the script. It then executes the CCTKSetting function that allows for you to enter each desired setting. There are four variables passed into the function. The first is a description. The second is the actual name of the BIOS setting. The third is the desired value for the setting. Finally, the fourth is only for the bootorder setting. There has to be an additional value passed for this setting.

When executed, the script writes both to the screen and a log file the settings that were changed. Since this is a multiplatform, I have included a return message "unavailable" for those settings not present of the machine this was executed on.

NOTE: If you use this script in a build process and make changes to embsataraid, the OS will likely fail to load. This setting has to be changed before the OS is layed down.

You can download this script here.


<#
.Author
   Mick Pletcher
.Date
   01 May 2014
.SYNOPSIS
   Dell Client Configuration Toolkit
.DESCRIPTION
   Installs CCTK
.PARAMETER <paramName>
   <Description of script parameter>
.EXAMPLE
   <An example of using the script>
#>

#Declare Global Memory
Set-Variable -Name Errors -Value $null -Scope Global -Force
Set-Variable -Name LogFile -Value $Env:windir"\Logs\BuildLogs\CCTK.log" -Scope Global -Force
Set-Variable -Name BuildLog -Value $Env:windir"\Logs\BuildLogs\Build.log" -Scope Global -Force
Set-Variable -Name RelativePath -Scope Global -Force

Function ConsoleTitle ($Title){
    $host.ui.RawUI.WindowTitle = $Title
}

Function GetRelativePath { 
    $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\" 
}

Function InstallCCTK {
    $MSI = "/i "+[char]34+$Global:RelativePath+"cctk.msi"+[char]34
    $Switches = [char]32+"/qb- /norestart /lvx C:\Windows\logs\ApplicationLogs\CCTK.log"
    $Argument = $MSI+$Switches
    $Output = "Install CCTK....."
    Write-Host "Install CCTK....." -NoNewline
    $ErrCode = (Start-Process -FilePath msiexec.exe -ArgumentList $Argument -Wait -Passthru).ExitCode
    If ($ErrCode -eq 0) {
        $Output = $Output+"Success"
        Write-Host "Success" -ForegroundColor Yellow
    } else {
        $Output = $Output+"Failed with error code "+$ErrCode
        Write-Host "Failed with error code "$ErrCode -ForegroundColor Red
        $Global:Errors++
    }
    Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force
}

Function CCTKSetting ($Name,$Option,$Setting,$Drives) {
    $EXE = $Env:PROGRAMFILES+"\Dell\CCTK\X86\cctk.exe"
    If ($Option -ne "bootorder") {
        $Argument = "--"+$Option+"="+$Setting
    } else {
        $Argument = "bootorder"+[char]32+"--"+$Setting+"="+$Drives
    }
    $Output = $Name+"....."
    Write-Host $Name"....." -NoNewline
    $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Argument -Wait -Passthru).ExitCode
    If ($ErrCode -eq 0) {
        If ($Drives -eq "") {
            $Output = $Output+$Setting
            Write-Host $Setting -ForegroundColor Yellow
        } else {
            $Output = $Output+$Drives
            Write-Host $Drives -ForegroundColor Yellow
        }
    } elseIf ($ErrCode -eq 119) {
        $Output = $Output+"Unavailable"
        Write-Host "Unavailable" -ForegroundColor Green
    } else {
        $Output = $Output+"Failed with error code "+$ErrCode
        Write-Host "Failed with error code "$ErrCode -ForegroundColor Red
        $Global:Errors++
    }
    Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force
}

Function ProcessLogFile {
    If ((Test-Path $Env:windir"\logs") -eq $false) {
        New-Item -ItemType Directory -Path $Env:windir"\logs"
    }
    If ((Test-Path $Env:windir"\Logs\BuildLogs") -eq $false) {
        New-Item -ItemType Directory -Path $Env:windir"\Logs\BuildLogs"
    }
    If ((Test-Path $Env:windir"\Logs\ApplicationLogs") -eq $false) {
        New-Item -ItemType Directory -Path $Env:windir"\Logs\ApplicationLogs"
    }
    If ($Global:Errors -eq $null) {
        If (Test-Path $Global:LogFile) {
            Remove-Item $Global:LogFile -Force
        }
        $File1 = $Global:LogFile.Split(".")
        $Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]
        If (Test-Path $Filename1) {
            Remove-Item $Filename1 -Force
        }
        $Global:Errors = 0
    } elseIf ($Global:Errors -ne 0) {
        If (Test-Path $Global:LogFile) {
            $Global:LogFile.ToString()
            $File1 = $Global:LogFile.Split(".")
            $Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]
            Rename-Item $Global:LogFile -NewName $Filename1 -Force
        }
    } else {
        Out-File -FilePath $Global:BuildLog -InputObject "08-Dell Client Configuration Toolkit" -Append -Force
    }
}

cls
ConsoleTitle "Dell Client Configuration Toolkit"
GetRelativePath
ProcessLogFile
InstallCCTK
CCTKSetting "PowerLoss" "acpower" "last" ""
CCTKSetting "Advanced Battery Charge" "advbatterychargecfg" "enable" ""
CCTKSetting "On-Board AGP Slot" "agpslot" "enable" ""
CCTKSetting "Resume from Suspended Mode" "alarmresume" "enable" ""
CCTKSetting "Ambient Light Sensor" "amblightsen" "enable" ""
CCTKSetting "Auto On" "autoon" "disable" ""
CCTKSetting "Battery Charge" "batteryslicecfg" "express" ""
CCTKSetting "Bluetooth Devices" "bluetoothdevice" "enable" ""
CCTKSetting "Camera" "camera" "enable" ""
CCTKSetting "Cellular Radio" "cellularradio" "enable" ""
CCTKSetting "Chassis Intrustion" "chasintrusion" "disable" ""
CCTKSetting "Clear BIOS Event Log" "clearsel" "yes" ""
CCTKSetting "Disable WiFi for Ethernet" "controlwwanradio" "enable" ""
CCTKSetting "CPU eXecute Disable" "cpuxdsupport" "disable" ""
CCTKSetting "C states" "cstatesctrl" "enable" ""
CCTKSetting "System Power Mode" "deepsleepctrl" "disable" ""
CCTKSetting "Dell Reliable Memory Technology" "drmt" "enable" ""
CCTKSetting "Built-in NIC" "embnic1" "on" ""
CCTKSetting "Embedded SATA RAID Controller" "embsataraid" "raid" ""
CCTKSetting "Embedded SD Card" "embsdcard" "on" ""
CCTKSetting "Energy Star logo" "energystarlogo" "enable" ""
CCTKSetting "Serial ATA (e-sata) port" "esataport" "auto" ""
CCTKSetting "Express Battery Charge" "expresscharge" "enable" ""
CCTKSetting "Fastboot" "fastboot" "automatic" ""
CCTKSetting "Ready Boost" "flashcachemodule" "enable" ""
CCTKSetting "HDD Acoustic Mode" "hddacousticmode" "performance" ""
CCTKSetting "HDD Protection" "hddprotection" "on" ""
CCTKSetting "HDD Free Fall Protection" "hdfreefallprotect" "enable" ""
CCTKSetting "Hot Docking" "hotdock" "enable" ""
CCTKSetting "WxAN Hotkey" "htkeywxanradio" "enable" ""
CCTKSetting "CPU Hardware Prefetcher" "hwprefetcher" "enable" ""
CCTKSetting "Hardware Prefetcher" "hwswprefetch" "enable" ""
CCTKSetting "CD drive" "idecdrom" "auto" ""
CCTKSetting "Latitude ON" "instanton" "disable" ""
CCTKSetting "Integrated Sound Device" "integratedaudio" "enable" ""
CCTKSetting "Integrated USB Hub" "integratedusbhub" "highspeed" ""
CCTKSetting "Internal Mini PCI Slot" "internalminipci" "enable" ""
CCTKSetting "Internal USB Ports" "internalusb" "on" ""
CCTKSetting "Ultra Wide Band (UWB) Card" "interwirelessuwb" "enable" ""
CCTKSetting "Intel Rapid Start Technology" "intlrapidstart" "enable" ""
CCTKSetting "Intel Smart Connect" "intlsmartconnect" "disable" ""
CCTKSetting "Keyboard Click Sound" "keyboardclick" "enable" ""
CCTKSetting "Keyboard Illumination" "keyboardillumination" "auto" ""
CCTKSetting "Booting to Latitude ON" "latitudeon" "disable" ""
CCTKSetting "Ability to boot to the Latitude ON" "latitudeonflash" "disable" ""
CCTKSetting "Limit Maximum CPUID Function" "limitcpuidvalue" "off" ""
CCTKSetting "Hyper Threading" "logicproc" "enable" ""
CCTKSetting "Microphone" "microphone" "enable" ""
CCTKSetting "Multiple CPU Cores" "multicpucore" "enable" ""
CCTKSetting "Multiple Displays" "multidisplay" "enable" ""
CCTKSetting "Number Lock" "numlock" "on" ""
CCTKSetting "Onboard 1394 Controller" "onboard1394" "enable" ""
CCTKSetting "Onboard Modem" "onboardmodem" "enable" ""
CCTKSetting "Onreader" "onreader" "disable" ""
CCTKSetting "PCI Slots" "pcislots" "enable" ""
CCTKSetting "<F12> boot menu" "postf12key" "enable" ""
CCTKSetting "<F2> boot menu" "postf2key" "enable" ""
CCTKSetting "MEBx hotkey" "postmebxkey" "on" ""
CCTKSetting "Power Button" "powerbutton" "enable" ""
CCTKSetting "Primary Battery Charging" "primarybatterycfg" "express" ""
CCTKSetting "Primary IDE Master Channel" "primidemast" "auto" ""
CCTKSetting "Primary Parallel IDE Slave Channel" "primideslav" "auto" ""
CCTKSetting "Rear Single USB Ports" "rearsingleusb" "on" ""
CCTKSetting "Report Keyboard Errors" "rptkeyerr" "enable" ""
CCTKSetting "Selective USB feature" "safeusb" "disable" ""
CCTKSetting "SATA port 0" "sata0" "auto" ""
CCTKSetting "SATA port 1" "sata1" "auto" ""
CCTKSetting "SATA port 2" "sata2" "auto" ""
CCTKSetting "SATA port 3" "sata3" "auto" ""
CCTKSetting "SATA port 4" "sata4" "auto" ""
CCTKSetting "SATA port 5" "sata5" "auto" ""
CCTKSetting "SATA port 6" "sata6" "auto" ""
CCTKSetting "SATA port 7" "sata7" "auto" ""
CCTKSetting "SATA Controllers" "satactrl" "enable" ""
CCTKSetting "Serial Port 1" "serial1" "auto" ""
CCTKSetting "Serial Port 2" "serial2" "auto" ""
CCTKSetting "Serial Port Communication" "serialcomm" "on" ""
CCTKSetting "Smart Card Reader" "smartcardreader" "enable" ""
CCTKSetting "SMART Errors" "smarterrors" "enable" ""
CCTKSetting "Built-In Speaker" "speakervol" "enable" ""
CCTKSetting "Speedstep" "speedstep" "automatic" ""
CCTKSetting "POST Splash Screen" "splashscreen" "enable" ""
CCTKSetting "ACPI Standby State" "standbystate" "s3" ""
CCTKSetting "Tablet Buttons" "tabletbuttons" "enable" ""
CCTKSetting "Trusted Execution" "trustexecution" "off" ""
CCTKSetting "Intel Turbo Boost" "turbomode" "enable" ""
CCTKSetting "USB 3.0" "usb30" "enable" ""
CCTKSetting "USB port 00" "usbport00" "enable" ""
CCTKSetting "USB port 01" "usbport01" "enable" ""
CCTKSetting "USB port 02" "usbport02" "enable" ""
CCTKSetting "USB port 03" "usbport03" "enable" ""
CCTKSetting "USB port 04" "usbport04" "enable" ""
CCTKSetting "USB port 05" "usbport05" "enable" ""
CCTKSetting "USB port 06" "usbport06" "enable" ""
CCTKSetting "USB port 07" "usbport07" "enable" ""
CCTKSetting "USB port 08" "usbport08" "enable" ""
CCTKSetting "USB port 09" "usbport09" "enable" ""
CCTKSetting "USB port 10" "usbport10" "enable" ""
CCTKSetting "USB port 11" "usbport11" "enable" ""
CCTKSetting "USB port 12" "usbport12" "enable" ""
CCTKSetting "USB port 13" "usbport13" "enable" ""
CCTKSetting "USB port 14" "usbport14" "enable" ""
CCTKSetting "USB port 15" "usbport15" "enable" ""
CCTKSetting "User Accessible USB ports" "usbports" "enable" ""
CCTKSetting "External USB Ports" "usbportsexternal" "enable" ""
CCTKSetting "Front USB Ports" "usbportsfront" "enable" ""
CCTKSetting "USB PowerShare" "usbpowershare" "enable" ""
CCTKSetting "USB Rear Dual Stack" "usbreardual" "on" ""
CCTKSetting "USB Second Rear Dual Stack" "usbreardual2stack" "on" ""
CCTKSetting "USB Rear Quad Ports" "usbrearquad" "on" ""
CCTKSetting "USB Wake" "usbwake" "disable" ""
CCTKSetting "Virtualization" "virtualization" "enable" ""
CCTKSetting "Virtualization Technology for Direct I/O" "vtfordirectio" "on" ""
CCTKSetting "Wake-on-LAN" "wakeonlan" "lanorwlan" ""
CCTKSetting "WiFi Locator" "wifilocator" "enable" ""
CCTKSetting "Wireless Adapter" "wirelessadapter" "enable" ""
CCTKSetting "Wireless LAN Module" "wirelesslan" "enable" ""
CCTKSetting "Ultra Wide Band (UWB) Switch" "wirelessuwb" "enable" ""
CCTKSetting "Bluetooth Control Switch" "wirelesswitchbluetoothctrl" "enable" ""
CCTKSetting "Cellular Control Switch" "wirelesswitchcellularctrl" "enable" ""
CCTKSetting "Wireless Gigabit Switch" "wirelesswitchwigigctrl" "enable" ""
CCTKSetting "Disable Floppy" "bootorder" "disabledevice" "floppy"
CCTKSetting "Boot Order" "bootorder" "sequence" "hdd.1,hdd.2,cdrom,usbdev,embnic"
ProcessLogFile
Start-Sleep -Seconds 10

10 April 2014

How to remove shortcuts during an MSI installation

It is very easy to stop shortcuts from being installed during an MSI installation. The first thing you will need is ORCA or Super ORCA. These applications will allow you to open up and edit the contents of the MSI. Once you have the MSI opened up in either app, go to the shortcut table as shown in the pic below. Once there, right-click on each row and click drop-row. That is all that is to preventing shortcuts from being installed.


07 April 2014

Message containing password has been suppressed error

In my experience, this error was caused by me manually editing the unattend.xml file associated with an imported operating system. Specifically, I had manually entered the UnattendedJoin credentials within the unattend.xml file. Apparently when you manually enter the credentials in there, and they are in plain text, this error will occur when you override those credentials in the customsettings.ini file. To fix this, either re-import the operating system image or make sure the plain text credentials match in both the customsettings.ini and the unattend.xml files.

13 March 2014

Get list of installed printers

This function will get the list of printers installed for a user. It will also get the Default Printer. It outputs the list to Printers.txt, located at the location where the script is executed.

You can download the script here.


Function GetRelativePath {
    $Global:RelativePath=(split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"
}

Function GetPrinterList {

    #Declare Local Memory
    Set-Variable -Name Count -Scope Local -Force
    Set-Variable -Name DefaultPrinter -Scope Local -Force
    Set-Variable -Name Printers -Scope Local -Force
    Set-Variable -Name Temp -Scope Local -Force
    
    If (Test-Path -Path $Global:RelativePath"Printers.txt") {
        Remove-Item -Path $Global:RelativePath"Printers.txt" -Force
    }
    $DefaultPrinter = Get-WmiObject -Query " SELECT * FROM Win32_Printer WHERE Default=$true"
    $DefaultPrinter = $DefaultPrinter.ToString()
    $DefaultPrinter = $DefaultPrinter -replace [char]34,""
    $DefaultPrinter = $DefaultPrinter -replace "\\\\","\"
    $DefaultPrinter = $DefaultPrinter.split("=")
    $Temp = "Default Printer: "+$DefaultPrinter[$DefaultPrinter.Length-1]
    $Temp | Add-Content -Path $Global:RelativePath"Printers.txt"
    $Printers = Get-WmiObject -Query " SELECT * FROM Win32_Printer WHERE Default=$false"
    For ($Count=0; $Count -lt $Printers.Length; $Count++) {
        $Temp = $Printers[$Count]
        $Temp = $Temp.ToString()
        $Temp = $Temp -replace [char]34,""
        $Temp = $Temp -replace "\\\\","\"
        $Temp = $Temp.split("=")
        $Temp = "Printer: "+$Temp[1]
        $Temp | Add-Content -Path $Global:RelativePath"Printers.txt"
        Write-Host $Temp
    }
    
    #Cleanup Local Memory
    Remove-Variable -Name Count -Scope Local -Force
    Remove-Variable -Name DefaultPrinter -Scope Local -Force
    Remove-Variable -Name Printers -Scope Local -Force
    Remove-Variable -Name Temp -Scope Local -Force
    
}

06 March 2014

Creating Active Setup Registry Key

Here is a script I just wrote that will create an active setup registry key. It prompts you for the title, description, command line execution string, and version. It generates a unique GUID to name the registry key. It then generates the registry key file and places it in the same directory as the script was executed from.

You can download the script from here.

<#
     Author: Mick Pletcher
       Date: 06 March 2014
   Synopsis: This will generate the active setup registry key to
             deploy to machines so it iterates through every user that
             logs onto a machine.
Description: This will prompt for the title, brief description, version, and
             command line execution string. It then generates the .reg file
             and places it in the same directory as the script was executed from.
#>

Function GetRelativePath{  

    #Declare Local Memory
    Set-Variable -Name RelativePath -Scope Local -Force
    
    $RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"
    Return $RelativePath
    
    #Cleanup Local Memory
    Remove-Variable -Name RelativePath -Scope Local -Force
    
}
 
Function GenerateGUID {

    #Declare Local Memory
    Set-Variable -Name GetGUID -Scope Local -Force
    
    $GetGUID = [guid]::NewGuid()
    $GetGUID = $GetGUID.ToString().ToUpper()
    
    return $GetGUID

    #Cleanup Local Memory
    Remove-Variable -Name GetGUID -Scope Local -Force
    
}

Function GetKeyInfo {

    #Declare Local Memory
    Set-Variable -Name ComponentID -Scope Local -Force
    Set-Variable -Name Description -Scope Local -Force
    Set-Variable -Name StubPath -Scope Local -Force
    Set-Variable -Name Version -Scope Local -Force
    
    $ComponentID = Read-Host "Enter the title"
    $Description = Read-Host "Enter brief description"
    $Version = Read-Host "Enter the version number"
    $StubPath = Read-Host "Enter the command line execution string"
    $StubPath = $StubPath -replace '\\','\\'
    Return $ComponentID, $Description, $Version, $StubPath
    
    #Cleanup Local Memory
    Remove-Variable -Name ComponentID -Scope Local -Force
    Remove-Variable -Name Description -Scope Local -Force
    Remove-Variable -Name StubPath -Scope Local -Force
    Remove-Variable -Name Version -Scope Local -Force
    
}

Function GenerateRegKey ($RelativePath, $GUID, $KeyInfo) {

    #Declare Local Memory
    Set-Variable -Name File -Scope Local -Force
    Set-Variable -Name Text -Scope Local -Force
    
    $File = $RelativePath+"ActiveSetup.reg"
    If (Test-Path $File) {
        Remove-Item -Path $File -Force
    }
    New-Item -Name ActiveSetup.reg -Path $RelativePath -ItemType file -Force
    $Text = "Windows Registry Editor Version 5.00"
    Add-Content -Path $File -Value $Text -Force
    $Text = [char]13
    Add-Content -Path $File -Value $Text -Force
    $Text = "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\{"+$GUID+"}]"
    Add-Content -Path $File -Value $Text -Force
    $Text = "@="+[char]34+$KeyInfo[1]+[char]34
    Add-Content -Path $File -Value $Text -Force
    $Text = [char]34+"ComponentID"+[char]34+"="+[char]34+$KeyInfo[0]+[char]34
    Add-Content -Path $File -Value $Text -Force
    $Text = [char]34+"StubPath"+[char]34+"="+[char]34+$KeyInfo[3]+[char]34
    Add-Content -Path $File -Value $Text -Force
    $Text = [char]34+"Version"+[char]34+"="+[char]34+$KeyInfo[2]+[char]34
    Add-Content -Path $File -Value $Text -Force

    #Cleanup Local Memory
    Remove-Variable -Name File -Scope Local -Force
    Remove-Variable -Name Text -Scope Local -Force

}

#Declare Global Memory
Set-Variable -Name GUID -Scope Local -Force
Set-Variable -Name KeyInfo -Scope Local -Force
Set-Variable -Name RelativePath -Scope Local -Force

cls
$RelativePath = GetRelativePath
$GUID = GenerateGUID
$KeyInfo = GetKeyInfo
GenerateRegKey $RelativePath $GUID $KeyInfo

#Cleanup Global Memory
Remove-Variable -Name GUID -Scope Local -Force
Remove-Variable -Name KeyInfo -Scope Local -Force