Skype Won’t Login

This post was migrated from my older blog.

We had an issue a while ago where Skype would not sign several users in. There was nothing obvious from Skype itself, no errors, no timeouts. It just sat there spinning. I opened up WireShark and found no packets were even being attempted from Skype to our server. In procmon, I similarly found nothing happening after the logon is attempted, no errors, no network traffic, no access denied, etc. A coworker finally managed to get some headway by noticing that all affected users had no network connections shown in the Network and Sharing center. This was odd as they did have internet access; could check e-mail, browse the internet, access domain resources, etc. It turns out, the cause was permissions on a specific set of registry keys dealing with network information. Specifically the netprofm account did not have access to the following registry keys

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles

Once the permissions were corrected, Network and Sharing center showed our domain connection and Skype started functioning, didn’t even require a reboot.

Installing Java through SCCM

This post was migrated from my older blog.

I have been trying to get Java to install smoothly from SCCM for quite a while now. We need to deploy Java in a way that ensures that old versions of Java are removed, and both 32-bit and 64-bit versions of Java are installed. Here is a list of problems a ran into, as well as fixes for each.

The GUID is only Semi-Predictable

Uninstalling Java improves security as the Java installer frequently fails to remove previous versions. So, how do we uninstall Java remotely through SCCM? The most obvious approach is to remove Java by the GUID with MSIEXEC. Example:

MsiExec.exe /X{26A24AE4-039D-4CA4-87B4-2F06417067FF} /qn /norestart

This works well, but you have to know the GUIDs beforehand. If you search for the Java GUIDs you will likely find forums with comments stating to just replace parts of the GUID with the software version and bit version. We had a script that, mostly, worked based on this concept.

Here is the general suggestion you will find when you search for the Java GUIDs. The first bolded part of the following GUID is the bit version of Java, 32 or 64. The second bolded part relates to the specific version of Java. In this case, 7 update 55.

{26A24AE4-039D-4CA4-87B4-2F83217055FF}

This does not work all the time however.

Here’s an example:

Java 7 Update 55 {26A24AE4-039D-4CA4-87B4-2F83217055FF}
Java 7 Update 60 {26A24AE4-039D-4CA4-87B4-2F03217060FF}

The bolded parts changed outside the expected pattern.

That’s just one example, it seems as though subtle changes like that are littered through the Java releases. Most scripts that remove multiple versions of Java don’t seem to account for this. Our in-house script didn’t.

I noticed that the parts of the GUID that frequently change are only on the last segment of the GUID. The front segments of the GUID rarely change. I built a powershell script to remove Java on this concept.

Click here to go to the wiki page on the JavaRemoval script.

SCCM starts 32-bit Powershell by default

The removal works well by itself, but had issues when used in an SCCM package. It only removed 32-bit versions of Java. This leads to multiple 64-bit versions of Java. Thanks to the logging lines I added to the script I found out that it was only receiving the 32-bit keys, even from the 64-bit registry path. Turns out, SCCM executes the script with the 32-bit Powershell. This was a quick fix thanks to this technet post. I took jfvanroy’s answer and entered in the Powershell script name. It is working well so far. You can find a copy of it below.

If "%PROCESSOR_ARCHITEW6432%"=="" GOTO Native
%windir%\Sysnative\windowsPowershell\V1.0\PowerShell.exe -NoProfile -ExecutionPolicy Bypass -file %~dp0JavaRemoval.ps1
GOTO END
:Native
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -file %~dp0JavaRemoval.ps1
:END

The Uninstall Restart

The next problem I ran into with uninstalling/installing Java is a reboot requirement. Our original batch file uninstalled and installed Java in one run. This was hit or miss for 2 reasons. The first script that we made did not have a /norestart switch to the uninstall command. When a restart was required, the machine rebooted. The problem with that is it cancels the rest of the script which prevents Java from being installed. SCCM does not resume scripts that restart in the middle of their execution. As for the second reason; when we added the /norestart switch the install fails due to a pending restart. One of the main reasons a reboot was required is because IE or Java was still in use by a user at the deployment deadline.

We originally remedied these issues by using a task-sequence with a required reboot in-between an uninstall and install step. We added a few taskkill commands to our script to help with the program in-use issues. Not exactly elegant, but it worked… mostly. This was before we figured out the GUID issues. We are now using a single application package for uninstall and 2 application packages for install. This is done to bridge any gaps created by the install. For example, if you uninstall Java, then install the latest version, this causes a gap in the Java coverage for the user. To fix this, deploy two packages, x86 and x64, of Java. Then about a week later, deploy an uninstall package the removes all versions except for the version you want to standardize your users on.

The Installer doesn’t work with the 64-bit System Account

When you use the executable installer to install Java, it extracts an MSI and CAB file to the AppData folder. It then runs a MSIEXEC /i command to install the extracted MSI file. For home users this usually works, as it uses the home user’s account. SCCM, however, uses the system account. The system account is a little odd in that, it has two profiles. A 32-bit and a 64-bit profile. MSIEXEC is a 64-bit utility in 64-bit versions of windows, but the Java installer runs as 32-bit. The files that the installer extracts ends up in the 32-bit system profile. When MSIEXEC goes to install the MSI, it looks in the 64-bit profile and fails to find it.

This is a known bug and has been for a while. Shavlik submitted a bug report to Java back in 2010 on the issue, however it was recently resolved with the resolution “Won’t Fix”.

A workaround to this, is to extract the MSI, and CAB file for older versions, and run those directly. It works but it is an unsupported practice according to Oracle. Update: You were once able to find instructions on how to do that at Oracle’s website. This page now advertises their enterprise “My Oracle Support” option. As such, I will include the instructions below.

  1. Download the Java SE JRE Offline installers from the Java SE Downloads page
  2. Run the installers but do not click next or continue the installation!
  3. Once the installer is visible, navigate to “C:\Users\[Your UserName]\AppData\LocalLow\Oracle\Java” or “%APPDATA%\..\LocaLow\Oracle\Java”. Inside this directory you should see a folder matching the version of Java you started the installer for. For example “jre1.8.0_112_x64”. Copy everything inside the folder to wherever you need the install files to be. Pre Java 8 Update 20, this folder usually contained an MSI and CAB file. Afterwards, it is usually just a single MSI file. Either way, that MSI file and any supporting files in that folder make up the extracted installer. Repeat this as needed for the 32/64 bit versions if you are installing those as well.

Java extracts two files (Pre 8 Update 20)

I briefly attempted to deploy Java through SCUP. I sent a test deployment out and it half worked. Some received the update, some didn’t. Mostly it was just a mess. At the time I was not fully sure why, but it is likely that it was due to the same issue I had deploying Java as an application package. It extracted to the wrong system profile

Before entirely giving up on the idea, I decided to see if I could send it out using the extracted MSI files. It was not even plausible as a concept as Java extracts to 2 files, a MSI and a CAB. Both files are required for the install to succeed. SCUP does not support multi-file installers unfortunately.

Update 2016-01-07: The 2 file issue appears to have stopped. Extracting Java now only seems to produce a single MSI file. I have not attempted a SCUP deployment however. If it does work, the next problem will still be an issue.

Java doesn’t remove old versions in silent mode

Java recently, starting with an update of 8, started to prompt during install to remove previous version of Java. This does works well for home users, but for enterprise environments, this does not work in silent mode. There are currently no switches you can use to get the MSI to remove old versions.

Java doesn’t install in silent mode correctly without a config file

Another recent development with Java, is that it now appears to require a config file in order to install in silent mode correctly. The /q switch for msiexec is no longer enough.

The config file needs to be saved to “C:\ProgramData\Oracle\Java\java.settings.cfg”. The file is a plain text file with install commands on every line. The line we need to ensure a functional silent install is “INSTALL_SILENT=1”. See below for an example config file.

AUTO_UPDATE=0
EULA=0
INSTALL_SILENT=1
SPONSORS=0
WEB_ANALYTICS=0

There is a sub issue related to this. If you leave the config file in place after the install occurs, then any administrator that then needs to manually update or remove Java in the future will not see their installer/uninstaller run. More than likely, they will troubleshoot their “failing” installer until they finally realize that the installer actually is running, but is forced into silent mode by the left over file.

My Complete Solution

I have a 3 Deployment solution that appears to work solidly in SCCM. Instructions on how to create the solution is located at Java_Install_Package

In general though, the package can be built as such:

  1. Create an application package. Ensure the source folder contains the extracted installers for whatever version of Java you are installing.
  2. Add to the source folder a silent install config file, and a batch file that installs the config file, installs java, then removes the config file.
  3. Repeat for any other versions of Java.
  4. Use the JavaRemoval script and the batch code from Problem 2 to create a Java Removal package that removes all versions of Java except the ones that you just built packages for.
  5. Deploy the 2 installers for x86 and x64 in SCCM.
  6. Deploy the uninstaller about a week later when 95% or more of your clients have your new version of Java.

The end effect of all this is, when the install program is deployed it will install Java. The uninstall package which should be deployed a week later will uninstall un-needed versions of Java.

Win32Exceptions

This post was migrated from my older blog.

There have been a few times where I found myself starting at an error prompt stating Error: 0x000006C1 or some other unhelpful hex number. Then upon searching for the error code, only finding results for a specific instance of the error for an unrelated application with generic fixes that still don’t hint at the root issue. I found that you can translate some of these error codes using .Net and by extension PowerShell. If you find yourself in this situation, try the following command:

new-object System.ComponentModel.Win32Exception @($ErrorCode);

Where “$ErrorCode” is your error. Example:

new-object System.ComponentModel.Win32Exception @(0x80190193); #Can use integers or hex numbers

I also generated a list of the exceptions here: Win32Exceptions List If the list does not contain your error code, then it is likely just “Unknown error”… not very helpful.

Alternatively, if you utilize SCCM and have the CMTrace tool, you can preform error code lookups directly from the CMTrace application.

EMET and BitLocker

This post was migrated from my older blog.

Here is a quick story on how I “broke BitLocker”.

We recently deployed the latest EMET to our client machines utilizing SCCM. Our machines never had EMET before, but the deployment was installing the software without issue. Shortly after the install, our clients started to receive new policies they never had before.

One of these new policies changes DEP. When DEP is configured, it changes a setting in the BIOS. This is bad, at least for us as we utilize BitLocker heavily. Changes to a machine’s hardware, OS, or BIOS baseline will cause BitLocker to prompt for a recovery key. The general fix for these kind of situations is to grab the machines recovery key and unlock the machine, then suspend and re-enable BitLocker. This causes BitLocker to acknowledge the new baseline. Unfortunately, that is a very manual process that we must now perform on all the machines. There is no real work around for this.

During all the turmoil this setting caused, we discovered a few of our users do not have BitLocker recovery passwords backed up anywhere. These users were unable to get into the machine, and the service desk couldn’t assist due to the keys not being backed up. We believed these users would loose their data.

I started to think about how to get back into these machines and it hit me. When you insert a CD into a BitLockered machine, it causes the BitLocker to prompt for a recovery password. However you don’t have to provide one if you remove the CD and reboot. By removing the CD, you effectively bring the machine back to it’s expected baseline. Since it is a BIOS change, I thought, what if we just change it back. I booted one of the affected machines into PXE, opened up the debug command prompt (If enabled in SCCM, press “F8”) and entered the following command to try and change the DEP setting back:

BCDEdit /Set nx 

I then rebooted the machine and *poof* Windows loading logo appeared. We were able to save a few of our users from having an unfortunate week thanks to this trick.

Installing a Custom Service

This post was migrated from my older blog.

So I was playing around with custom services in C# a couple years back. I never created a service before so I was going off of Microsoft’s MSDN articles and a few blogs that Google searches turned up. They all followed the same pattern.

This solution works fine, but I don’t really like it much.

Fast forward to about a month ago. We had some issues with one of our servers. One of the steps in troubleshooting the issue was to manually check what the machine and resources looked like from Local System’s perspective. To do this, I opened an instance of cmd.exe under the Local System account interactively using the built-in tool SC. (More on how to do that here) I did not know about that tool until then. Turns out, all it does is register the application specified, cmd.exe in this case, as a service. I decided to test it for use in installing a custom service created in C#. I created a quick service that answered a single incoming TCP connection with “Hello World”. Installed it with SC, and it worked! I did not have to create an install class within the service, nor did it rely on InstallUtil.exe. For more information on SC for installing services, check out the “SC Create” TechNet article

PowerShell Signing

This post was migrated from my older blog.

I wanted to sign a PowerShell script to make it easier and more secure to use in our environment. PowerShell signing was not in great use in the environment. To make signing the scripts easier I created a simple script to help with the signing process. There was an issue however. We have generic, fully trusted, all purposes certificates. Despite being fully trusted and all purpose, they did not show up as valid certificates in PowerShell. I tried manually running:

Get-ChildItem cert:\CurrentUser\My -codesigning

It returned nothing. The certificates should work, but they weren’t showing up. I checked the certificate inside of the Certificate Store. Inside the certificate’s properties on the “General” tab, there is a “Certificate purposes” group box. Inside of this “Enable all purposes for this certificate” was selected.

CertStore
Showing how to manually enable all purposes

Since that was not working, I selected “Enable only for the following purposes”.
By default, all purposes were already checked. I clicked “Ok” and ran the Get-ChildItem command again and the certificate was finally listed. I ran through the signing process successfully. The signature on the PowerShell file was trusted and valid.