Wednesday, January 30, 2013

Data Recovery

My RAID-0+1 (2 sets of RAID-0 2TB HDD's) just failed with two drives failing, both drives being from each stripe.  The worst case scenario.  The Intel RAID utility could not recover the array.  I went and then downloaded some utilities to try and recreate the array but they all couldn't determine what the array's configuration was that I setup.  Time to read up on Microsoft's clustering file shares.

SO I went ahead and recreated the array using defaults and then tried the tool "TestDisk".  TestDisk recognized my previous partition (which was GPT -- Wow!).  I had to manually set the type to NTFS then the tool could let me see the files within.  I pulled out about 900GB of Hyper-V VHD's and each one works perfectly.  I am going to try recreating the partitions with that tool, but it's telling me that the disk is too small, the previous partition is 4000MB and the current partition is 3800MB.  This maybe accurate because the Intel RAID utility tries to reserve 5% at the end of the array for expansion/drives of different sizes so they can be added to the array.  Once the recovery of the VHD's completes, I will recreate the array with a slightly larger size then use TestDisk to recover the partitions and update it here if it worked or not.

UPDATE: I was not able to recover the partitions but I was able to recover the files successfully.

Tuesday, January 22, 2013

Internet Explorer Maintenance Odd Behaviour

Recently, I was experiencing some odd behaviour on some of our Windows boxes.  We were getting redirected to a proxy server but RSOP.MSC and group policy showed that we should have been good in the GUI.

The issue is IE Maintenance will store it's settings in a INS file as opposed to the registry and for some reason IE Maintenance in GPEDIT.MSC doesn't display the values.  This document details it more:

http://blogs.technet.com/b/perfguru/archive/2008/04/26/how-to-troubleshoot-internet-explorer-s-maintenance-group-policy.aspx

The INS files created via GPO are placed in the following locations:
2003-"C:\Documents and Settings\trententtye\Local Settings\Application Data\Microsoft\Internet Explorer"
2008-"C:\Users\trententtye\AppData\Local\Microsoft\Internet Explorer"


Tuesday, January 15, 2013

Internet Explorer popping up outside the App-V Bubble

We have an application that launches Internet Explorer for printing certain PDF documents that it creates.  Adobe Reader is in the AppV package and NOT locally on the server.  The application resides in an AppV bubble but Internet Explorer starts outside the bubble.  I was able to verify that by starting the application with the debug switch "/exe cmd.exe" and running SET which shows some variables that only exist within an AppV bubble.  Once at the command prompt I launched the application and got to the point where it launched IE, from there I was able to use the IE open dialog to launch cmd.exe from the Windows\system32 folder.  Once that was open I ran SET again and the AppV variables were not there; this confirmed that it was not in the AppV bubble.

It appears this issue is caused by XenApp because it modifies the Internet Explorer handler registry keys to point to a unique Citrix version of IE.  This version appears to open outside the bubble.  to correct this you need to change these registry keys:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\Software\Classes\http\shell\open\command]
@="\"C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe\" \"%1\""

[HKEY_LOCAL_MACHINE\Software\Classes\https\shell\open\command]
@="\"C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe\" \"%1\""

[HKEY_LOCAL_MACHINE\Software\Classes\htmlfile\shell\opennew\command]
@="\"C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe\" \"%1\""

[HKEY_LOCAL_MACHINE\Software\Classes\htmlfile\shell\open\command]
@="\"C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe\" \"%1\""

With the keys set like that Internet Explorer will now launch within the AppV bubble.

Tuesday, January 08, 2013

Modify XML files with PowerShell (for manipulating AppV)

#===================================CHANGE OS VALUE===========================================
#
#   By Trentent Tye 2012-12-19
#
#   This script will find all the applications in TEST and PROD and query the user to
#   which application they want to change the OS VALUE in the OSD file.  You will be given
#   four options.  1 - Remove any OS VALUE from the file, 2 - Set an OS VALUE,
#    4 - Get current value (if exists)
#
#
#
#
#
#

#=====================================================================================
#=====================================================================================

#setting up variables
$APPV_Packages_Path = "\\jeeves\appv_images"

#Which environment to change?
$caption = "Choose Action";
$message = "Modify OS VALUE for which type of application?";
$Prod = new-Object System.Management.Automation.Host.ChoiceDescription "&Prod","Prod";
$Test = new-Object System.Management.Automation.Host.ChoiceDescription "&Test","Test";
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($Test,$Prod);
$answer = $host.ui.PromptForChoice($caption,$message,$choices,0)
 
switch ($answer){
    0 {"You entered Test"; $Env = "TEST"}
    1 {"You entered Prod"; $Env = "PROD"}
}

#=====================================================================================
#=====================================================================================

#get list of applications (osd files) and put into a dictionary and
#display the key-value combos for user to enter a number
#if the user does not enter a correct choice, show the screen again.
Clear-Host
$completedsuccessfully = $TRUE
do {
$list = dir $APPV_Packages_Path\$ENV -include *.osd -recurse | Select-Object -ExpandProperty Name  | sort
$n = 0

#create a dictionary and put all the OSD files into it and add a numerical value to each one
$dict = New-Object 'System.Collections.Generic.Dictionary[String,String]'

foreach ($i in $list) { 
$n++
$dict.Add("$n","$i")
}

#format the dictionary nicely...
$dict | ft -auto

$appChoice = read-host -Prompt "Please select an application"
$appName = $dict.Get_Item("$appChoice")
if ($?) {
   $completedsuccessfully = $TRUE
   } else {
   Clear-Host
   Write-Host "An invalid choice (" -nonewline; Write-Host "$appChoice" -f Red -nonewline; Write-Host ") was selected";
   $completedsuccessfully = $FALSE
   }
} until ($completedsuccessfully)
Write-Host "You selected '" -nonewline; Write-Host "$appName" -f Yellow -nonewline; Write-Host "'";

#=====================================================================================
#=====================================================================================
#Setup functions for the next section

function GetOSValue() {
    #get the path to the OSD file
    #Get OSD file as an XML
    $OSDFile = dir $APPV_Packages_Path\$ENV -include $appName -recurse
    [xml]$OSD = Get-Content "$OSDFile"
    Write-host "======================================================================"
    Write-host ""
    Write-host "Application: " -nonewline; write-host "$appName" -f Yellow;
    $OSD.SOFTPKG.IMPLEMENTATION.OS | fl | Out-String
    Write-host "======================================================================"
}

function RemoveOSValue() {
    #get the path to the OSD file
    #Get OSD file as an XML
    $OSDFile = dir $APPV_Packages_Path\$ENV -include $appName -recurse
    [xml]$OSD = Get-Content "$OSDFile"
    Write-host "======================================================================"
    Write-host ""
    Write-host "Application: " -nonewline; write-host "$appName" -f Yellow;
    Write-host "" ; write-host "Original value:"
    $OSD.SOFTPKG.IMPLEMENTATION.OS | fl
    Write-Host "Removing ALL OS Value(s)..."

    #select OS node from the XML file  
    #remove the node, continue until no more OS Values exist
    try {
        do {
            $node = $OSD.SelectSingleNode("//SOFTPKG/IMPLEMENTATION/OS")
            [Void]$node.ParentNode.RemoveChild($node)
        } until ( $? -eq $FALSE )
    } catch {
        write-host "Complete"
        write-host ""
    }



    #backup the original file
    $File = dir $APPV_Packages_Path\$ENV -include $appName -recurse
    $fileObj = get-item $File

    # Get the date
    $DateStamp = get-date -uformat "%Y-%m-%d@%H-%M-%S"

    #make our backup
    copy "$File" "$File-$DateStamp"

    # Display the new name
    "Backup filename: $File-$DateStamp"

    #save our file 
    $osd.Save($OSDfile)
    

    Write-host "======================================================================"
}

function SetOSValue() {
    #get the path to the OSD file
    #Get OSD file as an XML
    $OSDFile = dir $APPV_Packages_Path\$ENV -include $appName -recurse
    [xml]$OSD = Get-Content "$OSDFile"
    Write-host "======================================================================"
    Write-host ""
    Write-host "Application: " -nonewline; write-host "$appName" -f Yellow;
    write-host ""
    Write-Host "Setting OS Value..."
    #select OS node from the XML file  
    # Creation of a nod ans his text
    $xmlElt = $OSD.CreateElement("OS")
    # Creation of an attribute in the principal nod
    $xmlAtt = $OSD.CreateAttribute("VALUE")

    #ask which OS you'd like
    $caption = "Choose Action";
    $message = "Which OS do you want to deploy this app?";
    $2003 = new-Object System.Management.Automation.Host.ChoiceDescription "&3 - 2003 R2 x32","2003 R2 x32";
    $2008 = new-Object System.Management.Automation.Host.ChoiceDescription "&8 - 2008 R2 x64","2008 R2 x64";
    $choices = [System.Management.Automation.Host.ChoiceDescription[]]($2003,$2008);
    $answer = $host.ui.PromptForChoice($caption,$message,$choices,0)
 
    switch ($answer){
        0 {$xmlAtt.Value = "Win2003TS"}
        1 {$xmlAtt.Value = "Win2008R2TS64"}
    }

    
    # Appending the attribute to the element
    $xmlElt.Attributes.Append($xmlAtt)
    # Appending the new element to the proper location
    [void]$OSD.SOFTPKG.IMPLEMENTATION.AppendChild($xmlElt)


    $osd.Save($OSDfile)
    

    Write-host "======================================================================"
}


#=====================================================================================
#=====================================================================================

#What would they like to do to the file?
function action() {
$caption = "Choose Action";
$message = "Modify OS VALUE for which type of application?";
$1 = new-Object System.Management.Automation.Host.ChoiceDescription "&1 Remove OS VALUE","Remove OS VALUE";
$2 = new-Object System.Management.Automation.Host.ChoiceDescription "&2 Set an OS VALUE","Set an OS VALUE";
$3 = new-Object System.Management.Automation.Host.ChoiceDescription "&3","";
$4 = new-Object System.Management.Automation.Host.ChoiceDescription "&4 Get current OS VALUE","Get current OS VALUE";
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($1,$2,$3,$4);
$answer = $host.ui.PromptForChoice($caption,$message,$choices,3)
 
switch ($answer){
    0 {RemoveOSValue;exit}
    1 {RemoveOSValue;SetOSValue;exit}
    2 {Write-Host "Incorrect Option, please try again"}
    3 {GetOSValue}
  }
}

#loop forever
$loop = 1
do {action} until ($loop = 0)