2017-11-29 22:41:16

SharePoint Missing Setup Files Webpages

As like from my last post covers any missing webparts, that won't actually remove any webpages the SharePoing Admins created along the way.
So here's the next solution should you need to remove those web pages, if you don't wish to re-install the third party solution.

EXample Error Message:

Category        : MissingSetupFile
Error           : True
UpgradeBlocking : False
Message         : File [Features\K2WebDesignerV2\PageTemplates\K2WebDesigner.aspx] is referenced [4] times in the database 
                  [WSS_Content_OpsCentre], but is not installed on the current farm. Please install any feature/solution which contains 
                  this file.
Remedy          : One or more setup files are referenced in the database [WSS_Content_OpsCentre], but are not installed on the current 
                  farm. Please install any feature or solution which contains these files.
Locations       : 
Here's my script, just as effective and vulgur as my last one. :D
########################################################################################################################## 
# Author: Zewwy (Aemilianus Kehler)
# Date:   Oct 28, 2017
# Script: Delete-SPWebFiles
# This script allows to remove Web Parts from the Web Parts Gallery.
# Cudos to Phil Childs from get-spscripts.com
# Required parameters: 
#   A valid  SharePoint Site Collection URL and a string (case insensitive :D) for the particular SP File.
#   Best to be run from a SharePoint Mgmt Console with an account that has collection admin on the Web URL 
##########################################################################################################################

##########################################################################################################################
#   Variables
##########################################################################################################################
#The Varible used to display wrong URL provided, or not found
$BadURL = @("Sorry, the string you entered ","is not a valid Site Collection.")
#File not found from SQL query response
$BadfileQry = "Sorry mate but it seems the dingo ate your file."
#MyLogoArray
$MylogoArray = @("#####################################","# This script is brought to you by: #","#                                   #","#             Zewwy                 #","#                                   #","#####################################"," ")
#Static Variables
$ScriptName = "Delete-SPWebFiles; cause some SharePoint files just suck ass.`n"
$SQLServer = "Server\instance"
$DB = "WSS_Content"

$pswheight = (get-host).UI.RawUI.MaxWindowSize.Height
$pswwidth = (get-host).UI.RawUI.MaxWindowSize.Width

##########################################################################################################################
#   Functions
##########################################################################################################################

#function takes in a name to alert confirmation of deletion of a web part, returns true or false
function confirm($name)
{
    #function variables, generally only the first two need changing
    $title = "Confirm SharePoint File Deletion!"
    $message = "You are about to delete SharePoint File: $name"

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "This means Yes"
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "This means No"

    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

    $result = $host.ui.PromptForChoice($title, $message, $Options, 0)
    Write-Host " "
    Switch ($result)
        {
              0 { Return $true }
              1 { Return $false }
        }
}

#Function to Centeralize Write-Host Output, Just take string variable parameter and pads it
#Nerd Level over 9000!!! Ad-hoc Polymorphic power time!!
function Centeralize()
{
  param(
  [Parameter(Position=0,Mandatory=$true)]
  [string]$S,
  [Parameter(Position=1,Mandatory=$false,ParameterSetName="color")]
  [string]$C
  )
    $sLength = $S.Length
    $padamt =  "{0:N0}" -f (($pswwidth-$sLength)/2)
    $PadNum = $padamt/1 + $sLength #the divide by one is a quick dirty trick to covert string to int
    $CS = $S.PadLeft($PadNum," ").PadRight($PadNum," ") #Pad that shit
    if ($C) #if variable for color exists run below
    {    
        Write-Host $CS -ForegroundColor $C #write that shit to host with color
    }
    else #need this to prevent output twice if color is provided
    {
        $CS #write that shit without color
    }
}

#Function provided by phil to check the content database via the sharepoint front end server
function Run-SQLQuery ($SqlServer, $SqlDatabase, $SqlQuery)
{
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Server =" + $SqlServer + "; Database =" + $SqlDatabase + "; Integrated Security = True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = $SqlQuery
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $SqlConnection.Close()
    $DataSet.Tables[0]
}

#Start actual script by posting and asking user for responses
foreach($L in $MylogoArray){Centeralize $L "green"}
Centeralize $ScriptName "White"
#Notify User to enter the Site Collection URL then check if it exits.
Centeralize "Please enter a SP Site Collection URL`n"
Write-host "SharePoint Site Collection URL: " -ForegroundColor Magenta -NoNewline
$SPSitecolstr = Read-Host
Write-Host " "
Centeralize "Verifying SharePoint Site Collection URL, Please Wait...`n" "White"
if ($SPSiteCol=Get-SPSite $SPSitecolstr -EA SilentlyContinue)
{
    $DB = $SPSiteCol.ContentDatabase.Name
    $SQLServer = $SPSiteCol.ContentDatabase.Server
    Centeralize "Phhhh, ok good guess, that is a site collection here's what the systems got:`n" "Cyan"
    Centeralize "SqlSever\Instance: $SQLServer Using Database: $DB `n" "White"
    Write-host "What file you lookin' for boy?: " -ForegroundColor Magenta -NoNewline
    $StupidFile = Read-Host
    Write-Host " "
    $Shitfile = "'%"+$StupidFile+"%'"
    try
    {
        [System.Collections.ArrayList]$ShitArray = Run-SQLQuery -SqlServer $SQLServer -SqlDatabase $DB -SqlQuery "SELECT * from AllDocs where SetupPath LIKE $Shitfile" -ErrorAction Stop
    }
    catch
    {
        $BadfileQry += " This `"$StupidFile`""
        Centeralize "$BadFileQry" "Red"
        Break
    }
    $ShitArray.RemoveAt(0) #For some reason the query's first result (or more to say the first element in the object array) was the result amount, so remove it from the array
    #$ShitArray | select Id, SiteId, DirName, LeafName, WebId, ListId | Format-List
    #$ShitArray.Count #entered for testing purposes, should be removed
    foreach($ShittyFile in $ShitArray)
    {
        $SPWeb = $SPSiteCol | Get-SPWeb -limit all | where {$_.ID -eq $ShittyFile.WebId}
        $SPWURL = $SpWeb.Url
        if(!$SPWURL.EndsWith("/")){$SPWURL+="/"}
        $file = $SPWeb.GetFile([Guid]$ShittyFile.ID)
        $fn = $file.Name
        Centeralize "File Found: $SPWURL$fn" "Yellow"
        if (confirm $SPWURL$fn)
                {
                    Centeralize "Deleting Web File: $SPWURL$fn`n" "Red"
                    $file.Delete() 
                } 
    }   
}
else
{
    $SPSitecolstr = "`""+$SPSitecolstr+"`" "
    $BadURL = $BadURL[0] + $SPSitecolstr + $BadURL[1]
    foreach($str in $BadURL){Centeralize $str "red"}
}

Posted by Aemilianus Kehler | Permanent link

2017-11-29 22:23:14

SharePoint Missing Setup Files Webparts

As like from my last post covers any missing features, that won't actually remove any webparts the third party application installed along the way.
So here;s the next solution should you need to remove those web parts, if you don't wish to re-install the third party solution.

EXample Error Message:

Category        : MissingSetupFile
Error           : True
UpgradeBlocking : False
Message         : File [Features\SourceCode.SharePoint.WebPart.Reporting14_ReportingWebparts\ActivityGraph\ActivityGraph.webpart] is 
                  referenced [1] times in the database [WSS_Content_OpsCentre], but is not installed on the current farm. Please install 
                  any feature/solution which contains this file.
Remedy          : One or more setup files are referenced in the database [WSS_Content_OpsCentre], but are not installed on the current 
                  farm. Please install any feature or solution which contains these files.
Here's my script, just as effective and vulgur as my last one. :D
Solution:
########################################################################################################################## 
# Author: Zewwy (Aemilianus Kehler)
# Date:   Oct 28, 2017
# Script: Delete-SPWebParts
# This script allows to remove Web Parts from the Web Parts Gallery.
# Cudos to Carlos from Technet Galleries  
# Required parameters: 
#   A valid root SharePoint Web URL and a case senstive string for the particular Web Part.
#   Best to be run from a SharePoint Mgmt Console with an account that has collection admin on the Web URL 
##########################################################################################################################

##########################################################################################################################
#   Variables
##########################################################################################################################

#The Variable used to display the message that no web parts were found.
$NoWPFound = "Sorry to inform you, but the system returned no results for deletion. :("

#The Varible used to display wrong URL provided, or not found
$BadURL = "Sorry doofus that is not a known SharePoint Web URL"

#MyLogoArray
$MylogoArray = @("#####################################","# This script is brought to you by: #","#                                   #","#             Zewwy                 #","#                                   #","#####################################"," ")

#Static Variables
$pswheight = (get-host).UI.RawUI.MaxWindowSize.Height
$pswwidth = (get-host).UI.RawUI.MaxWindowSize.Width

##########################################################################################################################
#   Modules
##########################################################################################################################

#Load Sharepoint Modules
If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )  
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell }


##########################################################################################################################
#   Functions
##########################################################################################################################

#function takes in a name to alert confirmation of deletion of a web part, returns true or false
function confirm($name)
{
    #function variables, generally only the first two need changing
    $title = "Confirm WebPart Deletion!"
    $message = "You are about to delete WebPart: $name"

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "This means Yes"
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "This means No"

    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

    $result = $host.ui.PromptForChoice($title, $message, $Options, 0)

    Switch ($result)
        {
              0 { Return $true }
              1 { Return $false }
        }
}

#Function provided by phil to check the content database via the sharepoint front end server
function Run-SQLQuery ($SqlServer, $SqlDatabase, $SqlQuery)
{
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Server =" + $SqlServer + "; Database =" + $SqlDatabase + "; Integrated Security = True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = $SqlQuery
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $SqlConnection.Close()
    $DataSet.Tables[0]
}

#Function that delete Web Parts from the Web Parts catalog 
function RemoveWebPartsFromCatalog ($SPWA, $TSFWP)
{    
    try 
    {    
        #Variable to hold the Web Part Catalog, I'm not sure exactly why this line is here       
        $wpCatlog = [Microsoft.SharePoint.SPListTemplateType]::WebPartCatalog
        #This on creates a variable to hold the list of all the web parts located in the catalog
        $WPList = $SPWA.GetCatalog([Microsoft.SharePoint.SPListTemplateType]::WebPartCatalog)
        #Orginally i attmpted to delete the web part directly in the inital foreach loop
        #However since the item wanting to be deleted is part of the system array variable we are iterating through
        #It would crash the script after deleting the first item asked to successfully, instead
        #theres a variable used to contain all the web part ids to run a second foreach loop
        $wpIDlist = @()      
        foreach ($spItem in $WPList.Items)  #Iterating through all web parts
        {
            $S1=$TSFWP.ToLower();$S2=$spItem.DisplayName.ToLower(); # To deal  with case sensitivity   
            if($S2.Contains("$S1")) #Check for given string (this is the case senstive bullshit part)
            {  
               # $wpName = $spItem.DisplayName
               # Centeralize "Web Part Found!: $wpName" "yellow"
               # Write-Host "Web Part ID!: " $spItem.ID
                $wpIDlist += $spItem.ID 
            }                                   
        }
        #if No Web Part Found 
        if($wpIDlist.Count -eq 0)
        {
            Centeralize $NoWPFound "yellow"
        }
        else
        {
            foreach($wp in $wpIDlist)
            {
                $wpItem = $WPList.GetItemById($wp)
                $wpName = $wpItem.DisplayName
                Centeralize "Web Part Found!: $wpName" "yellow" 
                if (confirm $wpItem.DisplayName)
                {
                    Centeralize "Deleting Web Part: $wpName`n" "Red"
                    $wpItem.Delete() 
                } 
            }
            $WPList.Update()
        }     
        $WPList.Update() 
        $SPWA.Dispose()     
    } 
    catch [System.Exception] 
    { 
        write-host -f red $_.Exception.ToString() 
    } 
}

#Function to Centeralize Write-Host Output, Just take string variable parameter and pads it
#Nerd Level over 9000!!! Ad-hoc Polymorphic power time!!
function Centeralize()
{
  param(
  [Parameter(Position=0,Mandatory=$true)]
  [string]$S,
  [Parameter(Position=1,Mandatory=$false,ParameterSetName="color")]
  [string]$C
  )
    $sLength = $S.Length
    $padamt =  "{0:N0}" -f (($pswwidth-$sLength)/2)
    $PadNum = $padamt/1 + $sLength #the divide by one is a quick dirty trick to covert string to int
    $CS = $S.PadLeft($PadNum," ").PadRight($PadNum," ") #Pad that shit
    if ($C) #if variable for color exists run below
    {    
        Write-Host $CS -ForegroundColor $C #write that shit to host with color
    }
    else #need this to prevent output twice if color is provided
    {
        $CS #write that shit without color
    }
}

#Start actual script by posting and asking user for responses
foreach($L in $MylogoArray){Centeralize $L "green"}
Centeralize "Delete-SPWebParts; cause some Web Parts just suck ass.`n" "White"
#Notify User to enter the Site Collection URL then check if it exits.
Centeralize "Please enter a SP Web URL`n"
Write-host "SharePoint Web URL: " -ForegroundColor Magenta -NoNewline
$SPWebURL = Read-Host
Write-Host " "
Centeralize "Verifying SharePoint web URL, Please Wait...`n"
if ($SPWeb=Get-SPWeb $SPWebURL -EA SilentlyContinue)
{
    Centeralize "K, The SPWeb URL you entered appears to be valid.`n" "Cyan"
    if(!$SPWeb.IsRootWeb){Centeralize "But it is not a root web, you fail!" "Red"; Exit}
    Write-Host "Sigh... This HAS to be case sensitive.`nNow what does the Web Part name you are looking for contain? " -ForegroundColor Magenta -NoNewline
    $SPWPS = Read-Host
    #Write-Host " " #Need this to make new line
    #if(Confirm "$SPWPS from: $SPWebURL")
    #{
        $Ugh = @(" ","Attempting to locate web parts with the parameters you defined.","Please Wait.","I must say you are not making this easy."," ")
        foreach($lineitem in $Ugh){Centeralize $lineitem "Cyan"}
        RemoveWebPartsFromCatalog $SPWeb $SPWPS
    #}
}
else
{
    Centeralize $BadURL "red"
}

Posted by Aemilianus Kehler | Permanent link

2017-11-10 22:47:19

SharePoint Missing Feature

This is the message you'll see about missing features:
Category        : MissingFeature
Error           : True
UpgradeBlocking : False
Message         : Database [WSS_Content_OpsCentre] has reference(s) to a missing feature: Id = [a59ff911-7eb6-4671-abea-079e58218fde],
                  Name = [K2 Site Settings], Description = [Adds the K2 Site Settings link to the Site Actions menu, allowing for
                  configuration of K2 components in the site collection.], Install Location = [K2SiteSettings].
Remedy          : The feature with Id a59ff911-7eb6-4671-abea-079e58218fde is referenced in the database [WSS_Content_OpsCentre], but is
                  not installed on the current farm. The missing feature may cause upgrade to fail. Please install any solution which
                  contains the feature and restart upgrade if necessary.
This isn't anything new, it has been discussed here and also here. While Phil and Eitenne did a good job with their scripts (Phils was a big source for my own) they didn't exactly meet my expectations.
That mostly being being able to run a script without editing it and be able to clean up my mess. Now you might think that soudns rediculous cause everyones enviroemnt is different.
While I do agree there, that doesn't mean ones scipt can't ask for these variables instead of having to edit the script to define them.
Here's my script and a picture of what I mean.



If you think this is cool and exactly what you need to fix your SharePoint. Have at my code, I offer it as is, without warranty, and use at your own risk.
This is one of 4 scripts to be released on an epic Sharepoint adventure!
########################################################################################################################## 
# Author: Zewwy (Aemilianus Kehler)
# Date:   Oct 28, 2017
# Script: Remove-SPSiteFeature
# This script allows to remove Site Collection Features.
# Cudos to Phil Childs from get-spscripts.com
# Required parameters: 
#   A valid  SharePoint Site Collection URL and a string (case insensitive :D) for the particular SP Feature.
#   Best to be run from a SharePoint Mgmt Console with an account that has collection admin on the Web URL 
##########################################################################################################################

##########################################################################################################################
#   Variables
##########################################################################################################################
#The Varible used to display wrong URL provided, or not found
$BadURL = @("Sorry, the string you entered ","is not a valid Site Collection.")
#File not found from SQL query response
$BadfileQry = "Sorry mate but it seems the dingo ate your file."
#MyLogoArray
$MylogoArray = @("#####################################","# This script is brought to you by: #","#                                   #","#             Zewwy                 #","#                                   #","#####################################"," ")
#Static Variables
$ScriptName = "Remove-SPSiteFeature; cause some SharePoint features just suck ass.`n"
$SQLServer = "Server\instance"
$DB = "WSS_Content"

$pswheight = (get-host).UI.RawUI.MaxWindowSize.Height
$pswwidth = (get-host).UI.RawUI.MaxWindowSize.Width

##########################################################################################################################
#   Functions
##########################################################################################################################

#function takes in a name to alert confirmation of deletion of a web part, returns true or false
function confirm($name)
{
    #function variables, generally only the first two need changing
    $title = "Confirm SharePoint Feature Removal!"
    $message = "You are about to remove a SharePoint Feature: $name"

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "This means Yes"
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "This means No"

    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

    $result = $host.ui.PromptForChoice($title, $message, $Options, 0)
    Write-Host " "
    Switch ($result)
        {
              0 { Return $true }
              1 { Return $false }
        }
}

#Function to Centeralize Write-Host Output, Just take string variable parameter and pads it
#Nerd Level over 9000!!! Ad-hoc Polymorphic power time!!
function Centeralize()
{
  param(
  [Parameter(Position=0,Mandatory=$true)]
  [string]$S,
  [Parameter(Position=1,Mandatory=$false,ParameterSetName="color")]
  [string]$C
  )
    $sLength = $S.Length
    $padamt =  "{0:N0}" -f (($pswwidth-$sLength)/2)
    $PadNum = $padamt/1 + $sLength #the divide by one is a quick dirty trick to covert string to int
    $CS = $S.PadLeft($PadNum," ").PadRight($PadNum," ") #Pad that shit
    if ($C) #if variable for color exists run below
    {    
        Write-Host $CS -ForegroundColor $C #write that shit to host with color
    }
    else #need this to prevent output twice if color is provided
    {
        $CS #write that shit without color
    }
}

#Found Function, to be called whenever the feature is found... Sorry guys I kinda had bad code using the break, whoopsie.
function FoundItinWeb($ss, $SPF)
{
    $FName = "Feature Found: "+$SPF.Definition.DisplayName
    Centeralize $FName "Yellow"
    
    #[System.Collections.ArrayList]$ShitArray = "Parent Site: "+$SPFeature.Parent.Url,"Feature guid: "+$SPFeature.DefinitionId.Guid #,"Feature ID: "+$SPFeature.Definition.Id,"Feature Name: "+$SPFeature.Definition.DisplayName,"Compatibility Level: "+$SPFeature.Definition.CompatibilityLevel,"Physical File: "+$SPFeature.Definition.RootDirectory,"Scope: "+$SPFeature.$SPFeature.FeatureDefinitionScop)
    [System.Collections.ArrayList]$ShitArray = @("Parent Site: "+$SPF.Parent.Url)
    $ShitArray += "Feature guid: "+$SPF.DefinitionId.Guid
    $ShitArray += "Feature ID: "+$SPF.Definition.Id
    $ShitArray += "Feature Name: "+$SPF.Definition.DisplayName
    $ShitArray += "Compatibility Level: "+$SPF.Definition.CompatibilityLevel
    $ShitArray += "Physical File: "+$SPF.Definition.RootDirectory
    $ShitArray += "Scope: "+$SPF.FeatureDefinitionScope

    foreach($line in $ShitArray){Centeralize $line "white"}
    $FName = $SPF.Definition.DisplayName
    if(confirm $FName)
    {     
        Centeralize "Deleting SharePoint Feature $FName`n" "Red"
        $ss.Features.Remove($SPF.DefinitionId, $true)
    }
}

function FoundIt()
{
    $FName = "Feature Found: "+$SPFeature.Definition.DisplayName
    Centeralize $FName "Yellow"    
    [System.Collections.ArrayList]$ShitArray = @("Parent Site: "+$SPFeature.Parent.Url)
     $ShitArray += "Feature guid: "+$SPFeature.DefinitionId.Guid
     $ShitArray += "Feature ID: "+$SPFeature.Definition.Id
     $ShitArray += "Feature Name: "+$SPFeature.Definition.DisplayName
     $ShitArray += "Compatibility Level: "+$SPFeature.Definition.CompatibilityLevel
     $ShitArray += "Physical File: "+$SPFeature.Definition.RootDirectory
     $ShitArray += "Scope: "+$SPFeature.FeatureDefinitionScope

     foreach($line in $ShitArray){Centeralize $line "white"}
     $FName = $SPFeature.Definition.DisplayName
     if(confirm $FName)
     {     
         Centeralize "Deleting SharePoint Feature $FName" "Red"
         $SPSiteCol.Features.Remove($SPFeature.DefinitionId, $true)
     }
     #Remember the site is checked first, so even if the feature is found in the main site we don't want to forget each sub site
     TryWeb
}

function TryWeb()
{
        $SSW = $SPSiteCol | Get-SPWeb
        foreach($ss in $SSW)
        {
            $SPWFeature=$ss.Features[$StupidFeatureStr]
            if($SPWFeature)
            {
                FoundItInWeb $ss $SPWFeature
            }
        }
        Write-Host "Script is done."
}

#Start actual script by posting and asking user for responses
foreach($L in $MylogoArray){Centeralize $L "green"}
Centeralize $ScriptName "White"
#Notify User to enter the Site Collection URL then check if it exits.
Centeralize "Please enter a SP Site Collection URL`n"
Write-host "SharePoint Site Collection URL: " -ForegroundColor Magenta -NoNewline
$SPSitecolstr = Read-Host
Write-Host " "
Centeralize "Verifying SharePoint Site Collection URL, Please Wait...`n" "White"
if ($SPSiteCol=Get-SPSite $SPSitecolstr -EA SilentlyContinue)
{
    $DB = $SPSiteCol.ContentDatabase.Name
    $SQLServer = $SPSiteCol.ContentDatabase.Server
    Centeralize "Phhhh, ok good guess, that is a site collection here's what the systems got:`n" "Cyan"
    Centeralize "SqlSever\Instance: $SQLServer Using Database: $DB `n" "White"
    Write-host "Please enter the feature ID string: " -ForegroundColor Magenta -NoNewline
    $StupidFeatureStr = Read-Host
    Write-Host " "
    $SPFeature = $SPSiteCol.Features[$StupidFeatureStr]
    if(!$SPFeature)
    {
        Write-Host "Not Found in main site.... Trying Web"
        TryWeb
    }
    else
    {
         #Call Found Function
         Write-Host "Found in main site running found it function."
         FoundIt
    }

}
else
{
    $SPSitecolstr = "`""+$SPSitecolstr+"`" "
    $BadURL = $BadURL[0] + $SPSitecolstr + $BadURL[1]
    foreach($str in $BadURL){Centeralize $str "red"}
}   

Posted by Aemilianus Kehler | Permanent link

2017-11-01 19:46:26

Clearing the cache

This one will be nice and short. I was working on a DNZ zone migration, from one domain to another. Since the zone wasn't the parent zone of the AD domain it was in I had two options.
One make the new domain authorative for the zone, once trust is established they would take over for the zone.
Or in this case since there were only a few records and the new AD domain was already created with the same domain anem as the zone I was attempting to migrate, I figured I'd simply recreate the records manually.
Basically setup your conditional forwarders to the new domain DC's which will be authorative for the new zone. Generally allow UDP (TCP as well if you want to be extra safe) on port 53 through the firewall, and records should resolve just fine.
In this case you'll clearly notice that resolving the record for the transferred zone from the orginal domain now replies with non-authorative answer.
This is to be expected as the domain's DC that you are associated with (and generally your DNS settings configured to via DHCP of course) are no longer controlling the zone (adding/removing/editing records).
Again as to be expecting these are now managed via the new domain which teh zone was transferred to.

So low and behold I messed u one of the records IP addresses. So sure it's super fast to adjust and force replication, however replication would be domain/forest wide. Which even though I did on both domains i found my previous DC's would update the non-authorative answer.
I tripple checked all systems in teh new domain could get the proper reply from the DC/DNS servers. So what gives why were the old DC's DNS servers replying with the old IP address, when the conditional forwarders were setup to query the proper DNS servers and they were 100% holding the correct IP address?
The answer? Cache? yup the lovely blessing and nightmare that is cache. so what does any regular workstation admin try... yeah you guessed it "ipconfig /flushdns" (cmon were talking AD here which is Microsoft specific AFAIK). Do a query from your old domain DC's and yet the record is still the old IP adress?!?!
What gives? Well... in this case ipconfig /flushdns is only used for clients. You maybe wondering isn't the old DC a client in this case? Yes/No It's still a DNS server, and it still needs to answer queries it recieves, the command provided would help if simply doing a query (yes we are doing a query but for a record it needs to hold a record for to reply with).
Just to stop beating around the bush, as a DNS server it needs to clear its own cache, the records to retains to provide to requesting clients. this is a different command. in this case it's dnscmd /clearcache.
That's it, do another lookup and find your old DC DNS servers showing a non-authorative answer of the new IP address. Of course you could have also simply waited for cache to clear and replication to occur naturally... but ain't no body got time for that!

 1) To Clear Dns from a client system (Windows): ipconfig /flushdns
 2) To clear non-authortive DNS servers cache:	 dnscmd /clearcache

Posted by Aemilianus Kehler | Permanent link

2017-10-30 19:09:19

Exit, Break, and Return

The Break, The Return, and the Exit are all well break dance moves even the newiest of new comers knows about.
Hahaha, Nah I'm just making that shit up. They are however great tools for powershell scripting.
However, do you know what the difference in all of them are, and when best to use them?

For a longer answer and some explainations visit this site. :D
If not whatever here's the quick low down so you can save going to that day of class. :P

	1) Break terminates execution of a loop or switch statement and hands over control to next statement after it.
	2) Return terminates execution of the current function and passes control to the statement immediately after the function call.
	3) Exit terminates the current execution session altogether. It also closes the console window and may or may not close ISE depending on what direction the wind is facing.

Posted by Aemilianus Kehler | Permanent link

2017-10-28 23:12:02

Arrays Gone Astray

Arrays Gone Astray

I love powershell, and as one figures you'll have to deal with arrays. and when you learn them, they become a handy tool for any dev/scripters toolkit.
This guy covers it well. in short do this

PS C:\Scripts> $Fruit = @("Apple","Banna","Orange")
PS C:\Scripts> $Fruit.Add("Kiwi")
Exception calling "Add" with "1" argument(s): "Collection was of a fixed size."
At line:1 char:1
+ $Fruit.Add("Kiwi")
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NotSupportedException

PS C:\Scripts> $Fruit = $Fruit + "Kiwi"
PS C:\Scripts> $Fruit
Apple
Banna
Orange
Kiwi
PS C:\Scripts> $Fruit.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS C:\Scripts> $Fruit = $Fruit - "Kiwi"
Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'.
At line:1 char:1
+ $Fruit = $Fruit - "Kiwi"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (op_Subtraction:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound
PS C:\Scripts> $Fruit = $Fruit -ne "Kiwi"
PS C:\Scripts> $Fruit
Apple
Banna
Orange
PS C:\Scripts> $FruitIsFixedSize
PS C:\Scripts> $Fruit.IsFixedSize
True

Posted by Aemilianus Kehler | Permanent link

2017-10-28 20:37:47

Center Write-Host Output

Write-Host

It's great and it's main purposes is to well write to the host. Nothing more. So often people abuse it and leaving people to rant about it.
E.G. This guy and the "Gurus"
I agree with both of them in terms of displaying data, hands down. However, when it comes to simple informing the admin/user of the script the "it displays and gets rid of that info" is effiecent, and interactive (colors).

With that out of the way. I am working on a script to clear web parts from a sharepoint page via powershell.
I always like clean code an usually my scripts are interactive, for other non-interactive scripts I'd stick with Write-Output as descibed by the scripting guys.
However since I like to display things colorfully and neatly Write-Host is perfect!

The Problem

Turns out there's no easy way to get-write host to center it's output, no mater how hard I googled. This reply from James Bernie however kicked off the idea it was possible.
There were actually a decent amount of issues with his propsed idea, when implemented. First we'll want a static variable of the window size at start of script.
Then it turns out Bernies fancy full integer trick may return whole numbers, but does so as a dang string type. Instead of wasting time dicking around with another method, i simply did this trick of dividing by 1 on the variable.
The final problem with his concept which was driving me nuts for a good while was due to the fact of how padding method actually works.
PadLeft adds spaces to the left of a string.
This is handy for numeric out-put because padding keeps the numbers properlly aligned on the right.
This was exactly the problem I was facing, testing my existing function with a series of dots of different lengths, I found them all to be right aligned, and not centered.
Another issue I found was that the pipe into measure method under an expression based section of code and calling its sub routine of count ($var | measure).count wasn't returning the correct value.
That line was pretty stupid anyway when you can simply call any variable thats of a string type length method.
And the final nail in the logical coffin, the padding was again aligning more right of center than actual center due to the fact that's what it was comparing to first in the convert.
So it made more sense to take ((Wdith of screen) - String.Length)/2 + String.Length, this associated with a left and right padding, creates a centered master piece!!
Finally!!

Here's the final thing I had to overcome. My function I wanted to support Write-Host outputs color param.
As it turns out, overloading functions isn't supported in powershell, but that didn't stop someone from comming up with a work around!
This guy and his buzz works... Woo Ad-hoc Polymorphism!!! OK OK... here's my final piece of code for you guys. NOTE I didn't do fully ad hoc polythingy I cheated and only supprted foreground color via an if else.
If you *burp* want to make it support background and foreground... Uhhhhh.. do it yourself... getting to wasted right now...

#Function to Centeralize Write-Host Output, Just take string variable parameter and pads it
#Nerd Level over 9000!!! Ad-hoc Polymorphic power time!!
$pswwidth = (get-host).UI.RawUI.MaxWindowSize.Width
function Centeralize()
{
  param(
  [Parameter(Position=0,Mandatory=$true)]
  [string]$S,
  [Parameter(Position=1,Mandatory=$false,ParameterSetName="color")]
  [string]$C
  )
    $sLength = $S.Length
    $padamt =  "{0:N0}" -f (($pswwidth-$sLength)/2)
    $PadNum = $padamt/1 + $sLength #the divide by one is a quick dirty trick to covert string to int
    $CS = $S.PadLeft($PadNum," ").PadRight($PadNum," ") #Pad that shit
    if ($C) #if variable for color exists run below
    {    
        Write-Host $CS -ForegroundColor $C #write that shit to host with color
    }
    else #need this to prevent output twice if color is provided
    {
        $CS #write that shit without color
    }
}

Posted by Aemilianus Kehler | Permanent link

2017-04-17 17:41:11

PWM Installation on Debian 16.04 Server and tomcat8

My place of work was looking for a way to allow user to set their own passwords. Generally no easy feat when starting from scratch.

Install Ubuntu Server 16.04 LTS

Disconnect ISO and Click Continue
Let's update our package lists and download some necessary utilities first:
sudo apt-get update
sudo apt-get install unzip
Unzip was the only one not installed by default on the server edition, rock on.

Installing Tomcat8

A better tutorial of this section is available here: Installing Apache Tomcat 8 on Ubuntu 16.04.
Let's start off by installing the Java Development Kit.
sudo apt-get install default-jdk
sudo apt-get install tomcat8

Alright, we are ready to start our Tomcat service
sudo service tomcat8 start
sudo service tomcat8 status

Status

sudo systemctl enable tomcat8

This tell this the system to start tomcat at boot.

Assuming your Ubuntu server allows port 8080 inbound, you should be able to access the Tomcat welcome page in your web browser:
http://your_server_IP_address:8080

Web
Alright! That's one step down!

Installing Apache

"You might be wondering why you need both Apache2 and Tomcat8. By default, Tomcat listens on alternate ports (8080 and 8443) and was not designed to run natively on privileged ports like 80 and 443. Instead, we will be using Apache2 to proxy a secure connection between the client and Tomcat. Additionally, we will configure Apache2 to redirect all unencrypted HTTP requests to HTTPS."
While this is technically not wrong, it's not the real reason for having both. The reason for tomcat is: The Apache Tomcat software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies."
Here's a snippet of the new config file used by the guide. I'll dissect this section a bit to provide some information feedback.

Config

At first I was confused as the file under the apache config folder didn't exist. I had talked around IRC for a bit and attempted to figure out why that was the case. After double checking the guide, you can see at the bottom he tells apache to use this new config file instead of the default one. To simply test how this works, I decided to tweak the virtual directory for now to simply redirect port 80 requests back to itself using its own hostname on port 8080, just to see if they 80 -> 8080 would work as I had anticipated it to.

 -listen on all IPs on this system for port 80 traffic
	#redirect to tomcat -a commentin the config file
	Redirect Permanent / http://pwm:8080 - The redirect rule to make sure any basic http traffic is redirected to the tomcat service
 -Closing line
As you can see I commented out all the SSL redirects, as I don't have the certificates ready just yet. However it will be easy to change once all those requirements are met.
Then

Sudo a2dissite 000-default
Sudo a2ensite tomcat
Sudo service apache2 reload

This basically tell apache to use our new config file.

Then
In a browser type in the hostname for http, this time you should get the tomcat page simply by navigating just to the hostname of your server, or whatever A records your have in DNS for this server.
Success the redirection worked as expected. Now it's time to backup this server as is! Better to be safe than sorry.

Installing MySQL

Well I'm assuming we will probably need to use such a feature, even if we don't it be nice to know the system is prepared to handle them if we do need to use them. So here goes.

sudo apt-get install mysql-server
sudo mysql_secure_installation

During the MySQL installation it asked to set a root password for MySQL.
MySQLRootPassword
This password can be changed once placed into production.
Once done login to my SQL and create the PWM database and user account.

Sudo mysql -user=root -password (SQL Password)
CREATE USER 'pwm'@'localhost' IDENTIFIED BY NEW_PWM_DB_PASSWORD;
CREATE DATABASE pwm;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP on pwm.* TO 'pwm'@'localhost';
FLUSH PRIVILEGES;

When creating the pwm user account password was set to: PWMMySQLUserPassword
If you messed something up here no worries!

Resetting SQL User password and permissions

GRANT USAGE ON pwm.* TO 'pwm'@'localhost' IDENTIFIED BY NEW_PASSWORD;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX on pwm.* TO 'pwm'@'localhost';
FLUSH PRIVILEGES;

As Noted the guide forgot to grant the INDEX permission, the PWM Web config will fail at testing database connection without it.

Installing PWM

*NOTE* DO NOT USE ANY OF THE FEB 09-2017 BUILDS as they are broken.
Config

Here's the catch since we installed tomcat from the Ubuntu repo, and not from an RPM file (the more proper way to do it) the location of the tomcat files is different than that provided in the guide. This if you attempt to complete the rm command you'll find the directory is not autocompleting because frankly it does not exist.

So where does it exist now? Good question, let's use the find command to find out. :P Pun intended.

Config
Ahhh there's that bugger! Soo.

Config

Config

Well he says that's it for PWM let's see if that's correct!

Config
Would ya look at that! Just look at it! Of course just note this is internal as of now.

I did a staging thing here, and did come across an issue with Apache redirect redirecting to the old server IP instead of going to tomcat. Double check your Apache rules and make sure they are proper.
I cut out most of my staging stuff (moving to a DMZ zone) as it's beyond the scope of this tutorial.
I did split DNS for my records, so was easy for me to navigate traffic internally vs externally. Again this will come down to your own knowledge of your own networks.

I had come across an asymmetric routing issue in my network, ensure you know you network paths to prevent this.

The final part now is going to be determining exactly what connections the PWM is going to need to do ldap password resets on. Which from quick review of the firewall via its full open rule all it may need is LDAPS. (Port 636 TCP)

Configuring PWM

PWM Guide
I noticed these command didn't give the results I expected, a little bit of research and I discovered the proper command to use. I ran the command to grant permissions on the User Accounts OU to the ORBIT/PWM account.
dsacls "ou=UsersNeedingPasswordChanges,dc=domain,dc=com" /I:S /G "DOMAIN\PWM:CA;Reset Password;user"
At the Next screen it requested a connection to the LDAP server, the default setting was set for 636, the port standards defines as LDAPS.

Configure and setup LDAPS; If you have LDAPS configured; good, if not make sure you have a Enterprise CA, or some sort of CA certificate valid for LDAPS use. Lots of info about how to do this online. This is beyond the scope of this guide.

Got LDAPs? Yes? Good, good, moving on.

The guide I was following mentioned importing the cert into the java store. I stuck with this option for the time being (for testing).

Remember just setting up localDB, until we can get into the main config and change it to start using the "remote" database *cough* localhost, this will temp use a DB instance provided natively.
When entering the LDAP Proxy Credentials, this is the one you granted password reset rights to earlier. And when entering the LDAP Login Root Context that was the OU specified as the first object in the dsacls command specified above.

When enrtering the test user account, I get a local DB issue.
Anyway, Clear the field and continue the wizard. (This at least means the permissions applied to the proxy user has enough rights to change users passwords.)

Config Password: ConfigPassword
This is for testing only, in production run set and store password securley.

Save config and let the tomcat application restart.

Not sure why the Application URL is blank \_(`>`)_/
You'll finally be greeted with the following login page!

Got into main config area, configured DB settings, with config set to localDB (LocalDB is separate from the MySQL instance installed in this guide and is some native DB provided by PWM and resides within the tomcat libraries.)

Thanks to terrible documentation, I forgot to add the java mysql drivers.

sudo apt-get install libmysql-java
sudo cp /usr/share/java/mysql-connector-java-5.1.38.jar /varlib/tomcat8/webapps/ROOT/WEB-INF/lib/

Copy driver to tomcat libraries directory.

may need to reboot, or restart services after this.
Logging in with account that resides within the admin group specified during initial configuration.

Since we used the localDB that already exists within tomcat lib, it asks us to set the security questions for this account. After answering the question the page kind of froze, so I re-entered the default URL and was logged in.

Now to config, click the down arrow next to the username on the upper right of the page, and select configuration editor, and enter the config password. Let's attempt to connect to the MySQL instance that's local to the server now that we've installed the missing java-mysql drivers.

Settings -> Database (Remote) -> Connection
Database Class:
com.mysql.jdbc.Driver

Database Connection String:
jdbc:mysql://localhost:3306/pwm

Database Username:
pwm

Database Password:
(enter PWM database password)

Database Vendor:
Other

Once that's done, don't forget to change the primary setting from LocalDB to Remote. Check out the services section of the administration page to view the status.

Final Staging

Now that we were able to successfully install and test PWM in our test environment. It's time to complete everything in production and then finish the final steps, this includes making the PWM webpage accessible from the interwebs. First thing we are going to need to do is protect the page with SSL, so we can feel safe when user are entering their passwords, and secret questions that they simply can't be intercepted by a communication network middle man.

SSL Certificate

This requires generating a CSR and having your public CA provider sign it. E.G. using Digicert with a wildcard cert.

Log into PWM, and run the following command to generate a private key and certificate request:
sudo openssl req -new -newkey rsa:2048 -nodes -keyout serverPrivKey.pem -out server.csr
Then on the Digicert website click on the existing order, then scroll down and click the "Get a Duplicate" button.

Enter the CSR info from the request file we just created on PWM. Then scroll down and process the request. It will state the cert will be available in a few minutes, be patient and refresh the page, scroll down and the duplicate certificate should be available for download.

Once the files have been downloaded extract them from the zip and copy them to the PWM server using SCP program.
"A typical Apache installation will involve configuration lines
like these in your  block:

SSLCertificateFile /your/path/to/star_your_domain.crt
SSLCertificateKeyFile /your/path/to/star_your_domain.key
SSLCertificateChainFile /your/path/to/DigiCertCA.crt"

Sooo

sudo cp serverPrivKey.pem /etc/apache2/ssl/
sudo cp ./certs/DigiCertCA.crt /etc/apache2/ssl/
sudo cp ./certs/your_wildcard_cert.crt /etc/apache2/ssl


Fun reading.

Now time to manage the Apache config file. So here's the apache virtual hosts, the basic idea is if you access the site via an internal record, it'll redirect to the internal record on https, which will redirect to the tomcat page, then the other virtual host records are the same but for the public domain records.

Apache Configuration File
vim /etc/apache2/sites-available/tomcat.conf I came across another issue after making these changes.
No protocol handler was valid for the URL /. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.

FIX: sudo a2enmod proxy_http

After all this, I completed the config setup as posted above, but for production under the proper proxy redirect rules under the apache config, and using our wildcard, digicert certificate.

Next part of the staging is to create a NAT and Security rule to allow external users to access the password changing website.

This comes down to your own network knowledge again.

Once you figure out your NAT and security rules, your PWM page should be live.

 To Paraphrase to solution:
	1) PWM is a pain to setup.
	2) Lots of reading of poor documentation.
	3) My own doucmentation sucks cause it was hacked togeterh while attmpeting to learn and deploy this project.
	4) Google any errors along the way.
	5) PWM could still use a fair amount of work as password policies can be bypassed via the reset account and the forgotten password functionality as the reset account is not limited to the password polcies.


Posted by Aemilianus Kehler | Permanent link

2017-02-06 22:29:50

ESXi 6.0 on Windows 10 Hyper-V

You might ask why, I recently completed the VMware training module for installation and management of VMware vSphere components, to start to play around I don't exactly have a bunch of hardware kicking around. I do however, have my awesome gamming Rig which is massively over powered in terms of CPU, Memory however... err not so much, and disk I/O... also meh, these will need to be expanded on, but I do at least have Windows 10 running on SSD and a 3 TB spindle disc for more regular storage needs, but everyone knows a 7200 RPM disk provides mediocre performance.
Anyway I'm choosing Hyper-v Since I already have windows, and it comes free with windows, there are other options such as Oracles Virtual Box, and VMware player (can only run one VM at a time though for the free version :S)

Besides that here's the steps so far.

1) Activate your Windows 10 Pro (1607), as mentioned installed mine on a 120 GB SSD.

2) Ensure VT-x and VT-e and probably VT-d is enabled, and that you have a motherboard and CPU capable of doing virtualization.

3) make sure all your hardware drivers are up-to-date.

4) Install Hyper-v.

5) Configure server settings such as HDD location, CPU allocation, and networks. In my case, I want my ESXi hosts to be isolated from the internet, so I pick internal.

6) Grab the ESXi ISO installation media from VMware (login and subscription required).

7) Create VM, I had to pick Gen 1 with BIOS, Gen 2 with EUFI didn't boot the ISO for me.

8) I noticed at first attempt at the ESXi VM, it was sitting at loading kernel for an awfully long time, sure enough a simple Google search and discovered this gem.

When ESXi installer runs hit tab; add ignoreHeadless=TRUE

9) Before I could go any further I came across the dreaded, there are no network adapters available. You can Google this, but you will probably get blog posts about people attempting to load the nested VM with only 2 GB of ram when ESXi minimum requires 4 GB of RAM, so you have to be very specific in your search. In this case it's amazing the power of the open community these days:
Turns out (as usual) it’s a driver related issue (don't worry I'll talk about this a couple times throughout this guide).
Lucky enough some lad was genius enough to figure out a solution, not only that but also provide the direct VIB to inject into the ISO file.
I followed the instructions, discovering that the latest supported release was for 5.x including 5.5 for ESXi installation customizer.
A double whammy it didn't run on my Windows 10 x64 box... dismay not, we're playing with VMs here.
I quickly created another VM and install my old Windows XP ISO with custom Dark Vista theme imbedded.
The great part was getting the files into the VM was a breeze. Simply shutdown the VM, navigate to the VMs HDD folder, Right click the VHDX file, and select the mount context menu.
This mounts the system and C:\ as separate disks on my windows host, copied the files in, booted the VM, and followed the instructions using the provided VIB and the ESXi 6.0 installer from VMware (login required). Bam sure enough I got a new custom ESXi 6.0 installer ISO file. Moved it out in the same fashion. Mounted it as the ESXi VM's disc, and booted it up!
Finally the installation moves on! (Make sure you choose a "Legacy Network adapter")
*Note I do not discuss storage choice when setting up this test host, I simply chose to create a VHDX file of 1 TB for the Nested VMs and for ESXi to be installed on.

10) Once the installation completes, and reboots make sure to hit SHIFT + O and add "ignoreHeadless=TRUE". Let ESXi boot in DCUI

11) At DCUI, navigate to "Troubleshooting Options", Then "Enable Shell"

12) Press ALT + F1 (Not F2 as the source states, F2 is the DCUI, F1 is the console). Then Login with root.

13) Type in this command and you won't have type the headless part of the boot.
"esxcfg-advcfg --set-kernel "TRUE" ignoreHeadless"
(Copy command then select the Menu item "Clipboard", then "Type Clipboard Text") (classic Ctrl + V works too)

14) I was finally able to manage set an IP address for managing the host, the virtualized ESXi host hahaha. Sadly the vSphere client failed to connect on my XP VM.
So I setup a Windows 7 x64 bit VM instead. I set this up on Hyper-V on my Windows ten machine, alongside my ESXi hosts to mimic having a laptop running Windows 7.
The vSphere phat client can be downloaded from VMware (login required). Creating my first test VM on my nested ESXi host seemed to have an issue, reading further in the communities shows others with the exact same issue.

Turns out one can simply add a line to the VM's VMX file "vmx.allowNested = TRUE". This can be done via SSH (if enabled) or direct console (ALT+F1) using vi.

15) Another thing I noticed was when I was using the Hyper-V Manager's console to manage my Windows VM running vSphere, and then having it open up vSphere's console that the Hyper-v console would hang.
My only option at this point was to change my Windows 7 mgmt VM's network setup. Instead of it only being in the locked down management network, I added another NIC to the VM after creating an external vSwitch in Hyper-V.
Since I have a DHCP server in my local LAN, having the Windows 7 NIC setup to DHCP provided it from my DHCP pool. Using ipconfig (in VM) or checking my DHCP server’s pool I was able to find the IP to remote into.
This of course required setting up remote desktop permissions on the Windows 7 VM. This also allowed me to work in full screen mode, and didn't crash when opening up vSphere consoles, including of course copy and paste abilities. :D.

16) Next sort of problem was kind of expected. No x64 VM's in my Nested enviro. There’s topics on this. So I decided to grab the latest 32 bit version of windows that’s available... you guessed it; Server 2008 (Not R2).
Grabbing a couple different versions available from MSDN, gave me a tad bit of issues. First off, don't use the Checked/Debug, I played with the standard and the SP2 versions. I found the issue was it was hanging at completing installation.
Checking the VM stats via vSphere phat client VM's performance tab, showed MAX CPU (not always a sign of being hung as it could still just be processing, but definitely a sign on the less), then the big give away, Disk I/O and consumed memory.
Disk I/O was none, and the consumed memory was on a steady decline till it plateaued neared nothing, all signed of stuck or looped process. Since I felt like giving it a little benefit of the doubt, and I had two virtual ESXi hosts to play with,
I decided to bump the CPU on one from 2 to 4. This allowed me to create a VM with 4 virtual CPUs instead of 2. Not sure why this would make a diff, and not sure if it exactly was. So I mounted the same 2008 with SP2 ISO and load the full desktop standard.
This time it finally got into the desktop... guess I'll try the Standard core now on my other host after upping the CPU as well... let's see. Yay Server Core installed using the standard 2008 32bit ISO with 4 core CPU.

17) Next issue I came across was not being able to have the VM's inside the nested ESXi servers communicate with any other device in the same flat layer 2 network. I was sure I had configured everything correctly.
If one Googles this they will find lots n lots of articles on it stating the importance of promiscuous mode. I was up super late trying to figure out this problem and was starting to get a bit crazy. Setting all forms of the settings I could possibly find.
Including attempting to set mirror ports on the ESXi's VM NICs on Hyper-v hahaha. AS I mentioned you'll find many references to it, but googling promiscuous mode hyper-v and you discover most people stating to add a line to the VM's XML config file.
Well it probably won't take you long before you discover you VM config location doesn't contain XML files but rather vmcx files. Yeeeeapppp, good luck opening them up... they are now binary.... Wooooo! No admins playing around in here! Take that you tweakers!
This was a change in Hyper-V starting with Server 2016 / Windows 10. I spent a couple hours tumbling down this rabbit hole. To help other I'll make this part as clear as mud!
IN Hyper-V, ON THE ESXi VMs NETWORK SETTING THAT IS THE LEGACY NETOWRK ADAPTER (the one used as the "physical" adapter in the ESXi vSwitch) EXPAND THE SETTING AND UNDER ADVANCED FEATURES SELECT "Enable MAC address spoofing".
That's it! That is Server 2016/Windows 10 Hyper-V's work around for nested hypervisors. Although as usual support people on TechNet instead of giving an answer or a technical work around would rather dust their hands the classical "not supported" instead of "It's possible, here's how, but if something doesn't work with these settings that's all we can help with" which I feel would have been a far better response. Maybe these support people just aren't aware, who knows here's where I found my answer.

18) So now that I got my hosted ESXi servers up and running and communicating the next step is vCenter. vCenter will setup its own SSO domain, we can add a MS AD domain later and change the default SSO domain to be our active direct domain. However the default SSO domain created at vCenter deployment is the local configuration domain for all vCenter services. Grab vCenter Appliance from VMware. You might be wondering what gives when you discover under the download list for vCenter that there’s an ISO and an IMG file, but no OVA/OVF. This is cause in vSphere 6.0 the vCenter appliance is deployed via a client system using some weird system to communicate to the host to deploy via some web stuff… even I don’t know the exact details of what’s up, either way, if you attempt to create an VM and mount the ISO, you’ll find it’s not bootable. So mount it to the management VM. In my case my Windows 7 VM with vSphere installed. Since Windows 7 doesn’t have native ISO mounting features I had to install virtual clone drive. Then mount the ISO and navigate inside.

Oddly enough it almost seems as if you need a windows system to deploy a Linux appliance. Under the VCSA folder you should find an integration plugin exe installable… run the installable exe file. There seems to be a set that states installing certificates and service, this might be the start of the certs of the built in SSO domain. Not sure though. Once it’s done it sort of leaves you in the dark… as every just closes and there’s not complete window in the wizard…
Guess I’ll just run vsa-setup.html now… Since I have a native version of Windows 7 setup… looks like I’ll need IE 10/11 as the default IE 8 won’t suffice. Lucky for me the Windows 7 machine still had access to the internet, so I Googled the IE 11 installer and ran it, this may be a pre-requirement for the normal installer. As it seems to download and install required updates. You may need to find an offline installer file for IE 11 if you are in a test enviro where you Windows machine doesn’t have access to the internet.

Click Allow. Another pop-up will appear, click Allow.

Now we can finally click install: S

Accept the user agreement, then enter one of the hosts IP address. Member I installed and run this one the Windows 7 machine that can already access the hosts via SSH or the vSphere phat client. So I will enter the IP address here as I haven’t setup DNS at all yet in my environment, and one wouldn’t technically yet if the plan was to have nested DNS servers (The DNS the hosts point to are VMs it hosts).

I made a wrong IP entry, it alerted me as it couldn’t connect to the host, then corrected the IP, and got a cert warning.

Setup the Virtual Appliance OS’s Root password (I believe it uses openSUSE, so this would set the underlying openSUSE root password).

Now under the deployment type if one were never to connect any other vCenter server into the SSO domain for enhanced link mode, you can pick embedded, however for scalability, and the fact I need to setup a Windows Server vCenter to run Update Manger, I’ll create an external Platform Services Controller (PSE). This will require me to run through the wizard separately to actually deploy the vCenter server, in this case I’m actually just setting up the PSE Virtual Appliance (VA). Hence the options all make sense.

As I mentioned this will create the SSO domain for all vCenter services, do not make this the same as your AD domain, this will cause confusion between domains when you add and set your AD domain as the primary SSO identity source. I stick with VMware default vsphere.local, then add a site name (generally this would be some sort of regional reference). Also set the SSO admin password.

It complained about DNS a requirement and a System name, I’m assuming this is hostname, even though it requested it be either FQDN or IP like it was required for some sort of looked, I specified simply the hostname, and a DNS server IP that is not yet even setup for DNS (That which will be my PDC in my test AD setup) This allowed me to continue the setup. I’m thinking this might be what it enters as a common name or SAN for its cert. is my guess.
I went back and changed it to an IP address as I figured my first couple attempts to access it will be through its IP address and I didn’t want to deal with cert warnings. It did however warn me that FQDN is more preferred and this makes sense when a proper DNS system is already implemented.
Hahaha Sure enough had to go through all that IE 11 setup, and plugin installation for it simply to deploy an OVF file hahaha.

Cool, I guess it’s more that based on how you want to set vCenter up with the new PSE instead of having a bunch of Documentation to read through (While this is technically always best to do anyway) it sort of automates the templates to deploy and how to configure them using a questionnaire type setup. I believe in 6.5 this is maybe easier with some sort of HTML 5 based deployment system. Not sure though.
So I hit a couple snags on deployment. First off I thought I was stuck on not being able to do nest x64 virtualization on my nested ESXi hosts. Until the great lads in Freenodes #vmware told me to enable virtualization extensions to the ESXi VM.
“17:18 < genec> Zew: then did you forget to pass VT-x to the ESXi VM?” – Oh Neat! Thanks genec.
Since I was running all my stuff on Hyper-V I had to Google this. Did take long till I found my answer.
Set-VMProcessor -VMName -ExposeVirtualizationExtensions $true
The VM name being my ESXi hypervisor.

This however I only discovered after I enabled the whole vmx.allowNested = TRUE bit on the deployed VM after I saw that it failed with that usual error message. Luckily enough a bit of googling again and I was able to find my answer.
“You can add vmx.allowNested = "TRUE" to /etc/vmware/config in the ESXi VM to avoid having to put it in every nested VM's configuration file.” –Thanks Matt
I’ll delete the existing vApp and try my deployment again.
Once I managed to mount the VSCA ISO and install the client plugin, and attempt to deploy the PSC/VCSA I got hung up. It appears all my x64 VMs within my Nested ESXi hosts failed to properly boot. All the different VCSA\PSC versions all went into a boot loop. Windows 7 x64 gave a fault screen after loading the installer files and attempting to boot the setup.exe. Server 2016 just showed a black screen. Looking into this I discovered this guy’s blog… looks like I may have to resort to VMware Workstation Pro!
I’ll post this blog post for now as it has become rather long. I will post my success or failure in the upcoming weeks. Stay tuned!


Posted by Aemilianus Kehler | Permanent link

2017-01-31 15:24:54

Deleting Windows.old from New Windows 10 install

So I recently re-installed my Windows OS on my desktop. Glad to say the expeirence is generaly a really good one; most driver install automagically.
I even let it grab the latest updates, as you might expect this includes the Windows 10 1607 version update; aka the anniversary edision.
to my dismay I noticed a Windows.old folder under my C:\ the drive I selected to install windows on. Being a fresh install I was a bit surprised to see this. as it's usually from a complete Windows upgrade. I guess the 1607 version is a complete new version according to MS?

A quick google search however provided a nice blog by of course my fav HowToGeek .

Sadly even after this, I still had a Windows.old folder. :(


I couldn't figure out why, so I decided to navigate into the folder. I discovered it was a particular file InstAud.sys or something of that nature. I opened up the properties of it and seized ownership of the file, I am the administrator after all.
To my dismay again, I still couldn't add or remove permissions. I managed to use takeown and cacls to add permissions, but then it stated was locked by a process. Using sysinternals handle and procexp both came up empty handed for any locks.. odd :S.
autoruns also didn't show anything linked to that file... mmm. Even after, disabling my intl video (I was using a gefore PCI-e video card anyway), disabled it in device manager. and uninstalled the software/drivers. Made sure the service was gone. Yet it pertained I coudn't delete the file.
So, normally I'd use a linux live USB to mount the partition and wipe it out that way. However I wanted to keep it all Windows and attempt to do this without pointing user to any other site or tools.
And yes.... I did figure it out! hahah. Follow these steps.

	Step 1) Click the Action Center Icon (or swipe from the right side on a tablet) and select All Settings -> Update and Security -> Recovery -> (Under Advanced Startup) Restart Now.
	Step 2) Select Troubleshoot -> Cmd prompt.
	Step 3) Change to the windows disk drive, generally C:
Now if you attempt to navigate directly to the file you might find the commands you set to provide you account permissions might not have been persistent.
You might also be surprised to find there is no cacls command. well fear not, you'll just have to use icacls instead.
	Step 4) Take Ownership:
	Step 5) Grant Permissions:
	Step 5) Navigate into the folders, till you find the issue file, use del to delete, use takeown and icacls to take ownership and permissions.
	Step 6) Once thats done use rmdir /S /Q to delete C:\Windows.old

That's it! your done, reboot. And See Windows.old is gone! That was tougher than it shoulda been. Now I can re-enable, and re-install my integrated Intel drivers, I'm not sure exactly what happened, it was an update that ran right after installing Windows. I did however use a dedicated Windows 10 USB stick that's 6 months old or so. Just show how important to get the latest builds whenever possible.


Posted by Aemilianus Kehler | Permanent link