Wednesday, November 20, 2013

PS Scripts to change File Association on your Windows 8 / 8.1 Image

Hello there,

A colleague of mine asked me if we could automate modifying file association when building images.

Here is the solution we came up with:

After a bit of google-fu-ing, it seems that there are two ways to accomplish this either through some HKCU   registry keys but some key permissions need to be changed or using DISM.

Here we are going to look at the DISM way.

Note that when using DISM the changes are not available for the currently logged in user but it works for new users. Therefore, this is a valid method when creating a custom Windows 8 / 8.1 image.

First we Need to export the current File association with DISM. To do this we will create a script called
Get-AppAssociation.ps1 with the following content:


param(

[parameter(Mandatory = $True )][string]$AssocXMLExportPath
)
DISM /online /Export-DefaultAppAssociations:$AssocXMLExportPath


Next we will create a second script called Set-AppAssociation.ps1 to check if the file extension to modify exists and if so modify it else add it to the xml file. This script also creates a backup of the original xml file.


param(
[parameter(Mandatory = $True )][string]$AssocXMLPath,
    [parameter(Mandatory = $True )][string]$Extention,
    [parameter(Mandatory = $True )][string]$ProgID,
    [parameter(Mandatory = $True )][string]$AppName
)

If(! (Test-Path -Path $AssocXMLPath".bak")){
    Copy-Item $AssocXMLPath $AssocXMLPath".bak"
}

[xml]$AssocXML = Get-Content $AssocXMLPath -Encoding UTF8
$Associations = @($AssocXML.DefaultAssociations.Association)
$Found = $False

foreach ($Association in $Associations){
    #Checks if the file association already exists and if it does update it. 
   If($Association.Identifier -eq  $Extention){
        $Association.ProgId = $ProgID
        $Association.ApplicationName = $AppName
        $Found = $True
   }
}

#If not existing association are found a new one is created and added to the xml
 if(!($found)){
        #Create a new XML element       
        $NewAssociationNode = $AssocXML.CreateElement("Association")
       
        #Set the attributes for the new element
        $NewAssociationNode.SetAttribute("Identifier",$Extention)
        $NewAssociationNode.SetAttribute("ProgId",$ProgID)
        $NewAssociationNode.SetAttribute("ApplicationName",$AppName)

        #Inject the new child to existing
        $AssocXML.LastChild.AppendChild($NewAssociationNode) > $null
}
$AssocXML.Save($AssocXMLPath)

Finally, we will use a third script to import those modified settings back to the image, using the script Restore-AppAssociation.ps1. Here is the content of the script.
param(
[parameter(Mandatory = $True )][string]$AssocXMLImportPath
)
DISM /online /Import-DefaultAppAssociations:$AssocXMLImportPath

And to bring it all together and demonstrate how to properly use those scripts here is a batch file that calls the 3 scripts above with parameters to modify the file extensions (pre-sysprep & capture).

cd /d "%~dp0"
::powershell set-executionpolicy remotesigned

:: Export the file association XML to the file system with DISM
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Get-AppAssociation.ps1 -AssocXMLExportPath "C:\OSD\AppAssoc.xml""

::modify the association XML content
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".bmp"  -ProgID "PhotoViewer.FileAssoc.Bitmap" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".dib"  -ProgID "PhotoViewer.FileAssoc.Bitmap" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".jfif"  -ProgID "PhotoViewer.FileAssoc.JFIF" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".jpe"  -ProgID "PhotoViewer.FileAssoc.Jpeg" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".jpeg"  -ProgID "PhotoViewer.FileAssoc.Jpeg" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".jpg"  -ProgID "PhotoViewer.FileAssoc.Jpeg" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".jxr"  -ProgID "PhotoViewer.FileAssoc.Wdp" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".png"  -ProgID "PhotoViewer.FileAssoc.Png" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".tif"  -ProgID "PhotoViewer.FileAssoc.Tiff" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".tiff"  -ProgID "PhotoViewer.FileAssoc.Tiff" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".wdp"  -ProgID "PhotoViewer.FileAssoc.Wdp" -AppName 'Windows Photo Viewer'"
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Set-AppAssociation.ps1 -AssocXMLPath "C:\OSD\AppAssoc.xml" -Extention ".pdf"  -ProgID "AcroExch.Document.11" -AppName 'Adobe Reader'"

:: Import the file association XML to the file system with DISM
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& .\Restore-AppAssociation.ps1 -AssocXMLImportPath "C:\OSD\AppAssoc.xml""

Well that is it for today, I hope you enjoy this post !!

Monday, November 11, 2013

FIX: Setup could not configured one or more system components.

Whilst integrating the Dell E7240 and E6440 to our Windows 7 Sp1 64 bit image I got an error at deploy time right after the end of the WinPE Phase and in the first boot into Windows.

The error appeared after devices installation and in the phase where "Setup is applying system settings".

Here is a screen-shot of this error:


I opened a cmd prompt by pressing Shift + F10 and checked the "C:\Minint\SMSOSD\OSDLOGS\BDD.log" to see.

The "Property PHASE is now = STATERESTORE"  entry gave us an indicator as to where in the  TaskSequence the error occurred. Yet no specific steps where throwing the error as there was no entry in the BDD.log from ZTIGather.wsf (which is the script called by Gather local only).

Digging a bit further I took a look at the "C:\Windows\Panther\setuperr.log" and found this error.:
"[0x030153] CMI    Callback_CMI_ConfigInstall: CBS startup processing re-run failed."


From the cmd prompt I was also able to run mmc.exe to check the device manager and my Intel Management Engine Interface controller was showing a yellow ! with an error 37.

A quick google search for "setuperr [0x030153]  Intel Management Engine Interface"  took me to this page from the Dell Community Wiki where the reason for this problem is explained as quoted below:

" Reasons for failure:
-          Windows 7 Operating system comes with KMDF 1.9 (Kernel Mode driver framework) as part of image. Any driver release which is built with newer version of KMDF requires reboot of system during the installation, this reboot is unexpected during OS Setup.
-          If the Win7 image used contains any security update or patch affecting the KMDF components is used along with driver (which is built on newer version of KMDF) then deployment would fail. Example:KB2808735"

I tested the solution given in the article by mounting my image Wim with DISM, adding the package kmdf-1.11-Win-6.1-x64.msu to the mounted image and committing the change.

On the next deployment both the E7240 and E6440 deployed correctly.

I hope you find this entry useful. Until next time !!




Wednesday, November 6, 2013

How-To Run commands in SYSTEM context

Just a quick post on how to run commands, installation, programs in system context in windows vista and above.

For XP we use a tool called CmdAsSys.exe which we simply ran with admin rights.

But for windows 7 this tool would not run interactively in the currently logged in user session and instead the operating system would throw a prompt to change session which just isn't a convenient way to work.

Therefore, for Windows 7 we are now using psexec from sysinternals. This utility can be downloaded here.

From an elevated command prompt run:
PsExec -s -i cmd.exe

Here is a screenshot showing the command, task manager with the cmd.exe process running as SYSTEM as well as notepad started as SYSTEM.


That's it for now, hope you will find this entry useful and if you have other ways of doing this, please use the comment section to share them !!

Monday, November 4, 2013

How-To Manage the new Java security prompts without using keytool

As explained by Oracle on their web (follow this link for the full details):


"Java 7 Update 21 introduced changes to the Java browser plug-in behavior that enable you to make more informed decisions before running the Java applet in the browser. "

In the case of  "Java application with a certificate from a trusted authority" if the user checks the option "Do not show this again ... " well ... they would not get prompted again. 
Yet some administrator could still want to manage some of those prompts for their environment. For instance to prevent such prompt for their intranet applications.

To do so, you would need to: 

1. Get the URLs of the web pages throwing those warnings. 
2. On a test machine, install a version of Java that is higher than 7u21 and ensure that there is no trusted.certs file under C:\Users\<UserID>\AppData\LocalLow\Sun\Java\Deployment\security (unless you want to update an existing keystore)
3. Then browse each of the URLs you would like to pre-authorize on behalf of the users and ensure that you check the box "Do not show this again ... " and click on Run.

This will create and add the signing certificate information to the C:\Users\<UserID>\AppData\LocalLow\Sun\Java\Deployment\security\trusted.certs file.

To deploy this file you have several options, you could be using a GPO to push this file to your clients, or include it into your java package, or if java is installed in your corporate image simply copy it to the image prior to capturing it.

The file should be copied to the SYSTEM Java security folder - this way it will apply to all users. - under: 

C:\Program Files (x86)\Java\jre7\lib\security
and eventually 
C:\Program Files\Java\jre7\lib\security ( If you use 64-bit browser and 64 bit Java add-on) .

Here is a screenshot of the settings of a GPO that was tested to push the file to the clients: 


Should you want to carry on updating the keysotre file to add new applications as time passes then simply copy you existing trusted.certs file to your test machine - as per step 2 above - prior to adding more exceptions.

I have noticed when testing that the method that consists of first adding the certificate as described above and then going to the Java control panel to export the certificate as a .cer file to finally use keytool to add the signing certificate details to a keystore file did not work for me.

I have compared a working and a non-working trusted.certs file and the only difference I noticed was the Alias.  When letting java do the job of updating the trusted.certs the alias created looked like:
deploymentusercert$tsflag$loc=https//secure.entrust.com:443java.util.random@973f09
or
deploymentusercert$tsflag$loc=https//java.com:443java.util.random@a549a8
and this was the only way it would work. 

I hope you enjoy this article, until next time ...