Jun 18

Ny version av SCCM Application Creator

För ett par år sen släppte jag verktyget SCCM 2012 Application Creator, som gör det enkelt att skapa en applikation i SCCM och samtidigt skicka ut den till distributionspunkter, skapa collections, deploya applikationen och allt annat lull-lull som man normalt också gör när man skapar en ny applikation.

Sen dess har det hänt mycket. Vi har fått en ny version av SCCM (Current Branch) och PowerShell-modulen för SCCM, som verktyget är beroende av, har uppdaterats många gånger. Så den gamla versionen av verktyget fungerar helt enkelt inte särskilt bra med nuvarande version av SCCM, och många har efterfrågat ett uppdaterat verktyg.

Idag är jag glad att kunna presentera SCCM Application Creator 2.0 (2012 är borta från namnet), som fungerar utmärkt med senaste versionen av SCCM och tillhörande PowerShell-modul.

Scriptet finns precis som tidigare publicerat på Technet Gallery men nu också på PowerShell Gallery. Så det lättaste sättet att ladda ned scriptet är helt enkelt att använda PowerShellGet (kräver PowerShell 5.0) genom att skriva:

eller

Verktyget är alltså byggt helt och hållet i PowerShell och har ett enkelt grafiskt gränssnitt där man fyller i all information om applikationen.

Scriptet kan göra följande:

  • Skapa en Application i SCCM
  • Skapa en folder och flytta applikationen dit
  • Skapa en MSI deployment type
  • Skapa en App-V 5 (App-V 4 stöds ej) deployment type
  • Skapa en manuell/scriptad deployment type. I det här scenariot måste en detection method manuellt läggas till i efterhand i SCCM konsolen.
  • Distribuera applikationen till en distribution point group
  • Skapa en grupp i Active Directory
  • Skapa en device- eller user collection, antingen tom eller med en membership rule baserad på Active Directory gruppen
  • Skapa en collection folder och flytta collectionen dit
  • Deploya applikationen till collectionen, antingen som Available eller Required
  • Sätta vissa andra inställningar såsom beteende på slow networks eller allow fallback source location, osv

För mer detaljer, och bl.a. om vad exakt som är nytt i den här versionen, kan ni läsa på länkarna ovan till Technet Gallery och PowerShell Gallery.

Verktyget borde vara hyfsat självförklarande, och i hjälptexten i scriptet förklarar allt man behöver veta för att komma igång. Det grafiska gränssnittet är byggt för att vara idiotsäkert så att det inte ska gå att göra fel.

Hoppas det här kan komma till glädje för någon. Ni får jättegärna ge mig feedback om ni gillar det, eller inte gillar det.

SCCMApplicationCreator2.0

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Maj 20

Inaktivitet

Det har varit en längre tids inaktivitet här på bloggen. Anledningen är kort och gott att det senaste halvåret eller så har arbetsbelastningen varit extremt hög, och det har inte funnits så mycket utrymme till annat. Med allt nytt och kul som händer i Microsofts värld så räcker dygnets timmar inte till. Det har varit flera stora Windows 10 projekt, några nya Private Cloud/Fabric-implementationer och naturligtvis som vanligt massor med installationer/uppgraderingar/utbildningar av SCCM. Hur kul som helst, men nu får det gärna börja återgå till en lite mer normal nivå, vilket det också så sakta börjar göra. Det betyder att jag äntligen har en och annan kväll eller helg över då man t.ex. kan knåpa ihop något inlägg här på bloggen, och alla andra små projekt som ligger och skaver som dåliga samveten.

Det har börjat bli ganska många som efterfrågar en uppdaterad version av mitt verktyg SCCM Application Creator, som inte har uppdaterats på evigheter nu och inte har hängt med och fungerar med SCCM Current Branch. Jag hoppas nu kunna ta tag i detta relativt snart, även om jag inte vågar lova exakt när. Men det borde inte vara så jättemycket jobb, då jag faktiskt redan skrivit om och uppdaterat verktyget från grunden åt några kunder. Så alla kodförändringar som jag vill ha med finns klara där. Dessa varianter av verktyget är dock just kundanpassade med egna knappar och fält osv för att passa just kundens processer och behov. Så jag behöver alltså bara generalisera koden och ta bort alla kundspecifika grejer, så ska det vara klart. Dock fortfarande inget som görs på en fikarast, men den största delen av arbetet är alltså klart.

Så ha lite tålamod så ska jag verkligen försöka ta mig i kragen snart. 🙂

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Jan 31

Varför nya Software Center i SCCM v1511 inte är något att ha (än)

Ingen har väl missat att efterföljaren till SCCM 2012 (R2) är här, och numera heter bara SCCM utan något årtal som versionsnummer. Microsoft har gått över till en löpande servicemodell á la Windows 10, och traditionella uppgraderingar/migreringar är (i alla fall i teorin) ett minne blott.

Den första releasen av nya SCCM har versionsnummer 1511, och en av de mest efterlängtade nyheterna var ett nytt Software Center som kan hantera applikationer som har tillgängliggjorts till användare, och alltså inte bara till datorer.

-ÄNTLIGEN, utropade hela världen. Tills vi upptäckte hur det egentligen fungerade.

Först lite historik.
När man skapar en deployment för en Application eller ett Package och väljer Available, samt riktar installationen mot en device collection, så dyker applikationen upp i användarens Software Center, och användaren kan själv välja att installera programvaran när och om han så önskar. Perfekt, vi kan alltså bygga upp vår företagsinterna ”app store” och erbjuda våra användare en drös med applikationer, utan att de behöver kontakta IT-avdelningen. Vi behöver bara lära dem att de hittar allt de behöver i Software Center.

Men så väljer vi istället att rikta våra installationer mot användare, istället för mot datorer. Vilket kan medföra en viss extra hantering och arbete, men som ändå är otroligt mycket vettigare. Det är ju trots allt människan bakom datorn som ska använda programvaran, och inte datorn själv. Detta är också vad Microsoft har slagit på stora trumman om enda sen SCCM 2012 släpptes. Allting ska vara ”user centric”, och vi ska sluta rikta saker och ting mot datorer och istället sätta användaren i centrum.

Ok så då gör vi en deployment mot en user collection istället och förväntar oss att det naturligtvis ska fungera exakt likadant, dvs att användaren öppnar sitt Software Center och hittar sin applikation där. Men icke. Som vi alla vet så måste man istället installera rollerna Application catalog webservice/website och användaren måste nu istället surfa in på en Silverlight-baserad webbsida. Det finns visserligen en minimal liten länk inne i Software Center som användaren kan klicka på och därmed så öppnas Application Catalog, men det gör knappast saken bättre.

För att göra det ännu sjukare så hanteras egentligen inte applikationen inne i Application Catalog, utan den fungerar bara som en sorts beställningsfunktion (vare sig applikationen kräver ett godkännande eller ej). Efter att användaren valt att installera en applikation så hoppar den nämligen över till Software Center, och det är därifrån man kan följa installationsförloppet, om det gick bra eller dåligt, och även avinstallera applikationen.

VARFÖR i hela världen Microsoft gjorde på detta magiskt dåliga sätt när man byggde SCCM 2012 är okänt. Men att det är korkat och förvirrande är bara förnamnet. När jag håller utbildningar i produkten så är detta ett av de svåraste områdena att förklara för eleverna.

Det vi vill ha är naturligtvis EN plats för alla applikationer, och det var just det vi trodde vi hade fått med nya Software Center i nya SCCM-versionen. Så varför är det då så värdelöst? För att det helt enkelt visade sig vara ett hafsarbete, en otroligt dålig implementation som förmodligen gjorts av en praktikant på en fikarast.

”Nya” Software Center, som har fått ett nytt utseende, exsisterar parallellt med det gamla. Du måste aktivt välja vilket du vill använda med en Client Setting-inställning. Ok, det kan vi väl leva med. Men besvikelsen blev desto större när det visade sig att Application Catalog inte på något sätt försvunnit. Den rollen finns i allra högsta grad kvar, och du måste installera den även om du inte tänker använda webbportalen. Alltså, deployments riktade mot användare hamnar fortfarande i Application Catalog. Nya Software Center är ingenting annat än ett frontend som kan visa de ikoner som alltså i själva verket ligger i Application Catalog.

Det går inte att kalla för någonting annat än en fullösning. Men ok, vi hade kunnat leva med det. Om man bara ägnat ytterligare 5 minuter åt att åtminstone göra detta frontend komplett. Men så är icke fallet.

Följande är vad man kan göra i Application Catalog:

  1. Installera applikationer som är riktade som Available mot en användare.
  2. Beställa applikationer som kräver ett godkännande.
  3. Låta användaren konfigurera User Device Affinity, alltså tala om vilken/vilka datorer han använder oftast.

Av dessa tre funktioner klarar nya Software Center endast en av tre, nämligen den första. Så fort vi konfigurerar en applikation så att den kräver ett godkännande så fungerar det inte längre, och vi måste återigen använda webbportalen. Samma gäller möjligheten att låta användaren kryssa i sina primära enheter.

Men det kanske sämsta av allt är, även den första punkten fungerar bara halvvägs. Allting är frid och fröjd så länge vår applikation alltså inte kräver ett godkännande, men det får inte heller finnas några requirements. Låt oss säga att vi har en applikation med en requirement som säger att den enbart får installeras på användarens primära enhet. Om användaren sitter på en annan dator och surfar in på Application Catalog så kommer applikationen att synas där. Försöker han då installera den kommer ett felmeddelande att visas som talar om att kraven inte uppfylls, och att installationen inte kan fortsätta. Det är inte världens bästa felmeddelande, men det är åtminstone ett meddelande.

Försöker man göra samma sak i nya Software Center istället, så syns inget felmeddelande överhuvudtaget. Applikationen börjar installera och står och snurrar i all evighet, utan att någonting händer eller uppdateras. Klickar man runt i Software Center, eller stänger och öppnar det igen, så försvinner förloppsindikatorn och man kan återigen välja att installera applikationen. För att återigen få se ett snurrande hjul i all oändlighet.

Så kort och gott, har du enbart applikationer som inte kräver godkännande och inga som helst requirements, och inte heller vill låta användaren bestämma sina primära enheter – då kan du börja använda nya Software Center. I annat fall gör du förmodligen bäst i att fortsätta använda gamla Application Catalog, annars riskerar förvirringen bli större än någonsin.

Bitter och besviken? Jajamen. Inte längre förvånad? Nej, tyvärr.
Kommer detta bli bättre? Det hoppas jag verkligen. Klagomålen har varit ganska högljudda och får ganska många röster på Uservoice. Microsoft har nu, i och med den nya modellen för uppdateringar, alla möjligheter i världen att snabbt komma med förbättringar. Och här finns, kan man nog lugnt påstå, en viss förbättringspotential.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Sep 19

Uppföljning: Datorvariabler i SCCM 2012 fungerar inte efter återställning från backup

Det här inlägget är en uppföljning från det tidigare inlägget SCCM 2012: Datorvariabler fungerar inte efter en återställning från backup. Problemet jag beskrev där var hur det blir en mismatch på versionshanteringen för en tabell i databasen då man återställer en backup som innehåller avsevärt färre objekt. Tabellen i fråga berör policies för datorvariabler, och senaste versionen av denna tabell lagras även i registret. När man återställer databasen är alltså värdet annorlunda i registret och databasen, varpå datorvariabler inte kommer fungera förrän databasen har ”kommit ikapp” det värde som står i registret.

Min frågeställning var om detta scenario kan undvikas beroende på hur man gör sin återläsning från backup. I scenariot som min kund hade råkat ut för hade man enbart läst tillbaka databasen, utan att köra setup-programmet för SCCM och välja ”Recover site”.
Jag har nu haft tid att testa igenom lite fler scenarion i min testmiljö för att studera det här lite närmare.

Testscenario och metodik

I min testmiljö skapade jag några datorobjekt och lade till variabler till dem i SCCM-konsolen. Jag höll ögonen på vad som hände i databasen med följande queries:

Dessa queries visar alla datorobjekt som fått en variabel sorterat efter ”rowversion”, det senaste globala rowversion-värdet i databasen, samt vilka datorobjekt som det genererats en policy för, och därmed alltså kommer fungera. Jag kontrollerade också ”Last Row Version”-värdet i registret, som återfinns här:
HKLM\Software\Microsoft\SMS\Components\SMS_Policy_Provicer\MEPHandler som alltså alltid ska matcha det senaste värdet i MEP_MachineExtendedProperties.

Jag provade sedan att skapa 1000 nya datorobjekt i SCCM, och även att importera in 1000 nya användare. Som väntat ökas det globala rowversion-värdet i databasen kraftigt, då alla nya objekt genererar en massa transaktioner i databasen. Jag skapade sen manuellt ytterligare ett datorobjekt och lade till en datorvariabel. Rowversion-värdet för detta datorobjekt i tabellen MEP_MachineExtendedProperties var nu minst 1000 högre än objektet innan, vilket naturligtvis är förväntat. Jag kontrollerade också att värdet sparades även i registret.

Jag testade sedan att återskapa från en backup som jag tog innan jag importerade in mina 1000 objekt. Jag testade de olika supportade varianter som finns för att återställa en SCCM-installation som finns dokumenterade på Technet. Detta gör man genom att starta setup-programmet för SCCM och välja ”Recover a site”:

SCCMSiteRecoveryWizard

Vad jag hoppades upptäcka var om det i något scenario inte blir en mismatch mellan värdet i databasen och i registret.

Resultat

Så länge SCCM finns installerat på servern finns enbart valet ”Recover the site database…” tillgängligt i wizarden. För att återställa även site servern från en befintlig backup (som måste tas med det inbyggda jobbet i SCCM) så måste man avinstallera SCCM först (alternativt ominstallera Windows).

Jag började med att enbart återställa databasen från wizarden. Jag testade både varianten med att peka ut en backup som jag gjort med det inbyggda SCCM-backupjobbet, och även att manuellt återställa databasen från SQL Management Studio och sen välja Use a site database that has been manually recovered från wizarden.

Resultatet från båda dessa metoder blev exakt detsamma. Återläsningen gick bra, SCCM fungerade fint, mina 1000 importerade objekt var borta, och alla ”rowversion”-värden i databasen ställdes tillbaka till där de var innan de 1000 objekten importerades.

Men, registret återställdes inte och problemet med mismatchen uppstår alltså i det här scenariot – oavsett om man använt SCCMs inbyggda backup eller en vanlig SQL-backup.

Jag gick sen vidare med att börja om med en ominstallerad server, köra setupen igen, och den här gången välja scenariot att återställa hela site servern från backupen.

En liten fotnot här är att jag använde mig av en databas med splittade databasfiler. Detta lyckades setup-programmet inte att återläsa, så wizarden misslyckades. Med en icke splittad databasfil går det dock bra. Jag fick därför först manuellt återställa databasen i SQL Management Studio. Det här problemet måste jag testa mer och återkomma om.

Registernyckeln HKLM\Software\Microsoft\SMS\Components\SMS_Policy_Provicer\MEPHandler finns inte när man gör en ny installation av SCCM, utan skapas första gången man skapar en ny datorvariabel. Jag hade dock förväntat mig att nyckeln skulle finnas från början efter att ha läst tillbaka backupen, men det visade sig att så var inte fallet. Det förvånade mig då man kan se att detta värde tas med i backupjobbet, det återfinns nämligen i filen SMSbkSiteRegSMS.dat som ligger i backupkatalogen. Däremot skapades nyckeln lydigt på nytt när jag lade till en ny datorvariabel, och ”last row version”-värdet pekade korrekt mot det senaste värdet i databasen.

Alltså ingen mismatch mellan registret och databasen i det här scenariot, så datorvariabler kommer fungera som de ska.

Hur registervärdet återskapas vet jag dock inte, det måste finnas någon logik som helt enkelt tittar på det senaste värdet i MEP_MachineExtendedProperties och skriver in detta i registret.

Slutsats och rekommendation

Resultatet blev alltså att genom att enbart återläsa databasen så kommer det alltid bli en mismatch mellan värdet i registret och databasen. Om man återläser hela servern kommer värdet i registret att genereras på nytt och fungera som det ska. Dock skiljer sig inte detta från att göra en ren installation av SCCM och bara återläsa databasen, då registervärdet kommer återskapas även då.

Så vad blir lärdomen och rekommendationen? Om man vill backa tillbaka t.ex. någon ändring man gjort i SCCM, ska vi då enbart läsa tillbaka databasen? Eller ominstallera hela servern? Ska vi använda det inbyggda SCCM-backupjobbet, tillför det något?

Som jag skrev i förra inlägget är förmodligen scenariot som min kund råkat ut för ytterst ovanligt. Det är förmodligen mycket sällan någon läser tillbaka en backup med syfte att radera hundratusentals användarobjekt. Därför kommer mismatch-problemet med datorvariabler knappast vara ett vanligt problem i praktiken.

Detta blir alltså mer ett teoretiskt problem, och min förra slutsats med att detta är ett designfel av Microsoft kvarstår. Värdet borde lagras i databasen där det hör hemma, och inte i registret.

Kan man då känna sig trygg med att enbart läsa tillbaka en databas, utan att ominstallera hela servern? Min åsikt måste bli ”ja” på den frågan. Framför allt om det är en backup från enbart någon dag tillbaka i tiden, och om inga gigantiska förändringar skett. Det finns en rad andra ”rowversion”-värden i registret, så det här teoretiska problemet kan eventuellt uppstå med andra saker. Men det känns alltså osannolikt i de flesta scenarion.

Tillför då det inbyggda SCCM-backupjobbet överhuvudtaget något längre? Svaret måste bli nej från mig, jag ser ingen anledning till att använda det längre. Behöver man återställa hela servern gör man en ren installation och återställer sen databasen, och får på så vis tillbaka allting. De registernycklar som tas i backupen tycks ändå inte läsas tillbaka (vilket verkligen är helknäppt), och i övrigt så tar backupjobbet bara med loggfiler och lite annat som inte känns tillräckligt relevant för att det ska vara värt det.

Rekommendationen blir alltså, fortsätt gör rena databasbackuper och använd dessa för återställning. Databaserna måste som bekant tas om hand om, där backup bara är en del av underhållsjobbet. Favoritmetoden i SCCM-världen är att använda sig av Ola Hallengrens utmärkta lösning för databasunderhåll. Använd denna och ta backuper varje dag. Vill man kan man även ta backup på site servern med det inbyggda backupjobbet eller någon annan metod, men detta blir alltså kaka på kaka som förmodligen aldrig kommer behövas. Dock ska man naturligtvis ha backup på sina source filer, och eventuella andra saker såsom script man har skapat och dylikt.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Sep 11

Guide: Exekvera site maintenance tasks i SCCM 2012 med PowerShell

Då tidigare inlägg som går lite mer på djupet i SCCM har varit populära så tänkte jag slå till med ännu ett i samma tema. Den här gången tänkte jag att vi skulle titta ned lite i databasen igen, och se hur vi letar oss fram till rätt information, och hur vi sedan utför något som inte går att göra direkt i SCCM via PowerShell.

Som exempel kommer jag använda en s.k. ”site maintenance task” i SCCM, och visa hur vi kan starta den manuellt från PowerShell.

DisclaimerFippla aldrig runt i databasen om du inte vet vad du gör eller har bra backuper. Det är inte supportat av Microsoft. Det vi går igenom i den här guiden kan betraktas som säkert, om man inte gör fel, men du gör det på egen risk.

Bakgrund

Om man använder Asset Intelligence i SCCM så tillkommer en hel del möjligheter för inventeringen. Man lägger till nya klasser i WMI, dvs utökar vad som inventeras på klienterna, man kan kategorisera och sammanställa inventerade programvaror på snyggare sätt, och man kan importera in licensinformation om ens applikationer, och på så vis följa upp installerade programvaror kontra faktiska licenser.

När man jobbar med SCCM lär man sig snabbt att saker och ting går långsamt. Allting måste hända i en viss ordning innan ett resultat spottas ut på andra sidan. En del av att vara en uber-administratör för SCCM är att lära sig hur saker och ting hänger ihop under skalet, så att man bl.a. kan trigga igång någonting som man vill ska ske omedelbart. Vilket ju är ett ganska vanligt önskemål. Vem har lust att vänta timmar eller dagar på att en applikation ska installeras, eller en rapport om hur många som installerat den, när chefen står och hänger i dörren och frågar?

Många saker i SCCM bygger på att någonting ska flyttas från en plats till en annan i databasen. Just Asset Intelligence är ett sådant exempel. AI har sina egna tabeller, vyer och stored procedures osv i databasen, och hämtar mycket av sin information från andra tabeller, där inventeringsdata lagras.

Scenario

Vi ska titta lite just på Asset Intelligence. Låt oss säga att vi har installerat en viss programvara på en klient. Vi kör en hardware inventory och ser hur programvaran dyker upp i t.ex. Resource Explorer. Inventeringen har alltså körts, och vi kommer också kunna hitta programvaran i vissa rapporter. Men om vi tittar i vissa Asset Intelligence rapporter så ser vi den däremot inte. Exempelvis om vi har licenser importerade för den här programvaran, och t.ex. tittar på rapporten License 15B – General license reconciliation report by computer. Så varför syns den inte här? Det ska vi ta reda på i den här guiden, och vi ska ta fram en metod för att snabbt uppdatera den här informationen, så att rapporterna börjar funka.

Hur funkar AI?

Lite kort om hur det funkar, och vad som behöver ske i SCCM för att en nyinventerad programvara ska börja dyka upp i AI-rapporterna.

Vi kan enkelt kontrollera vilka programvaror som AI ”känner till” genom att titta under Asset Intelligence och Inventoried Software i SCCM konsolen, under vyn Assets and Compliance. Syns inte programvaran där, så kommer heller inte rapporterna att funka.

Så vad är det för mekanism som ”flyttar” informationen från den vanliga inventeringen till AI? När kan jag förvänta mig att AI har uppdaterats?

En ledtråd till hur man kan tänka här är, att de flesta typer av sådana här aktiviteter, när tabeller i databasen ska uppdateras, sker med s.k. Maintenance Tasks i SCCM. Alla Maintenance Tasks hittar vi genom att högerklicka på Siten i konsolen, under Administration, och välja Site Maintenance.

SummarizeInstalledSoftwareWithPowerShell_1

 

Tittar vi vilka jobb som finns här så hittar vi ett jobb i listan som heter Summarize Installed Software Data. Det låter ju som det vi vill göra, och jag kan avslöja att mycket riktigt är det detta jobb som ansvarar för att uppdatera programvarorna i AI. Om vi tittar på när detta jobb körs så ser vi att standardinställningen är att köra mellan kl. 00-05 varje dag.

Doh! Vi måste alltså vänta till imorgon innan våra AI rapporter är uppdaterade med dagens alla installationer. Och chefen som ville ha svar ASAP…

Microsoft har tyvärr inte gett oss någon ”Run-right-now-I-don’t-want-to-wait-god-damnit”-knapp för att köra dessa maintenance tasks. Det enda sättet vi kan kicka igång dem från GUI’t är att gå in och ändra schemat till ett par minuter fram i tiden. Detta funkar och kan vara ”good enough” som metod någon gång ibland. Men det är inte helt optimalt. Dels måste man komma ihåg att ställa tillbaka schemat igen efter jobbet är klart, och dels funkar det faktiskt inte alltid helt bra om man t.ex. inte ställt in tidsintervallet, alltså fönstret som jobbet får köras under, tillräckligt långt.

Låt oss nu skapa vår egen ”Run-right-now-I-don’t-want-to-wait-god-damnit”-knapp.

Steg för steg…

Vi börjar med att köra jobbet, genom att som jag skrev ovan, ändra schemat inne i konsolen. När jobbet väl körs vill vi ta reda på vad som faktiskt händer i databasen. Det kan vi göra på lite olika sätt. Vi kan köra SQL Profiler och övervaka allt som sker i databasen, och där garanterat få vårt svar. Det är dock inget jag rekommenderar att börja med. Informationen man får kan vara ganska överväldigande, så man kan behöva filtrera och söka ganska länge innan man finner det man letar efter.

Istället tittar vi i SCCMs loggfiler, och den fil vi vill ha heter smsdbmon.log. Här loggas allting som SCCM gör just mot databasen, så låt oss se vad som händer när vi kör Summarize Installed Software Data-jobbet.

SummarizeInstalledSoftwareWithPowerShell_2

 

Lämpligtvis använder vi av oss t.ex. Highlight-funktionen i CMTrace och markerar orden ”Summarize Installed Software Data”. Vad vi ser ovan är att jobbet har körts och i det här fallet lagt till 0 rader i en tabell som heter INSTALLED_SOFTWARE_DATA_Summary.

Det var den första ledtråden, bra. Nu vet vi var datat lagras. Men vad använde SCCM för metod för att uppdatera denna tabell? Det ser vi tyvärr inte i loggen. Men SCCM använder sig av Stored Procedures i SQL för den här typen av uppgifter, så allt vi behöver göra är att leta upp rätt SP. Hmm, finns några hundra, så var börjar vi?

In i SQL Management Studio.
Vi vet ju nu vad tabellen heter, så låt oss titta på den. Vi kan ju börja med att högklicka på den och välja Select top 1000 rows så ser vi innehållet. Det vi ser här är en lista med exakt samma programvarutitlar som vi ser i SCCM-konsolen under Inventoried Software. Det verkar ju lovande, men vi vet fortfarande inte hur tabellen uppdateras. Vi högerklickar därför på tabellen och väljer View Dependencies.

SummarizeInstalledSoftwareWithPowerShell_3

 

Aha, det finns en stored procedure som heter spLoadInstalledSoftwareDataSummary. Låt oss undersöka den, genom att leta upp den i den lååånga listan med stored procedures, högerklicka på den och välja Modify.

När vi tittar närmare på koden ser vi att vad denna SP gör lite kortfattat är att ta en del information från tabellen INSTALLED_SOFTWARE_DATA, lagra resultatet i en temporär tabell och sedan jämföra med innehållet i INSTALLED_SOFTWARE_DATA_Summary. Programvarutitlar som lags till eller tagits bort kommer att uppdateras i INSTALLED_SOFTWARE_DATA_Summary.

Om vi tittar i INSTALLED_SOFTWARE_DATA så ser vi här samtliga inventerade programvaror från alla datorer. Med andra ord är INSTALLED_SOFTWARE_DATA_Summary en summering av INSTALLED_SOFTWARE_DATA (duh! därav tabellens namn) där ett hashvärde används för att identifiera varje unik programvara.

Jaha, det verkar ju logiskt hur det hänger ihop. Vi testar väl att köra denna stored procedure då, högerklicka och välj Execute Stored Procedure.

Tada! Om vi tittar i tabellen INSTALLED_SOFTWARE_DATA_Summary igen så har mycket riktigt vår saknade programvara dykt upp där. Var det verkligen så enkelt? Låt oss titta i SCCM-konsolen också för säkerhets skull. Jajamen, under Inventoried Software har applikationen dykt upp. Strålande.

Var det någon som sa PowerShell?

Nu hade ju jag lovat att vi skulle göra detta med PowerShell också. Vem vill hålla på och hoppa in i SQL Management Studio hela tiden för att göra sådana här saker? Det är ju PowerShell vi vill använda för allt. Så kan man köra en stored procedure i SQL med PowerShell? Jajamen. Vi kan göra det på lite olika sätt, men jag tänker nöja mig med att visa det enklaste sättet här.

Vi använder oss av cmdleten Invoke-Sqlcmd från modulen SQLPS som medföljer när man installerar SQL.

Svårare än det lilla simpla exemplet ovan är det inte. Byt ut CM_S01 mot namnet på din databas (alltså din sitekod), och spara scriptet som t.ex. Update-InventoriedSoftware.ps1 så kan du när som helst köra det.

Slutsats

Genom att ta sig tid att titta lite ”under skalet” kan man lära sig mycket. Och kunskap är nyckeln till hur vi förenklar vårt arbete, vår vardag och våra liv. Den här lilla guiden hade som syfte att hjälpa till att utveckla ett tankesätt, hur man börjar leta efter information i SCCM och hur man tar sig framåt och finner det man söker.

Det här exemplet är också förhoppningsvis till faktisk nytta för någon, i alla fall för er som använder sig flitigt av AI.

Hur skulle man kunna bygga vidare på det här och förfina lösningen?

Genom att använda samma metodik kan vi leta fram hur andra site maintenance tasks fungerar, och t.ex. låta namnet på stored proceduren vara en parameter till vårt script. På så vis kan vi enkelt starta igång olika maintenance tasks. Skulle man kunna lägga till detta i SCCM-konsolen så att man bara behöver klicka någonstans och få upp en lista på våra maintenance tasks, och då kunna köra igång dem direkt? Jajamen, visst kan vi göra det.

Det är, som alltid, bara vår fantasi som sätter gränserna.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Sep 03

SCCM 2012: Datorvariabler fungerar inte efter en återställning från backup

Uppdatering 2015-09-19: En uppföljning till detta inlägg med en vidare analys av problemet, finns nu här.

Jag har just spenderat hela dagen med att felsöka ett problem av den lite ovanligare sorten, och tänkte här återge i stora drag hur jag gick tillväga och vad jag hittade under det arbetet. Är man intresserad av felsökningsmetodik på lite djupare nivåer i SCCM 2012, där man tack och lov rätt sällan behöver pilla runt (och absolut inte SKA pilla runt om man inte är väldigt säker på vad man gör), så kan detta inlägg vara intressant att läsa. Men framför allt är också slutsatsen och upptäckten av den faktiska felorsaken intressant att känna till för alla. Jag lärde mig själv en del nytt som jag tar med mig i bagaget för framtiden.

Bakgrund

Under förra året gjorde jag en nyinstallation av SCCM 2012 hos en kund, som sedan under 2015 fortsatt införandet i delar av sin organisation. I somras råkade av misstag en ”AD user discovery” ske mot en mot en plats i AD som innehåller användarkonton som inte ska hanteras i SCCM. Det var ingen liten mängd utan rörde sig om flera hundratusentals konton. Teoretiskt är detta inget problem i sig då det ”bara” är att radera dessa konton i SCCM. Men då det rör sig om sådana här mängder, i en miljö som heller inte är dimensionerad för detta, så upptäcker man hur lång tid det faktiskt tar att radera ett objekt i SCCM. Det skulle helt enkelt ta alldeles för lång tid att rensa all denna information, så det beslutades istället att en återläsning av backupen skulle ske.

Databasbackuper kördes varje natt och man hade inga förändringar som skulle gå förlorade, så tanken var att detta skulle gå oändligt mycket snabbare än att försöka rensa ur databasen.

Sagt och gjort, databasen lästes tillbaka och vips var man av med över 300 000 konton som man inte ville ha på en bråkdel av tiden jämfört med att radera allting. Här ska noteras att enbart databasen lästes tillbaka, en ”site recovery” kördes inte. Enligt dokumentationen ska egentligen alltid en site recovery köras, men det är egentligen oklart varför och dokumenationen är egentligen ganska luddig. I SCCM 2012 finns t.ex. inte längre någon ”site control fil” och det är numera supportat att göra en site recovery med enbart en databasbackup från t.ex. ett SQL Maintenance Job. All relevant information och konfiguration ska finnas i databasen, så att återställa just bara databasen kan man ju tycka räcker. Vad gör ”site recovery”-processen i övrigt för magi som gör att man bör köra den? Det framgår inte i någon dokumentation, och här skulle jag säga råder en viss förvirring i världen.

Hur som helst, här återläste man alltså enbart databasen. Allting verkade frid och fröjd, allt ”lyste grönt” och fungerade som det skulle. Tills man började köra ”OS deployment” och rulla burkar.

Själva installationerna gick precis som vanligt utan problem, men man använder också variabler på både collections och på datorobjekten för att dynamiskt kontrollera en rad olika saker i installationen. Vad man nu upptäckte var att datorvariablerna inte längre fungerade, och ignorerades helt och hållet av task sequencen.

Analys

För att felsöka problemet fick jag först börja ”från början”, då jag själv inte varit med vid återläsningen från backup och inte sett miljön på länge. Jag började alltså med en enkel hälsokontroll för att se om det fanns några allmänna fel eller problem, eller tecken på att något gått fel vid återläsningen. Allting tycktes dock vara ett praktexempel på en fungerande miljö utan några konstigheter.

Då just problem med datorvariabler och OSD har varit en känd bugg tidigare så kontrollerade jag också snabbt att den hotfixen inte längre var applicerbar (den byter bara ut en liten dll-fil), och så var inte fallet. Det hade också varit konstigt då versionsnivån var R2 SP1 (dock utan CU1), där denna fix för länge sen ingår. Service packen hade också installerats efter återläsningen från backup, vilket annars är en bra metod för att lösa många problem då i princip de flesta delar på hela site servern ominstalleras och återställs. Men problemet kvarstod alltså.

Jag fortsatte sedan med att skruva upp loggningen till maxnivå på SMSTS.log på klienten (en bra artikel för hur man gör detta och ändrar maxstorleken på loggen, kan man läsa här). I loggen kunde jag mycket riktigt utläsa ”Found 0 machine variables” och att någon policy för datorvariabler aldrig ens försökte laddas ned. Däremot fungerade collection variabler utan problem. Något annat intressant fanns inte här, men detta räckte för att visa att det helt enkelt inte fanns någon policy för datorvariabler att hämta på management pointen. Det kändes alltså tydligt som ett serverproblem och inte ett klientproblem.

Jag aktiverade därefter debug logging på management pointen och började gå igenom de olika MP-loggarna, och matcha vad som hände där samtidigt som klienten efterfrågade sin policy. Kort sagt fanns inget intressant att hitta om problemet i dessa loggar. Jag såg inga tecken på problem i management pointen, och kunde helt enkelt inte se några spår av en policy med datorvariabler hämtats från databasen.

Nästa steg i kedjan blev alltså att börja undersöka själva databasen, och den process som genererar policies som sedan levereras till MPn. Den komponent i SCCM som ansvarar för detta heter SMS_POLICY_PROVIDER och har en loggfil som heter policypv.log. Jag började alltså gräva i denna loggfil, samt även i loggen smsdbmon.log för att se vad hände i databasen.

Jag började skapa variabler på datorobjekt, både i den riktiga miljön samt i min egen testmiljö, där allting fungerade som det ska, och jämförde resultaten.

Så fort en variabel skapas kan följande utläsas i smsdbmon.log:

SCCM_Datorvariabler_1

Ok, så tabellen MEP_MachineExtendedProperties har uppdaterats. Detta är också vad som är förväntat, och detta skedde utan problem, likadant i både problem-miljön och min testmiljö.

Det som ska ske härnäst är att en ny policy ska genereras för datorn som har fått variabeln, och denna policy ska alltså innehålla variabeln och dess värde. Detta ser man tydligt i policypv.log, och så här ser det ut i min testmiljö när det fungerar som det ska:

SCCM_Datorvariabler_2

Det vi ser här är ett urval ur loggen som visar hur en ny policy som innehåller ”machine extended properties”, vilket är lika med datorvariabler, har genererats för en dator med ett visst ”machine ID” och GUID. En snabb koll i konsolen, alternativt ”Get-CMDevice -Name MinTestDator” visar att detta ID och GUID mycket riktigt hör till den dator där jag skapade variabeln.

I problem-miljön såg det dock lite annorlunda ut. Samma saker sker fram till raden i loggen som börjar med ”MEP-Querying MV for rowversion...” men där det sedan ska returneras en ny policy, så var det här helt tomt. Ingen policy med ”machine extended properties” kom tillbaka, och SMS_POLICY_PROVIDER fortsatte glatt att generera policy för allt annat (applikationsinstallationer, device settings, osv).

Loggraden ”MEP-Querying MV for rowversion...” ser i sin helhet ut så här:

Det körs alltså en query i databasen, och därefter ska policyn som innehåller variabeln returneras. Hmm, kunde det vara så att denna query inte gav önskat resultat? Det var dags att på allvar titta ned i databasen.

Först lite bakgrund till hur det SKA se ut i databasen när allting fungerar som det ska.

När man skapar en variabel på en dator så uppdateras följande tre tabeller i databasen:
MEP_MachineVariables
MEP_MachineExtendedProperties
MEP_MachinePolicies

Jag testade att skapa variabeln ”MinTestVariabel” på min testmaskin ”testar3” som har Machine ID 16777235, och tittar i den första tabellen.

SCCM_Datorvariabler_3

Vi kan tydligt se att variabeln har skapats (värdet är dock ”scramblat” och går inte att läsa i klartext).

Nästa tabell, MEP_MachineExtendedProperties, innehåller ingen information i sig, utan är bara en plats för att hålla reda på vilka datorobjekt som faktiskt har variabler definierade, och när en förändring av dessa görs.

SCCM_Datorvariabler_4

Återigen hittar vi en rad med min testdator, information om när ändringen gjordes, samt någonting som heter rowversion. Vi återkommer till detta.

När väl dessa båda tabeller är uppdaterade ska, om allt fungerar korrekt, en ny policy genereras för datorn som innehåller variabeln. Att så har skett ser vi i den sista tabellen.

SCCM_Datorvariabler_5

Min testdator har dykt upp här, och i det här läget kan man alltså se i policypv.log att en ”MEP-policy” för datorn mycket riktigt hämtas.

I problem-miljön dök dock datorn bara upp i de två första tabellerna, men aldrig i den tredje. Ok, så variabeln lagras korrekt i databasen, och även den tidsstämplade informationen om att det faktiskt finns en variabel (i MEP_MachineExtendedProperties), men någon policy skapas tydligen aldrig. Det var dags att gå till botten med hur logiken i mekanismen som genererar denna policy faktiskt fungerar. Det var dags att göra en databas ”trace”.

För detta ändamål använder vi verktyget SQL Server Profiler vilket är ungefär motsvarigheten till Process Monitor i databasvärlden. Vi kan följa i realtid exakt vad som sker i databasen, vilka queries som görs, vilka transaktioner som sker. Precis som med Process Monitor blir det snabbt ett hav med information, och särskilt då det gäller en produktionsmiljö där det hela tiden sker saker. Det gäller alltså att veta ungefär vad man letar efter.

För att minska mängden information skapade jag ett filter: ApplicationName Like SMS_POLICY_PROVIDER
Detta då jag ju visste att det är denna komponent som genererar policies och att problemet därför måste ligga där, så med detta filter blev mängden hanterbar.

Genom att söka på ”MEP” fick jag ganska snabbt fram en hel del intressant information. Jag kunde se att det första som skedde var att följande query gjordes:

Aha, detta var ju samma query vi såg tidigare i policypv.log. Och mycket riktigt, efter denna query kunde jag i tracen se i min testmiljö steg för steg hur policyn skapades, men i problem-miljön hände ingenting. Så låt oss undersöka denna query.

Det den gör är kort och gott att leta fram alla datorer där en variabel har lagts till, tagits bort eller förändrats. Och denna information sparades ju i tabellen MEP_MachineExtendedProperties. Kör jag denna query manuellt så får jag mycket riktigt till svar just den dator där jag just skapat en variabel (i det här fallet min testdator ”testar3”).

Så logiken här är alltså att leta fram enbart de datorer där en förändring av en variabel har skett genom att titta i MEP_MachineExtendedProperties, därefter generera en policy för denna dator och spara information om detta i MEP_MachinePolicies.

I problem-miljön såg det ut så här:

SCCM_Datorvariabler_6

Alltså samma query här, men i den här miljön returneras inget svar vilket jag snabbt kan kontrollera genom att köra den manuellt. Så vad är problemet, varför hittas inte min dator där jag lagt till en variabel? Jag kunde ju se att min dator låg i tabellen MEP_MachineExtendedProperties precis som den ska, och det är ju där queryn ställer sin fråga. Låt oss återigen titta närmare på queryn. Den filtrerar resultatet genom att ställa villkoret att innehållet i kolumnen rowversion måste vara större än ett visst värde, som anges i hexadecimal form. Jag jämförde värdet i queryn med det högsta värdet som faktiskt fanns i tabellen, och upptäckte att värdet i queryn var över 4 miljoner högre än vad som fanns i tabellen. Så kort sagt, den frågar efter någonting som är otroligt mycket högre än vad som faktiskt finns, och får därför tillbaka ett tomt svar. Policy providern kommer tolka detta som att ingen dator har uppdaterat någon variabel och någon policy kommer därför heller inte att genereras. Logiskt, och nu börjar vi närma oss lösningen.

Så vad är då detta ”rowversion” och varför är värdet i queryn fel?

Enkelt förklarat används ”rowversion” för att spåra förändringar som sker i en databas, som en sorts versionshantering i tabellerna. Värdet är globalt för hela databasen men är frivilligt att använda i varje enskild tabell. Så fort en tabell innehåller en ”rowversion-kolumn” kommer den globala räknaren att öka med ett steg så fort en förändring sker i denna tabell. Mer detaljer finns att läsa på MSDN.

Nu är sista pusselbiten på plats för att förstå hur logiken fungerar med queryn ovan. Rowversion används alltså i tabellen MEP_MachineExtendedProperties för att hålla koll på varje gång en variabel läggs till, uppdateras eller tas bort. När så sker ska en ny policy genereras. Policy providern håller koll på senaste värdet för rowversion, och behöver därför bara ställa en fråga efter alla datorer som har ett högre värde för att på så vis få reda på vilka datorer som ska ha en ny policy.

Men varför trodde policy providern att det senaste rowversion-värdet var hela 4 miljoner högre än vad det verkliga värdet faktiskt var i databasen?

Hela problemet hade ju börjat efter en backup-återläsning av en SCCM-databas som innehöll ~300 000 färre objekt. När importen av alla dessa objekt skedde så motsvarade det tydligen ca 4 miljoner transaktioner i databasen, varpå rowversion ökades upp motsvarande. Efter återläsningen så återställdes detta värde till samma som det var innan hela importen, alltså ca 4 miljoner lägre.

Det var nu uppenbart att SCCM sparar detta värde även någonstans UTANFÖR databasen, och att vi därför fick detta glapp mellan vad policy providern trodde var den senaste förändringen, och vad som faktiskt stod i databasen. Så var kan detta tänka lagras?

Registret känns ju som en väldigt kvalificerad gissning, och nu råkade jag veta att de flesta SCCM-komponenter har en egen registernyckel under HKLM\Software\Microsoft\SMS\Components, och mycket riktigt så finns en nyckel där även för policy providern. Jag började med att titta där och fick jackpot direkt:

SCCM_Datorvariabler_7

VOILA! Här står klart och tydligt nyckeln MEPHandler som har ett värde med namn ”Last Row Version”. Kan det vara så enkelt? Jag jämförde datat i det värdet, ett hexadecimalt tal, med värdet för rowversion i den query som jag tidigare sett i policypv.log och i SQL tracen, och det var såklart exakt samma värde. Här var alltså det gäckande talet som var 4 miljoner för högt och som gjorde att inga datorvariabel-förändringar fångades upp i databasen.

Lösningen? En snabb titt igen i MEP_MachineExtendedProperties och sortera efter just rowversion för att leta upp det högsta värdet i tabellen:

Jag kopierade detta värde och klistrade in i registret och PANG så började allting att fungera perfekt igen.

Slutsats

Förutom att den här typen av felsökningsarbete är fantastiskt roligt, sådär som bara de nördigaste av de nördiga kan uppskatta, så lämnar dagens övningar ett par nya lärdomar och även ett frågetecken efter sig. Traditionellt har det i SCCM-världen alltid, fram till härom året, varit ett ”big no-no” att göra en återläsning på något annat sätt än från en backup gjord med det inbyggda backup-jobbet i SCCM. Det har alltså inte räckt att bara peka på en backup av databasen. Själv har jag haft lite svårt att vänja mig vid tanken på att man numera kan göra så.

Det inbyggda backupjobbet tar, förutom databasen, även med inboxarna och andra saker från filsystemet, samt även alla registernycklar. Och faktum är, jag dubbelkollade i min testmiljö nu ikväll, att just denna nyckel som innehåller ”last row version” tas med i den backupen. Så med andra ord, hade man använt den traditionella SCCM-backupen hade detta problem aldrig uppstått. Men när man återställer från en sådan backup så gör man å andra sidan också per definition en site recovery.

Men frågetecknet är detta: hade en site recovery fixat till problemet som här uppstod, och på något sätt synkat värdet i registret med databasen?

Jag vet inte, det får hamna på min att-göra-lista att prova i min testmiljö. Jag hoppas att så är fallet. Om inte, så är detta en brist i det fullt supportade scenariot att göra en återställning med enbart en databasbackup.

Det här är första gången jag ser en miljö läsas tillbaka på det här sättet, alltså att man bara lagt tillbaka databasen men struntat i site recovery. Men jag tror att det inte är helt ovanligt att så sker. På olika bloggar och forum runt om i världen nämns det ofta att backup i SCCM numera enbart handlar om databasen, och att det är den bästa metoden för då kan man använda ett SQL maintenance job eller DPM eller liknande, och därmed komprimera backupen och spara utrymme, och att allting är snabbare och bättre osv. Med andra ord börjar folk gå ifrån att använda det inbyggda backupjobbet i SCCM. Och jag kan tänka mig att många också gör en återläsning med just bara databasen. För allting finns ju där, och det funkar ju faktiskt. Dvs, förutom det problem som uppstod just i det här fallet. 🙂

Nu ska sägas att det är mycket osannolikt att det här scenariot uppstår, det här var förmodligen ett ganska unikt fall. Att man i en produktionsmiljö väljer att läsa tillbaka en backup som innehåller över 300 000 färre objekt hör knappast till det vanliga. Är det bara en liten differens mellan policy providerns räknare i registret och värdet i databasen, så äts den skillnaden upp ganska snabbt med alla transaktioner som sker hela tiden i databasen.

Kan det finnas andra saker som inte funkar när man återställer enbart databasen utan att också göra en site recovery? Säkert. Slutsatsen måste därför bli att verkligen följa site recovery wizarden i alla lägen.

En sista fundering från mig. VARFÖR i herrans namn sparas detta värde i registret, och inte i databasen? Varför får helt enkelt inte policy providern istället en egen liten tabell där den kan skriva detta och underhålla detta värde? Detta är i min mening ett designfel från utvecklarna. Jag kan i alla fall inte föreställa mig något bra skäl till att lagra en databaspekare utanför databasen.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Aug 28

BSOD i Windows 7 pga registerkomprimering i WinPE 5.0

Precis innan sommaren råkade jag ut för ett Blue-Screen-of-Death-problem hos en kund. Jag hade skapat en ny Windows 7 32-bit image med alla senaste uppdateringar fram t.o.m. juni. Det här är en image som uppdateras regelbundet, och några andra förändringar hade inte skett i imagen vid det här tillfället. Jag misstänkte alltså att problemet berodde på någon av juni månads Windows-uppdateringar.

Jag analyserade blåskärmen och såg att felet som rapporterades var: 0xF4_36b1_IMAGE_wininit.exe

Av en slump kände jag igen just detta fel, då jag sett det rapporteras från flera olika håll under 2015. Varför jag råkade ut för det just i juni och inte tidigare är märkligt, men felet är känt sedan tidigare och uppträder lite slumpmässigt. Man råkar typiskt sett bara ut för det om man kör en 32-bitars boot-image, vilket jag gjorde i det här fallet, och det uppstår bara i WinPE 5.0 och senare. En noggrannare förklaring till problemet beskrivs här:

http://blogs.technet.com/b/dip/archive/2015/01/21/win2008r2-win7-stop-0xf4-during-task-sequence-os-deployment.aspx

Kort sagt är lösningen följande:

  1. Mounta boot-imagen:
    dism.exe /mount-wim /wimfile:<path-to-wimfile> /index:1 /mountdir:C:\Mount
  2. Öppna regedit, välj Load hive och öppna filen C:\Mount\Windows\System32\config\SOFTWARE
  3. Lägg till följande registervärde:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet001\Control\Session Manager\Configuration Manager

    Name: RegistryReorganizationLimitDays
    Datatype: DWORD
    Value: 365

    (ja det ska vara CurrentControlSet001 ovan, detta omvandlas sen till CurrentControlSet när WinPE körs)

  4. Välj Unload hive och stäng regedit.
  5. Avmontera imagen:
    dism.exe /unmount-wim /mountdir:C:\Mount /commit

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Maj 07

SCCM 2012 R2 CU5 finns nu tillgänglig

Igår släpptes Cumulative Update 5 till SCCM 2012 R2.

Läs mer och hämta hem uppdateringen här: https://support.microsoft.com/en-us/kb/3054451

Notera att några uppdateringar för PowerShell inte längre ingår i cumulative updates. Alla PowerShell cmdlets har istället flyttats ut till System Center Configuration Manager Cmdlet Library som är en separat installation. Har ni inte redan installerat den, så gör det nu.

Nästa vecka ska det också släppas nya service packar till SCCM 2012.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Apr 02

Automatisk tilldelning av Office365 licenser med Powershell

När man kör Office365 men har ett eget on-premise Active Directory, så använder man Azure AD Sync (AADSync) för att automatiskt synkronisera kontoinformationen till Azure AD så att kontona kan användas i Office365. Vad som dock inte sker automatiskt med något av de verktyg vi får från Microsoft, är tilldelning av licenser till dessa konton. Detta måste man manuellt gå in i Office365-portalen och göra i efterhand.

Men nu är Azure och Office365 så fantastiskt att vi även kan hantera allting med Powershell. Vilket betyder att automatisering plötsligt blir både möjligt och enkelt.

Det vi behöver göra är följande:

  1. Förbereda konton och lösenord som ska användas till scriptet
  2. Skapa ett Powershell-script
  3. Skapa en schemalagd aktivitet som kör scriptet

Förbered konton och lösenord

Vi behöver två konton:

  • Ett admin-konto med tillräckliga behörigheter att ändra licensinformationen i Office365
  • Ett konto som ska köra den schemalagda aktivitet som vi använder för att schemalägga scriptet

Vi kan naturligtvis använda samma konto för båda dessa syften, det är valfritt. Eftersom vi redan använder AADSync så har vi redan ett konto där som vi lämpligtvis kan använda som admin-konto även för det här ändamålet. Men om detta konto t.ex. bara ligger i molnet och inte finns i vårt lokala AD, då blir det svårt att använda för vår schemalagda aktivitet, varpå vi behöver ett separat konto för detta.

Jag gillar att köra mina aktiviteter med datorns egna konto, alltså Local System, för att slippa ha ett dedikerat användarkonto, och kommer göra så i det här exemplet.

Nästa steg är att spara ned lösenordet för detta admin-konto på ett säkert sätt så att vi kan använda oss av det i scriptet. Här är nu det viktiga att se till att det konto vi använder för att köra den schemalagda aktiviteten kan läsa detta lösenord. Eftersom vi kommer spara lösenordet i krypterad form så kommer enbart detta utvalda konto att kunna läsa det.

Eftersom jag vill köra med kontot Local System måste jag därmed skapa det krypterade lösenordet med System-kontot. Ett enkelt sätt att göra detta är att ladda ned PsExec och sen köra:

psexec.exe -i -s powershell.exe

På så vis startar jag Powershell med System-kontot. Detta gör vi på den maskin där den schemalagda aktiviteten ska köras (lämpligtvis samma server som kör AADSync). Lösenordet kommer nämligen bara att kunna läsas av detta konto, på just denna dator, och ingen annanstans.

I Powershell kör vi nu följande:

I prompten skriver vi nu in lösenordet för det admin-konto vi kommer använda oss av i scriptet. Detta kommer sparas i krypterad form i filen C:\Scripts\DirSyncCreds.txt och bara vara läsbart för System-kontot på just den här datorn.

Skapa scriptet

För att tilldela en licens till en användare i Office365 behöver vi göra två saker:

  • Välja en licens och tilldela denna. Detta görs med cmdleten Set-MsolUserLicense 
  • Välja en location, dvs förmodligen Sverige för oss, som användaren tillhör. För detta används cmdleten Set-MsolUser

Så i grund och botten är det bara två enkla cmdlets vi behöver köra. För att göra en lite mer komplett lösning kan det vara en bra idé att lägga till lite logging och liknande i scriptet. Eftersom hela det här exemplet förmodligen är mest intressant för små och mellanstora organisationer, där man kanske inte har så mycket bra övervakningsverktyg, och där konton inte skapas så ofta, så har jag i mitt script-exempel lagt med att scriptet helt enkelt mailar någon administratör varje gång en licens tilldelats någon användare, eller om någonting har misslyckats. För att detta ska fungera måste det finnas en SMTP-server någonstans på nätverket som vi kan skicka mailet genom. Har du ingen sådan kan du enkelt lägga till en, då det finns en färdig sådan roll i Windows Server. Detta är dock utanför den här guiden.

Vi behöver också ett sätt att urskilja vilka användare som faktiskt ska få en licens, och det lättaste sättet här är att använda en vanlig AD-grupp. Har vi flera olika licenser som vi vill använda så skapar vi helt enkelt flera grupper. I det här script-exemplet utgår vi dock från bara en enda licens, men det är väldigt enkelt att lägga till fler om man så vill.

Scriptet ser ut så här:

Scriptet kräver följande för att fungera:

Spara ned scriptet och ändra variablerna högst upp i scriptet och fyll i korrekt admin-konto, sökväg till lösenordsfilen (som vi skapade tidigare), licens, AD-grupp, mailadresser, osv.

Kontrollera att allting fungerar genom att köra scriptet manuellt. Lägg till flaggan -Verbose så loggas hela förloppet i konsolen.

Skapa schemalagd aktivitet

När scriptet är testat och fungerar så är det bara att schemalägga det med en vanlig Windows schemalagd aktivitet. Hur ofta den ska köras är såklart valfritt, men AADSync körs t.ex. som standard var 3:e timme, så att matcha det schemat kan vara en ide.

Konfigurera följande i aktiviteten:

  • Kontot som köra aktiviteten (SYSTEM i det här exemplet)
  • Schema
  • Action:
    Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    Argument: -NoProfile -ExecutionPolicy Bypass -File C:\Scripts\Set-O365License.ps1

Ändra namn och sökväg till scriptet så att det matchar din miljö. Därefter kan vi luta oss tillbaka och se hur det trillar in ett litet mail i vår inkorg varje gång vi skapar en ny användare, som berättar att denne automatiskt fått sin O365-licens tilldelad.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Feb 10

Del 1 – Automatisera bygget av dina referensimages

Att bygga sin referensimage som man sedan rullar ut med sin OS deployment lösning är en återkommande uppgift för varje IT-avdelning. Microsoft släpper som bekant uppdateringar varje månad, varpå imagen helst bör byggas om varje månad så att den alltid är fullt uppdaterad. Det är naturligtvis fullt möjligt att släpa efter lite, och installera de uppdateringar som saknas vid själva installationstillfället av imagen istället. Men finns det någon anledning till att ha det så? Finns det något bra skäl till att inte uppdatera sin image varje månad?

De flesta gör nämligen inte det. Det sker istället ad-hoc när man har tid, eller i bästa fall har man en rutin där man gör detta en eller några gånger om året. Och man gör det manuellt. Eller rättare sagt, väldigt många har lyckats automatisera själva byggprocessen, men man startar igång den manuellt.

I den här guiden ska vi titta på hur vi väldigt snabbt och enkelt kan automatisera ett schema som spottar ur sig en rykande färsk image varje månad direkt efter Patch Tuesday.

Det här går naturligtvis att göra på många olika sätt och med många olika verktyg. Men vi börjar från början och gör det så enkelt som möjligt. Så i den här första delen kommer vi använda följande tekniker och verktyg:

  • MDT
  • Hyper-V
  • Powershell
  • Scheduled tasks

Förbered byggmiljön

För att bygga vår referensimage använder vi oss av MDT. Vi skapar alltså en task sequence som installerar Windows på en virtuell maskin, installerar alla uppdateringar och eventuella programvaror, gör eventuella anpassningar, och sparar sedan hela installationen i en imagefil någonstans på nätverket. I den här guiden kommer vi inte gå igenom exakt hur man gör allt detta. Vi utgår istället för att du redan har en sådan här task sequence på plats, och kommer istället fokusera på hur vi kör denna task sequence automatiserat och schemalagt.

Om du inte redan har ett deployment share färdigt i MDT för detta ändamål så är en bra plats att börja på här: https://technet.microsoft.com/en-us/library/dn744290.aspx

Det viktiga är att task sequencen och deployment sharet kör hela processen helt automatiskt, dvs utan att det krävs något manuellt meck, såsom frågor i Lite touch wizarden, eller pauser i task sequencen eller liknande. Har du några manuella anpassningar du gör i din image idag så är det första du måste göra att bygga script som fixar detta. Men normalt sett är det rekommenderat att försöka hålla imagen så ren och enkel som möjligt, och det ska vara enkelt att bygga den automatiskt.

Din CustomSettings.ini bör se ut ungefär så här:

Dessa inställningar resulterar i en helt automatisk installation som avslutas med att referensdatorn stängs ned.

Namnet på imagen kommer innehålla datumet då task sequencen kördes, vilket gör att vi får en enkel versionshantering.

Förbered den virtuella referensmaskinen

Vi använder oss här av Hyper-V som vi kan hantera helt och hållet via Powershell, och därför är underbart enkelt att automatisera. Hyper-V är gratis så du kan köra allt det här på din egen arbetsstation (om du har Windows 8 eller nyare), på någon överbliven dator, eller varför inte köpa in en liten NUC för ett par tusenlappar som får stå som dedikerad byggmaskin?

Så i Hyper-V, gör följande:

  1. Skapa en virtuell maskin. Ge den gärna 2 vCPU och 4 GB RAM (och helst inte mindre än 1 GB) om du har hårdvara som räcker. Skapa och lägg till en virtuell hårddisk med standardinställningarna, dvs en dynamisk expanderbar disk som är helt tom.
  2. När maskinen är skapad och medan den fortfarande är nedstängd, och hårddisken är helt tom, ta en snapshot som du kallar t.ex. ”Blank HD”. Den här snapshoten kommer vi använda för att återställa maskinen från början varje gång vi bygger en ny image.
  3. Om deployment sharet ligger på en annan dator än den dator som kör Hyper-V, så behöver du fixa så att du kan mounta ISO-filen över nätverket:
    1. Ge Hyper-V datorns datorkonto i domänen fulla behörigheter på Boot-katalogen i deploymentsharet.
    2. På Hyper-V datorns datorkonto i domänen, lägg till MDT-serverns datorkonto under fliken Delegation och välj tjänsten cifs.

Så kort och gott bör du nu ha en virtuell maskin, som heter t.ex. ImageFactory eller något liknande, men en snapshot och som ska kunna mounta boot-imagen från ditt deploymentshare. Testa manuellt att allt fungerar, att du kan boota maskinen från ISO-filen och att du kan backa tillbaka snapshoten.

Hantera den virtuella maskinen med Powershell

Spara scriptet nedan som Build-ReferenceImage.ps1 och lagra det i någon lämplig katalog på MDT-servern.

Vad scriptet gör är helt enkelt att återställa snapshoten på den virtuella maskinen, mounta en ISO-fil vilket i det här fallet ska vara boot-imagen från MDT, och sen startar igång den virtuella maskinen. Vidare raderar den alla sparade image-filer, baserat på hur många dagar tillbaka i tiden man vill ha historik, så att vi slipper ha image-filer som fyller upp disken i all oändlighet. Vill vi alltså bara ha de senaste två månadernas image-filer så raderar vi allting som är äldre än 62 dagar.

Allting styrs med parametrar till scriptet, såsom namn på virtuella maskinen, namn på snapshot, namn på Hyper-V datorn, sökvägar osv.

Exempel:

Testa att kör scriptet manuellt från MDT-servern och ange parametrar som stämmer överens med din miljö. Verifiera att den virtuella maskinen verkligen återställer sin snapshot, mountar ISO-filen och startar upp och bootar från ISOn ordentligt.

Schemalägg scriptet

När vi nu har alla byggstenar på plats så behöver vi bara schemalägga scriptet med en helt vanlig scheduled task, så att det körs en gång i månaden, direkt efter Patch Tuesday. Börja med att skapa ett lämpligt servicekonto som har behörighet att köra denna scheduled task på MDT servern, samt behörighet att på Hyper-V datorn att starta igång den virtuella maskinen. Kopiera sedan texten nedan och spara den som BuildReferenceImage.xml på MDT-servern.

Denna XML-fil innehåller hela den schemalagda aktiviteten. Ändra alla script-parametrar efter <Arguments> så att de passar i din miljö och kör sedan följande kommando för att skapa den schemalagda aktiviteten:

Ändra kontot och lösenordet och eventuellt namnet på den scheduled task som kommer att skapas.

Voilá det var det hela. Klockan 03:00 den andra onsdagen varje månad kommer nu automatiskt en ny referensimage att skapas och ligga och vänta på dig när du kommer in till jobbet på morgonen.

Slutsats

Som vi ser kan man med otroligt enkla medel göra så mycket som underlättar vår stressade IT-vardag. I det här exemplet har vi med bara tre ynka rader Powershell (ok 5 rader inklusive logiken för att ta bort gamla filer) samt en gammal hederlig scheduled task, automatiserat en uppgift som de flesta IT-avdelningar regelbundet utför, men som de flesta gör manuellt.

Vad är nästa steg, kan man utveckla det här och göra det ännu bättre? Självklart, och det är det som är så roligt med automatisering. Det är bara fantasin som sätter gränserna. Varför inte skicka ett mail till dig när bygget är klart som berättar om allting gick bra? Varför inte automatiskt lägga in den nya imagen i en task sequence i MDT och/eller SCCM? Kanske testa att deploya imagen med denna task sequence på en virtuell testmaskin, och sen skicka ett till mail och berätta om testet gick bra? Och så vidare och så vidare…

I nästa del ska vi titta på hur man gör detta med Service Management Automation istället.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Tidigare inlägg «