29 August 2016

This is another part of the Windows 10 project I am working on automating. This script will set the Windows 10 power settings. I created this, with the help of Sapien's PowerShell Studio that helped make this script much more robust, so that it can be executed during the image to configure the settings there. This allows me to take the settings out of GPO and put them on the local machine to help speed up the logon process. The users at the firm I work at do not have local administrator privileges, so this works great.

The advantage to using this script for configuring power settings, over using powercfg.exe directly, is that the script will verify the setting took place. It goes back and checks the new value to make sure it coincides with the desired value. If it was not successful, the script will return an error code 5, which I arbitrarily chose. This allows you to use the script in a build and it will report the error back to alert you at the end of the build if the power setting was unsuccessful.

The script can set individual power settings per the command line, you can hardcode the settings into the script (I commented out an example), or you can import a power scheme. I also included the feature to generate a detailed and formatted report of all power settings on a machine. The report not only displays to the screen, but it also generates a file named PowerSchemeReport.txt in the same directory as the script. I have included command line examples in the comments of the script.

Here is an example of the script generating a report:

Here is an example of setting the Monitor Timeout while plugged in to 120 minutes:

Here is an example of setting the power scheme from high performance to balanced:

Here is an example of the script importing a power scheme configuration file and setting it as the default:

23 August 2016

Recently, my firm has started using the AD extension attributes for custom data. I wrote a script a while back that read the data from a .CSV and imported it into a specific ExtensionAttribute. This came up again and it was brought to my attention that we may start using more of the fields. In order to automate this so that I don't have to modify the script each time, I decided to write one that gets all of its information from the .CSV file. With the help of Sapien's PowerShell Studio, this script was easy to write and easy to document.

This script will import a populated .CSV file that resides in the same directory as the script. The first line in the .CSV file contains the headers. The script reads that line to know what fields to populate in AD. You enter the exact extensionAttribute name in the header field and all data beneath it will be populated in that field for each user. Here is a screenshot of a sample .CSV file.

The first line is what tells it which extension attribute to populate the data to. It can have as many attribute lines as you need. I also added the features to remove data from an extension attribute. If a cell is left blank or CLEAR is input into the cell, the extension attribute will be cleared. If you do not want anything done to an attribute, input NO CLEAR into the cell and the script will not do anything to the attribute.

Logging has also been added to the script. If you want a log file written, then populate the -LogFile parameter. If this is left unpopulated, the script will not create a log file.

Another feature it -ProcessDelay. I added this as a precautionary feature. This puts a specified XX seconds delay between each record. This allows you to slowly implement the changes in AD without it all happening at once. Say you accidentally made an error in the .CSV file and discover it midway through. At least not all records got changed at that time. If you leave that field blank, the script will not pause between each record.

The final feature I added was for the script to go back and verify the change was actually made.

I do highly recommend that you test this script out on a test account first before using it against all of your user accounts. It works in my environment, but it is no guarantee that it will work in yours.

05 August 2016

While helping to manage Microsoft Endpoint, a former colleague suggested that I setup Endpoint to automatically run a full system scan each time an infection is detected. I Googled the blog posting on it and although it is a great post, I figured it could streamlined even more by just using SCCM alone to achieve the same outcome. It is nice when you are out of the office and your backup might not have the time to keep an eye on the antivirus infections. It is also beneficial if you are in an environment where the office is closed overnight and on weekends. If an infection takes place, this can help remediate it without your presence.

This is the third edition. The first edition just initiated a full system scan upon infection. The second edition initiated a full system scan plus would send an email to the designated email address. The third edition now combines the first two and allows for them to be designated using parameters. The code has also been optimized.I decided to use the SCCM custom application detection to query a system and see if a full system scan has been performed in the event of an infection logged in the event viewer. I first started out by writing a PowerShell script that would perform a WMI query on the SCCM server for the status of the system the application detection was being run on. The problem I ran across was that the application is being run under system credentials, which would require me to pass network credentials within the script. Instead of having to do this, I decided to query the event viewer logs on the local machine to look for the last infection date/time, which is event 1116. I also found that event 1001 and provider name Microsoft Antimalware designate are used when a system scan has been performed. Here are the steps SCCM and PowerShell go through:

SCCM deploys the package to the system.

The application detection queries the event viewer logs for the last 1116 ID (infection).

The application detection queries the event viewer logs for the last 1001 ID and "Microsoft Antimalware" provider name.

If a system 1001 ID does not exist since the last infection, the custom detection method will exit out as a failure.

If the custom detection failed, the AntiVirusScanEmail.ps1 file will be executed on the machine.

An email is sent that tells a scan was performed on %COMPUTERNAME% with the virus details in the body if -Email switch was specified

Once the scan is complete, an application deployment evaluation cycle is initiated to update the SCCM server with the status of the system.

The application detection is initiated again to confirm the scan occurred.

If you desire emails be sent alerting you of an infection and system scan, then you will need to download and place PsExec.exe in the same directory as this script. The next thing will be to define the Installation program in SCCM using psexec.exe. This allows the PowerShell script to be executed under a domain account, thereby giving it the ability to use the send-mailmessage commandlet. Here is how to do this:

Do not change %computername%. The only parts of the psexec.exe command line that need to be changed are <domain>, <username>, and <password>. If you do not want emails sent, then you can use the following command line parameter:powershell.exe -executionpolicy bypass -file AntiVirusScanEmail.ps1 -FullScanorpowershell.exe -executionpolicy bypass -file AntiVirusScanEmail.ps1 -QuickScanThis is setup in SCCM as a normal application deployment. The only thing that differs from a standard deployment is the application detection method. The ApplicationVirusDetectionMethodEmail.ps1 script is imported in for the detection method. The AntiVirusScanEmail.ps1 file is setup as the installation program. I have mine entered like this:

If you also want it to email you, then refer to the section above on using psexec.exe and the example to enter in as the installation program. One more thing is that I have the application hidden from the software center. There really isn't a need for it to be seen by the end-users.

In order for this to work in a timely manor, you will need to change the software deployment frequency under the client settings. I have mine set at every 8 hours, or three times a day.

You can download the application and application detection files from the following links:

02 August 2016

It was time to upgrade the old SCCM Client Installer. I wanted to add new features and also make the script be able to execute by using parameters. With the help of Sapien's PowerShell Studio, this was very easy to do! I did not include all optional fields, but for my own company, this works great and you can easily modify it if there are additional parameters of the client installer you need in your environment.

The first thing I did was to make the parameters available for the client installer directory, client installer filename, management point, SMS site code, and two switches defining whether to install or uninstall. I centered this script around using the ccmsetup.exe file to both install and uninstall. Another feature I added is the Build parameter. This parameter can be added with the install parameter, or by itself. This configures the SCCM client in preparation for a sysprep of the computer. This is primarily done before sysprepping a machine using SCCM or MDT that captures a reference image. This allows for the client to be already present when the reference image is laid down on a newly imaged computer. It then communicates back to the SCCM server to configure itself as a new client when that reference image is laid down on new machines. I have included command line examples within the script's documentation.

This is a video of the script executing to uninstall the SCCM client on a machine.

This video shows the script installing the SCCM client. You can see that I include the uninstallation of the application first so that if this is being run to fix a machine, it will first uninstall and then install the client. Another thing you will see is that it initializes the installation and then goes on to wait for the installation to complete. I put the waiting in there because once the client begins its install, it closes out the first instance of the ccmsetup.exe and opens up a new one, thereby making the script think the installation finished, when in essence, it did not. I make the script wait because I want to make sure that when the install takes place, it is completely finished when the script closes. When the script executes during a build, especially during a reference image build, it needs to time complete the setup before the sysprep. That is the purpose of the wait. If you do not want it to wait, you can disable lines 264 and 280.

Finally, below is a pic of the script being executed to prepare the SCCM client for a sysprep. I have also included a pop-up window in the event the SCCM client is not properly prepared for the sysprep. The window will stay there until OK is clicked. This gives the admin the capability of either manually deleting the file and registry keys and stopping the ccmexec service, or restarting the build.