initial commit
This commit is contained in:
commit
87f047f909
54 changed files with 1113120 additions and 0 deletions
243
Measure-R125Direct.ps1
Executable file
243
Measure-R125Direct.ps1
Executable file
|
|
@ -0,0 +1,243 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
Misst Hotspots INNERHALB der ProcessADObjects-Funktion (Process-ADObjects-Work-<Institut>.ps1)
|
||||
zeilenweise mit PSProfiler.
|
||||
|
||||
.DESCRIPTION
|
||||
Problemstellung:
|
||||
Measure-Script instrumentiert nur die UEBERGEBENE Datei, nicht die zur Laufzeit
|
||||
dot-gesourcten. Misst man das Rahmenskript, erscheint die gesamte ProcessADObjects-
|
||||
Zeit nur als eine Zeile (der Aufruf), ohne Aufschluesselung innerhalb R125.
|
||||
|
||||
Loesung:
|
||||
1. Das ECHTE Rahmenskript wird mit ProcessDAW=$false ausgefuehrt. Dadurch laufen
|
||||
alle Imports und prepareADObjectsByType-Aufrufe (voller Scope: $ADObjects*,
|
||||
$FI, alle Pfad-Variablen, alle Funktionen), aber der try-Block mit den
|
||||
ProcessADObjects-Aufrufen wird uebersprungen. Wir "dot-sourcen" das Rahmenskript,
|
||||
damit sein kompletter Scope in DIESER Session erhalten bleibt.
|
||||
2. Von der Instituts-Work-Datei (R125) wird eine temporaere Kopie erzeugt, an deren
|
||||
Ende die eigentlichen ProcessADObjects-Aufrufe angehaengt werden.
|
||||
3. Diese temporaere Kopie wird an Measure-Script uebergeben. Da die Ausfuehrung der
|
||||
Funktion jetzt INNERHALB der gemessenen Datei stattfindet, wird der Funktions-
|
||||
koerper zeilenweise instrumentiert. Der geteilte Scope aus Schritt 1 liefert die
|
||||
noetigen Variablen.
|
||||
|
||||
Hinweis zu den Zeilennummern: Die temporaere Kopie ist bis zum Original-Ende
|
||||
zeilengleich mit R125. Die angehaengten Aufrufe stehen DAHINTER, stoeren die
|
||||
Zuordnung der Funktionszeilen also nicht.
|
||||
|
||||
.PARAMETER Sparkasse
|
||||
Institut. Default R125.
|
||||
|
||||
.PARAMETER ScriptRoot
|
||||
Verzeichnis der Skripte. Default: aktuelles Verzeichnis.
|
||||
|
||||
.PARAMETER Types
|
||||
Welche ADObject-Typen gemessen werden. Default nur die teuersten (Organisation, Role).
|
||||
Moeglich: Organisation, AppAccess, FilesystemAccess, AppConfiguration, Security, Role.
|
||||
|
||||
.PARAMETER OutputDir
|
||||
Zielverzeichnis fuer die Ergebnis-XML. Default: Verzeichnis dieses Skripts.
|
||||
|
||||
.EXAMPLE
|
||||
./Measure-R125Direct.ps1 -Sparkasse R125 -ScriptRoot /Users/edmond/Develop/PowerShell/sparkurs -Types Organisation
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Sparkasse = "R125",
|
||||
[string]$ScriptRoot = (Get-Location).Path,
|
||||
[ValidateSet('Organisation','AppAccess','FilesystemAccess','AppConfiguration','Security','Role')]
|
||||
[string[]]$Types = @('Organisation','Role'),
|
||||
[string]$OutputDir = $PSScriptRoot + "/Data/" + $Sparkasse + "/Log"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if (-not (Get-Command Measure-Script -ErrorAction SilentlyContinue)) {
|
||||
throw "PSProfiler (Measure-Script) nicht verfuegbar. Bitte 'Import-Module PSProfiler'."
|
||||
}
|
||||
|
||||
$ScriptRoot = (Resolve-Path $ScriptRoot).Path
|
||||
$mainScript = Join-Path $ScriptRoot "Process-ADObjects.ps1"
|
||||
$workScript = Join-Path $ScriptRoot ("Process-ADObjects-Work-{0}.ps1" -f $Sparkasse)
|
||||
foreach ($p in @($mainScript, $workScript)) {
|
||||
if (-not (Test-Path $p)) { throw "Nicht gefunden: $p" }
|
||||
}
|
||||
if (-not (Test-Path $OutputDir)) { New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null }
|
||||
|
||||
# Mapping Typ -> ($ADObjects*-Variablenname, $FI.TypeTag*-Property)
|
||||
$typeMap = @{
|
||||
Organisation = @{ Var = 'ADObjectsOrganisation'; Tag = 'TypeTagOrganisation' }
|
||||
AppAccess = @{ Var = 'ADObjectsAppAccess'; Tag = 'TypeTagAppAccess' }
|
||||
FilesystemAccess = @{ Var = 'ADObjectsFilesystemAccess'; Tag = 'TypeTagFilesystemAccess' }
|
||||
AppConfiguration = @{ Var = 'ADObjectsAppConfiguration'; Tag = 'TypeTagAppConfiguration' }
|
||||
Security = @{ Var = 'ADObjectsSecurity'; Tag = 'TypeTagSecurity' }
|
||||
Role = @{ Var = 'ADObjectsRole'; Tag = 'TypeTagRole' }
|
||||
}
|
||||
|
||||
# --- Temporaeres Local-Override: vollen Vorlauf, aber ProcessDAW=$false -----
|
||||
$localOverridePath = Join-Path $ScriptRoot "Process-ADObjects-Configuration-Local.ps1"
|
||||
$createdOverride = $false
|
||||
if (Test-Path $localOverridePath) {
|
||||
Write-Host "HINWEIS: Vorhandenes Configuration-Local-Override wird NICHT angetastet." -ForegroundColor Yellow
|
||||
Write-Host " Sicherstellen: DefaultInstitute=$Sparkasse, ProcessDAW=`$false, Verbose=`$false, Analyze=`$false." -ForegroundColor Yellow
|
||||
}
|
||||
else {
|
||||
$ov = @"
|
||||
# === AUTO-GENERATED by Measure-R125Direct.ps1 - wird automatisch geloescht ===
|
||||
# Voller Import/Prepare-Vorlauf, aber KEINE ProcessADObjects-Aufrufe im Rahmen
|
||||
# (die uebernimmt der Mess-Treiber selbst auf der temporaeren R125-Kopie).
|
||||
`$Config.DefaultInstitute = "$Sparkasse"
|
||||
`$Config.ProcessDAW = `$false
|
||||
`$Config.WriteKURS = `$false
|
||||
`$Config.TransferDAW = `$false
|
||||
`$Config.PostProcess = `$false
|
||||
`$Config.Analyze = `$false
|
||||
`$Config.Verbose = `$false
|
||||
`$Config.TestMode = 0
|
||||
"@
|
||||
Set-Content -Path $localOverridePath -Value $ov -Encoding UTF8
|
||||
$createdOverride = $true
|
||||
Write-Host "Temporaeres Configuration-Local-Override angelegt (ProcessDAW=false)." -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
$tmpWork = $null
|
||||
try {
|
||||
Push-Location $ScriptRoot
|
||||
try {
|
||||
# --- Schritt 1: Rahmenskript dot-sourcen -> voller Scope in dieser Session
|
||||
# ProcessDAW=$false ueberspringt den try-Block; Import + prepare laufen komplett.
|
||||
Write-Host "Baue vollen Scope auf (dot-source Rahmenskript, ProcessDAW=false) ..." -ForegroundColor Cyan
|
||||
|
||||
# Variablen, die VOR dem Dot-Sourcing schon existieren, merken - alles, was
|
||||
# danach NEU hinzukommt, stammt aus dem Rahmenskript und muss gespiegelt werden.
|
||||
$before = @{}
|
||||
Get-Variable -Scope Local | ForEach-Object { $before[$_.Name] = $true }
|
||||
|
||||
. $mainScript
|
||||
|
||||
# --- Scope-Bruecke: Measure-Script fuehrt die Zieldatei in einem EIGENEN
|
||||
# Scope aus, in dem die hier per Dot-Sourcing aufgebauten lokalen Variablen
|
||||
# NICHT sichtbar sind. Loesung: alle vom Rahmenskript erzeugten Variablen
|
||||
# ins GLOBALE Scope spiegeln - global ist auch aus dem Measure-Lauf sichtbar.
|
||||
# PowerShell-Automatic-Variablen und die treibereigenen werden ausgelassen.
|
||||
$automatic = @(
|
||||
'args','input','PSBoundParameters','MyInvocation','PSCmdlet','PSItem','_',
|
||||
'?','^','$','null','true','false','PSScriptRoot','PSCommandPath','this',
|
||||
'before','automatic','t','vn','val','cnt','mainScript','workScript','tmpWork',
|
||||
'typeMap','Types','Sparkasse','ScriptRoot','OutputDir','localOverridePath',
|
||||
'createdOverride','ov','result','callLines','tag','timestamp','xmlPath','v',
|
||||
'mirrored','ErrorActionPreference','ExecutionContext','HOME','PID','PWD','ShellId'
|
||||
)
|
||||
$mirrored = 0
|
||||
foreach ($v in (Get-Variable -Scope Local)) {
|
||||
if ($before.ContainsKey($v.Name)) { continue }
|
||||
if ($automatic -contains $v.Name) { continue }
|
||||
if ([string]::IsNullOrEmpty($v.Name)) { continue }
|
||||
Set-Variable -Name $v.Name -Value $v.Value -Scope Global -Force -ErrorAction SilentlyContinue
|
||||
$mirrored++
|
||||
}
|
||||
Write-Host (" {0} Rahmen-Variablen ins globale Scope gespiegelt." -f $mirrored) -ForegroundColor DarkGray
|
||||
|
||||
# Sanity-Check: sind die vorbereiteten Objekte da (jetzt global)?
|
||||
foreach ($t in $Types) {
|
||||
$vn = $typeMap[$t].Var
|
||||
$val = Get-Variable -Name $vn -ValueOnly -Scope Global -ErrorAction SilentlyContinue
|
||||
$cnt = if ($val) { @($val).Count } else { 0 }
|
||||
Write-Host (" {0,-16} = {1} Eintraege" -f $t, $cnt) -ForegroundColor DarkGray
|
||||
if ($cnt -eq 0) {
|
||||
Write-Host (" WARNUNG: {0} ist leer/null - Messung wuerde fehlschlagen." -f $vn) -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# --- Schritt 2: temporaere Mess-Datei aufbauen
|
||||
# Sie muss ALLES enthalten, was ProcessADObjects zur Laufzeit braucht:
|
||||
# a) die Hilfsfunktionen (Utility/Base/Analyze/Work) - werden hier per
|
||||
# Dot-Source geladen, da der isolierte Measure-Scope die in der
|
||||
# Treiber-Session definierten Funktionen nicht sieht.
|
||||
# b) die ProcessADObjects-Definition selbst (R125) - ebenfalls als R125
|
||||
# direkt eingebettet, damit ihre Zeilen instrumentiert werden.
|
||||
# c) die eigentlichen Aufrufe.
|
||||
# Die Variablen (FI, Config, *FilePath, ADObjects*) kommen ueber das globale
|
||||
# Scope (siehe Spiegelung oben).
|
||||
#
|
||||
# Damit die Zeilennummern der Funktion 1:1 zu R125 bleiben, wird R125 NICHT
|
||||
# kopiert-und-erweitert, sondern als eigene Datei per Dot-Source eingebunden;
|
||||
# Measure-Script instrumentiert dot-gesourcte Dateien jedoch nicht. Deshalb
|
||||
# betten wir R125 INLINE ein und haengen die Aufrufe an. Die Hilfs-Sources
|
||||
# stehen davor und verschieben die Funktionszeilen um einen festen Offset,
|
||||
# den der Analyzer nicht braucht (Code-Text steht pro Zeile dabei).
|
||||
$tmpWork = Join-Path $ScriptRoot ("Process-ADObjects-Work-{0}.measure-tmp.ps1" -f $Sparkasse)
|
||||
|
||||
$header = @"
|
||||
# === AUTO-GENERATED by Measure-R125Direct.ps1 - wird automatisch geloescht ===
|
||||
# Hilfsfunktionen laden (im isolierten Measure-Scope nicht vererbt):
|
||||
. "`$PSScriptRoot/Process-ADObjects-Utility.ps1"
|
||||
. "`$PSScriptRoot/Process-ADObjects-Base.ps1"
|
||||
. "`$PSScriptRoot/Process-ADObjects-Analyze.ps1"
|
||||
. "`$PSScriptRoot/Process-ADObjects-Work.ps1"
|
||||
# === ab hier folgt der unveraenderte Inhalt von Process-ADObjects-Work-$Sparkasse.ps1 ===
|
||||
|
||||
"@
|
||||
$r125Body = Get-Content -Path $workScript -Raw
|
||||
|
||||
$callLines = @('', '# === appended calls by Measure-R125Direct.ps1 ===')
|
||||
foreach ($t in $Types) {
|
||||
$vn = $typeMap[$t].Var
|
||||
$tag = $typeMap[$t].Tag
|
||||
# Aufruf exakt wie im Rahmenskript (try-Block, Zeile 211ff)
|
||||
$callLines += ('ProcessADObjects $global:{0} $global:FI.{1}' -f $vn, $tag)
|
||||
}
|
||||
|
||||
$fullContent = $header + $r125Body + [Environment]::NewLine + ($callLines -join [Environment]::NewLine)
|
||||
Set-Content -Path $tmpWork -Value $fullContent -Encoding UTF8
|
||||
|
||||
# Header-Zeilen zaehlen, damit der Analyzer-Output korrekt interpretiert werden
|
||||
# kann (Funktionszeile in R125 = gemessene Zeile - $headerOffset).
|
||||
$headerOffset = ($header -split "`n").Count - 1
|
||||
Write-Host (" Zeilen-Offset Header -> R125: {0} (R125-Zeile = gemessene Zeile - {0})" -f $headerOffset) -ForegroundColor DarkGray
|
||||
|
||||
# --- Schritt 3: temporaere Kopie messen (instrumentiert R125 zeilenweise)
|
||||
Write-Host ""
|
||||
Write-Host ("Messe ProcessADObjects fuer Typen: {0}" -f ($Types -join ', ')) -ForegroundColor Cyan
|
||||
$result = Measure-Script -Path $tmpWork
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
# --- Ergebnis sichern --------------------------------------------------
|
||||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
$xmlPath = Join-Path $OutputDir ("Profile-WorkScript-{0}-{1}.xml" -f $Sparkasse, $timestamp)
|
||||
$result | Export-Clixml -Path $xmlPath -Depth 6
|
||||
|
||||
# Offset als Sidecar ablegen, damit der Analyzer die gemessenen Zeilennummern
|
||||
# automatisch auf die Original-R125-Zeilen zurueckrechnen kann.
|
||||
$sidecar = [pscustomobject]@{
|
||||
SourceFile = Split-Path $workScript -Leaf
|
||||
HeaderOffset = $headerOffset
|
||||
Types = $Types
|
||||
Sparkasse = $Sparkasse
|
||||
}
|
||||
$sidecar | Export-Clixml -Path ($xmlPath -replace '\.xml$', '.meta.xml')
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Ergebnis gespeichert: $xmlPath" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Auswertung:" -ForegroundColor Cyan
|
||||
Write-Host " ./Analyze-ProfileResult.ps1 -XmlPath '$xmlPath' -Top 40" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
Write-Host ("HINWEIS: Gemessene Zeilennummern sind um {0} (Header) verschoben." -f $headerOffset) -ForegroundColor DarkGray
|
||||
Write-Host (" R125-Originalzeile = gemessene Zeile - {0}. Der Analyzer liest" -f $headerOffset) -ForegroundColor DarkGray
|
||||
Write-Host " den Offset automatisch aus der .meta.xml-Sidecar-Datei." -ForegroundColor DarkGray
|
||||
}
|
||||
finally {
|
||||
if ($tmpWork -and (Test-Path $tmpWork)) {
|
||||
Remove-Item -Path $tmpWork -ErrorAction SilentlyContinue
|
||||
Write-Host "Temporaere R125-Mess-Kopie entfernt." -ForegroundColor DarkGray
|
||||
}
|
||||
if ($createdOverride -and (Test-Path $localOverridePath)) {
|
||||
Remove-Item -Path $localOverridePath -ErrorAction SilentlyContinue
|
||||
Write-Host "Temporaeres Configuration-Local-Override entfernt." -ForegroundColor DarkGray
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue