Wednesday, February 20, 2013

XML file ilma BOM'ita powershellis


 Lihtne asi, võta xml ja muuda seal mingi väli ära ja salvesta uue nimega tagasi. Esimene asi, mille otsa kohe jooksin oli salvestamine. Varemgi ette sattunud, aga ei olnud meeles - Powershell tahab täisteekonda failinimele. Kui peale $xml.save($filename) ühtegi faili ei tekkinud, sai natuke mõeldud ja infot otsitud ning probleem lahenes sellega, et panin $filename = "$pwd\output.xml".
 Teine komistuskivi. Algne xml fail on ilma BOM baitideta, aga Powershell paneb $xml.save() tehes uuele failile BOM baidid algusesse. Jälle mõnda aega netis tuhnimist ja kuigi päris otsest näidet ei olnud Powershellile, sai mitmest kohast info kokku lapitud ja tulemuseks ilma BOM baitideta väljundifaili kätte. Lihtsustatult:

$XMLInput = "$pwd\input.xml"
$XMLOutput = "$pwd\output.xml"

$list = New-Object System.Xml.XmlDocument
$list.PreserveWhitespace = $true
$list.load($XMLInput)
...
käime xml faili läbi ja teeme vajalikud muudatused
...

# uus väljundifail
$file = New-Object System.IO.FileStream($XMLOutput, [IO.FileMode]::CreateNew)
# Teeme XmlTextWriter objekti koos UTF8 enkodeerimisega, et faili kirjutada
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
$xwriter = New-Object System.Xml.XmlTextWriter($file, $Utf8NoBomEncoding)
$list.save($xwriter)
$xwriter.Close()


Tuesday, February 19, 2013

Arvutite kustutamine SCCM 2007'st powershelliga

 Oli nimekiri arvutitest ja vajadus need SCCM 2007 serverist ära kustutada. Käsitsi üsna tüütu neid otsida ja ükshaaval kustutada. Internetist leidsin skripti, mis otsis AD'st vanu arvuteid, tõstis need teise OU'sse ning kustutas AD'st ja SCCM'ist lõpuks arvutite kontod ära. Mul oli vaja aga ainult SCCM kustutamise osa ja kirjutasin asja ümber funktsiooniks endale.


Function Remove-WorkstationsFromSCCM {
<#
.SYNOPSIS
This Cmdlet deletes specified computers from specified SCCM server
.DESCRIPTION
This Cmdlet deletes specified computers from specified SCCM server. Computer names are specified as comma separated list of names.
You can use Powershell Common Parameters, see help about_commonparameters.
To use function dot source it - . .\Remove-WorkstationsFromSCCM.ps1
If you don't want to use it anymore, delete it - del function:\Remove-WorkstationsFromSCCM
.EXAMPLE
Remove-WorkstationsFromSCCM -Computers PC1 -SCCMServer SCCMSrv
Does not actually delete computer PC1 from SCCM server named SCCMsrv. Just dry run.
.EXAMPLE
Remove-WorkstationsFromSCCM -Computers PC1 -SCCMServer SCCMSrv -Remove
Deletes computer PC1 from SCCM server named SCCMsrv
.EXAMPLE
Remove-WorkstationsFromSCCM -Computers PC1,PC2 -SCCMServer SCCMSrv -Verbose -Remove
Deletes computers PC1 and PC2 from SCCM server named SCCMsrv and prints additional information.
.EXAMPLE
Get-Content .\PCsToDeleteFromSCCM.txt | Remove-WorkstationsFromSCCM -SCCMServer SCCMSrv -Verbose -Remove
Takes names of the computers from PCsToDeleteFromSCCM.txt and pipes it to cmdlet.
.LINK
Adapted from http://trevorsullivan.net/2010/08/17/powershell-ad-sccm-workstation-cleanup-script-version-3-0/
#>

[CmdletBinding(
# don't need whatif right now
# SupportsShouldProcess = $True
)]
Param(
    # computernames to remove from SCCM
    [parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, HelpMessage = "Computername(s) to delete from SCCM server")]
        [String[]]$Computers,
    # The server on which your SMS Provider component is installed
    [parameter(Mandatory = $True, HelpMessage = "SCCM server name")]
        [String]$SCCMServer,
    # If set to $true, the script WILL REMOVE computers from SCCM! [switch] means, that with no -Remove switch the $Remove is $false
    [switch]$Remove
)

    begin {
        # Dynamically obtain SMS provider location based only on server name
        $tSiteCode = (Get-WmiObject -ComputerName $SCCMServer -Class SMS_ProviderLocation -Namespace root\sms).NamespacePath
        # Return only the last 3 characters of the NamespacePath property, which indicates the site code
        $SCCMSiteCode = $tSiteCode.SubString($tSiteCode.Length - 3).ToLower()
        Write-Verbose "Site code is: $SccmSiteCode"
        Write-Verbose "SiteServer is: $SCCMServer"
    }
    process {
        # Now we delete resources from the Configuration Manager database
        foreach ($Computer in $Computers) {
            $tSysQuery = "select * from SMS_R_System where Name = '$Computer'"
            $tWmiNs = "root\sms\site_" + $SccmSiteCode
            $Resources = Get-WmiObject -ComputerName $SCCMServer -Namespace $tWmiNs -Query $tSysQuery
            if ($Resources -ne $null) {
                Write-Verbose $tSysQuery
                Write-Verbose "tWmiNs is: $tWmiNs"
                foreach ($Resource in $Resources)
                {
                    $AgentTime = $($Resource.AgentTime | Sort-Object | Select-Object -Last 1)
                    $UserName = $Resource.LastLogonUserDomain + '' + $Resource.LastLogonUserName
                    Write-Verbose $Resource.ResourceID
                    Write-Verbose $Resource.Name
                    Write-Verbose $AgentTime
                    Write-Verbose $UserName
                    # This line deletes records from the ConfigMgr database
                    if ($Remove)
                    {
                        # Delete the resource from the ConfigMgr site server
                        "Deleting resource " + [string]$Resource.Name
                        $resource.Delete()
                    }
                }
            } else {
                "There was not $Computer in $SCCMServer server."
            }
        }
    }
    end {}
}

Monday, February 18, 2013

Networker ja bootstrap

 Andsin alla ja leppisin olukorraga mõni aeg tagasi. Bootstrap on Networkeris nii tähtis asi, et seda ei saa tegemata jätta, isegi kui Schedule ütleb, et ära varukoopiat täna tee. Paistab, et Networker on mõeldud ikka suuremate infrastruktuuride jaoks, kus on Networkeri jaoks oma eraldi server või on neid rohkem kui üks.
 Kuskil manualis oli kirjas, et kui Networkeri server on kliendina aktiivses grupis, millest varukoopiat tehaks,et siis varundatakse alati ka bootstrap, isegi kui Schedule's on kirjas varukoopia tase - Skip
 Olukorras, kus Networkeri serverit on üks ja enamus andmeid, millest varukoopiat tehakse on sama serveri küljes, osutub selline omadus üsna tüütavaks. Kui nädala jooksul tööpäeva koopia algab kell 10:00 ja nädalalõpu koopia samadest asjadest 9:50, siis on nädalavahetusel garanteeritud oukord, kus oodatakse päev otsa lindi järel, et selle nädala sees tööle mineva grupi bootstrap'i saaks lindile kirjutada. Kui vastupidi ajad panna, et päeva oma algab 10:00 ja nädalalõpu oma 10:10, siis on terve nädal iga tööpäev lindi järgi ootamist. Ja analoogselt ka teiste gruppidega, mille töötamise ajad kattuvad. Tüütus küll, aga seda saab vähendada varukoopia aegade sättimisega ja teinekord koopia tegemise asemel klooni tehes.

Tuesday, January 8, 2013


  Lihtsad asjad võtavad teinekord kohutavalt palju aega. Just siis, kui neid esimest korda teed. Veendusin selles, kui Networkeri katki tegin. Sai Networkeri teenused natuke aega tagasi pandud teise konto, mitte LocalSystem alt, tööle pandud. Ja Networkeri uuendamisega läksid kõik Networkeri andmed(kontode õigused, conf, meedia andmebaas) kaduma. Kõigepealt läks paras aeg enda administraatoriks tagasi panemiseks, mida tegelikult polnud vajagi, nagu pärast selgus.Tegevuse käigus leidsin artikli How to reset the Admin Password in NetWorker Management Console . Siis sain selgeks, et adminiks saab lihtsalt command promptis käsuga nsraddadmin -u >kasutajakonto> . Või siis kasutades nsradmin utiliiti, vaadates enne administrator ressursi järgi ja siis ennast sinna juurde lisades.

nsradmin>
nsradmin> . NSRLA
Current query set
nsradmin> show administrator
nsradmin> p
               administrator: "group=Administrators,host=localhost",
                              "group=Administrators,host=server.domeen",
                              "isroot,host=server",
                              "isroot,host=server.domeen",
                              "isroot,host=server2",
                              "isroot,host=server2.domeen";

update administrator: "username,host=server.domeen","group=Administrators,host=localhost","group=Administrators,host=server.domeen","isroot,host=server","isroot,host=server.domeen","isroot,host=server2","isroot,host=server2.domeen"


Teinekord vajalik info, aga seekord kasutu. Samas aga kiitsin ennast selle eest, et olin just hiljuti indeksite ja bootstrap'i jaoks eraldi lindi pannud, mis kogu aeg sees oli. Ei pidanud kuskilt viimast bootstrap'i otsima, vaid sai scanneriga selle lindi pealt viimase bootstrap'i kätte:
        scanner -B \\.\Tapedevice
mõni aeg ootamist ja tulemuseks sai:
        8919:scanner: Bootstrap 835022085 of 12/10/12  7:00:00 located on volume 000019L3, file 177.

Kuna tegutsesin vale konto alt ja ei teadnud algul, et Networker oli vajalikele failidele sellised õigused pannud, et nendele ainult selle kontoga ligi pääses, mille alt teenused jooksevad, siis läks paar esimest taastamiskatset aia taha, kuni taipasin failide õigused üle käia ja mmrecover utiliidi vajaliku konto alt tööle panna. mmrecover ja anndsin ette eelnevalt scanner'iga saadud bootstrap'i andmed. Natuke ootamist ning kõik oli peaaegu sama korras, nagu enne. Mõningad voluumid tuli märkida käsitsi Appendable olekusse, kuna need olid l'inud Full olekusse.
 Kõige juures oli abiks ka EMC artikkel How to perform Disaster Recovery of a NetWorker Server, mille vahepeal leidsin. Kokkuvõttes läks selle tegevuse peale peaaegu kogu tööpäev, samas saaks aga nüüd hakkama poole tunni/tunniga.