Category: PowerShell

PowerShell module BalloonNotification – hvordan utvikle moduler med C# og VisualStudio 2012

By , 8 oktober, 2012 01:38

Balloon en pest og plage?

«Windows Ballooning» eller «NotifyIcon» oppleves av mange som en pest og plage, men de små beskjedene har også sin nytte. Selv har jeg benyttet «bobla» til å informere sluttbruker om viktige hendelser knyttet til logonscript, eller for å vise maskininformasjon slik som IP-adresse, domene- og maskinnavn.

Denne bloggposten gir hjelp til hvordan man kan lage C# PowerShell moduler i Visual Studio 2012 Express. Modulen BalloonNotification er benyttet som eksempel og kildekode.


Demo av PowerShell modulen BalloonNotification

PowerShell eller C# som språk ved utvikling av moduler

PowerShell er et kraftfullt språk. Som PowerShell fantast er min anbefaling at man også velger å utvikle moduler med PowerShell som språk så langt det er mulig. Likevel har jeg denne gang valgt å skrive modulen i C# med Visual Studio 2012. Årsaken var behov for enklere håndtering av klassen NotifyIcon. Samtidig hadde jeg også stor nysgjerrighet på C# og Visual Studio 2012. Jeg er ingen utvikler og C# er et språk jeg ikke benytter i det daglige. Dere som kan programering og C# får ha meg unnskylt.

Det er også mulig å kjøre C# i PowerShell, men det det kan på grunn av kompilering under kjøring av script oppleves som tregt. Jeg pleier derfor å kompliere koden først og importere denne som modul i PowerShell. (Det en fordel med god kildekode og versjonskontroll for senere iterasjoner). Typisk vil man komme i situasjoner hvor man ønsker å legge til GUI i script og C# eller andre lignende språk kan være enklere å jobbe med, for eksempel gjennom å lage en modul for PowerShell.

NotifyIcon
Klassen NotifyIcon tilhører System.Windows.Forms og er komponenten som håndterer ikon i systemstatusfeltet (http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.aspx). NotifyIcon klassen kan i likhet med andre .net klasser også benyttes i PowerShell, for eksempel gjennom følgende:

[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
$notification = New-Object System.Windows.Forms.NotifyIcon

Hvordan komme i gang med C# PowerShell modulprosjekt i Visual Studio 2012

Før man begynner utvikling av PowerShell modul i C# bør man installere Windows PowerShell 2.0 Software Development Kit (SDK) – http://www.microsoft.com/en-us/download/details.aspx?id=2560
I eksemplet skal vi benytte System Management Automation.

Opprettelse av Visual Studio 2012 PowerShell module prosjekt

  1. Opprett nytt prosjekt - for eksempel »File | New Project…» eller velg « New Project» under «Start Page»
  2. I vinduet «New Project» velg «Visual C# | Windows | Class Library«. Skriv inn ett passende navn i «Name» og «Soultion name«, samt angi plassering under «Location»

    New Project Visualt Studio 2012

  3.  

  4. Nye prosjekter i Visual Studio 2012 blir opprettet i .NET 4.0. Vi må endre dette til .NET Framework 3.5 slik at PowerShell 2.0 kan laste modulen.
    Under «Solution Explorer» høyreklikk «BalloonNotification» (eller ditt C# prosjektnavn) og velg «Properties«. Under vinduet «Application» velg «Target Framework | .Net Framework 3.5.»
    Net Framework 3.5

    Net Framework 3.5

  5. Det må legges til to PowerShell «References» – System.Management og System.Management.Automation.
    Høyreklikk «References» og velg «Add«. Legg til nødvendige references. Man må selv lokalisere og velge Windows.Management.Automation.dll i PowerShell SDK installasjonsmappen. Legg også til eventuelle andre References etter behov og etter hva du skal benytte i din modul.
    References

    References

Det er nå klart for å utvikle og skrive C# PowerShell modul i Visual Studio 2012.
 
Modulnavn og CmdLet
Navnet på modulen defineres av «namespace» og vil i «boble» eksemplet være BalloonNotification. Hver «CmdLet» opprettes som Class og [Cmdlet("Show", "Notification")] vil gi en CmdLet som får navnet «Show-Notification» under kjøring i PowerShell.

namespace BalloonNotification
{
    [Cmdlet("Show", "Notification")]
    public sealed class NotifyIconpop : PSCmdlet
    {
    }
}

 
Parametere til en CmdLet
For å opprettet parametere til en CmdLet anngir man egenskapene til parametere, for eksempel hvis parameteret er påkrevd (Mandatory). I eksemplet vil string IconType være pramameter nummer tre i rekkefølgen av aktuelle parametere for en CmdLet. I eksemplet er det også benyttet «ValidateSet» som angir de aktuelle valgene. Valgene vil komme som forslag ved bruk av «Tab» i PowerShell.

// Icon Type
[ValidateSet("Information", "Warning", "Error", "Exclamation", "Hand", "Shield", "Question")]
[Parameter(Mandatory = false, Position = 3)]
public string IconType
{
     get
     {
          return this.iconType;
     }
     set
     {
          this.iconType = value;
     }
}

Full kildekode modul BalloonNotification
Modulen BalloonNotification består av en CmdLet – Show-Notification. Show-Notification har fire parametre. Kildekoden beskriver også typisk bruk av klassen NotifyIcon og hendelseshåndtering ved bruk av «bobla».

Kildekode og kompilert modult kan lastes ned fra Technet Gallery: http://gallery.technet.microsoft.com/BalloonNotification-81c1cd0b

using System;
using System.Diagnostics;
using System.Management.Automation;
using System.Drawing;
using System.Windows.Forms;

namespace BalloonNotification
{
    [Cmdlet("Show", "Notification")]
    public sealed class NotifyIconpop : PSCmdlet
    {
        private string iconType;
        private string message;
        private string title;
        private string notifiaction;
        private System.Windows.Forms.NotifyIcon notify = new System.Windows.Forms.NotifyIcon();
                
        public ContextMenu contextMenu1 = new ContextMenu();
        public MenuItem menuItem1 = new System.Windows.Forms.MenuItem();

        // Message
        [ValidateNotNullOrEmpty]
        [Parameter(Mandatory = true, Position = 0)]
        public string Message
        {
            get
            {
                return this.message;
            }
            set
            {
                this.message = value;
            }
        }

        // Title
        [ValidateNotNullOrEmpty]
        [Parameter(Position = 1)]
        public string Title
        {
            get
            {
                return this.title;
            }
            set
            {
                this.title = value;
            }
        }

        // Action variable
        [ValidateNotNullOrEmpty]
        [Parameter(Mandatory = false, Position = 2)]
        public string NotifiAction
        {
            get
            {
                return this.notifiaction;
            }
            set
            {
                this.notifiaction = value;
            }
        }

        // Icon Type
        [ValidateSet("Information", "Warning", "Error", "Exclamation", "Hand", "Shield", "Question")]
        [Parameter(Mandatory = false, Position = 3)]
        public string IconType
        {
            get
            {
                return this.iconType;
            }
            set
            {
                this.iconType = value;
            }
        }
              
        // NotificationIcon Balloon start initilization 
        [STAThread]
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            Process thisProcess = Process.GetCurrentProcess();
         
            // Icon menu
            contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { menuItem1 });
            menuItem1.Index = 0;
            menuItem1.Text = "E&xit";
            menuItem1.Click += new System.EventHandler(menuItem1_Click);
          
            // Balloon and icon settings
            notify.Icon = typeof(SystemIcons).GetProperty(this.iconType).GetValue((object)null, (object[])null) as Icon;
            notify.BalloonTipIcon = ToolTipIcon.None;
            notify.BalloonTipText = this.Message;
            notify.BalloonTipTitle = this.Title;
            notify.ContextMenu = contextMenu1;
            notify.Visible = true
            notify.ShowBalloonTip(40);
            
            // If balloon clicked or closed
            notify.BalloonTipClicked += (sender, e) =>
            {
                // If no balloon action added
                if (string.IsNullOrEmpty(this.NotifiAction) == true)
                {
                    CleanUp(notify);
                }
                else
                {
                    System.Diagnostics.Process.Start(this.NotifiAction);
                    CleanUp(notify);
                }
            };
            notify.MouseMove += (sender, e) =>
            {
                notify.ShowBalloonTip(40);
                notify.Visible = true;
            };      
        }

        // Clean up
        static void CleanUp(System.Windows.Forms.NotifyIcon c)
        {
            c.Visible = false;
            c.Dispose();
            Application.Exit();
        }
        
        // Exit from menu
        private void menuItem1_Click(object Sender, EventArgs e)
        {
            CleanUp(notify);
        }          
    }
}

Bruk av modulen i PowerShell script


Eksempel på bruk av modulen i PowerShell script

Eksempel på bruk av modulen i PowerShell script


Dette eksemplet gir gjennom «bobla» informasjon om maskinen hvor scriptet kjører. Hvis man trykker på «bobla» opprettes en WEB-side hvor flere maskinegenskaper vises.

Import-Module BalloonNotification

#Region variabler
$WMIComputerSystem = get-wmiobject win32_computersystem -ComputerName $Env:COMPUTERNAME # WMI
$WMINetworks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Env:COMPUTERNAME | ? {$_.IPEnabled}
$UserNamedom = "$Env:USERDOMAIN" + "\" + "$Env:USERNAME" # USERNAME
$HtmFile = "C:\source\" + $Env:UserName + ".htm" # HTML FIL PATH

# MEMORY
If ($WMIComputerSystem.TotalPhysicalMemory -lt 1GB)
{        
	$Memory = "$('{00:N2}' -f ([MATH]::Round($WMIComputersystem.TotalPhysicalMemory / 1MB))) MB"    
}    
Else
{        
	$Memory = "$('{00:N2}' -f ([MATH]::Round($WMIComputersystem.TotalPhysicalMemory / 1GB))) GB"    
}

# IP
$IPAddress  = $WMINetworks.IPAddress[0]
# MAC
$MACAddress  = $WMINetworks.MACAddress
#EndRegion Variabler

#Region Maskin Objekter
$MaskinObj = New-Object -TypeName PSobject
$MaskinObj | Add-Member -MemberType NoteProperty -Name MaskinNavn -Value $Env:COMPUTERNAME # Maskinnavn
$MaskinObj | Add-Member -MemberType NoteProperty -Name Brukernavn -Value $UserNamedom # Brukernavn
$MaskinObj | Add-Member -MemberType NoteProperty -Name Modell -Value $WMIComputerSystem.Model
$MaskinObj | Add-Member -MemberType NoteProperty -Name Fabrikat -Value $WMIComputerSystem.Manufacturer # PC modell
$MaskinObj | Add-Member -MemberType NoteProperty -Name Minne -Value $Memory # Memory
$MaskinObj | Add-Member -MemberType NoteProperty -Name IP -Value $IPAddress # IP
$MaskinObj | Add-Member -MemberType NoteProperty -Name MAC -Value $MacAddress # MAC
#EndRegion Maskin Objekter		

#Region HTML
$a = "<style>"
$a = $a + "BODY{background-color:White;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:Grey}"
$a = $a + "TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:DarkGrey}"
$a = $a + "</style>"

$data = 
$MaskinObj | Select-Object Maskinnavn, Brukernavn, Fabrikat, Modell, Minne, IP, MAC | 
ConvertTo-HTML -head $a -body "<H2>Maskininformasjon</H2>" | 
Out-File $HtmFile
#EndRegion HTML

#Notification message
$Message =  “Maskinnavn: $($MaskinObj.Maskinnavn) `nBrukernavn: $($MaskinObj.brukernavn) `n`nFabrikat: $($MaskinObj.Fabrikat) `nModell: $($MaskinObj.modell) `nIP-addresse: $($MaskinObj.ip) `nMAC-address: $($MaskinObj.IP)”
Show-Notification -Message $Message -Title "Information" -NotifiAction $HtmFile -IconType Information

Post to Twitter Post to Facebook Post to LinkedIn

Sletting av AD Child Objekter med PowerShell

By , 25 april, 2012 00:20

I blant er det behov for å slette «Child Objects» tilhørende brukerobjekter i Active Directory. Typisk vil dette være nødvendig hvis man skal migrere brukerobjekter med Active Directory Migration Tool mellom domener eller forrest. Hvis brukerobjektet har «Child Objekts» vil ikke brukerobjektet kunne migreres.

«Child Objects» opprettes for eksempel for mobile enheter som synkroniseres mot Exchange 2010. Den mobile enheten får opprettet sin enhets-ID i klassen msExchangeActiveSyndDevice under «Child» objektet CN=ExchangeActiveSyndDevices.

Sletting av «child» objekter kan manuelt utføres gjennom ADSIEdit, men hvis behov for sletting av denne type objekter fra flere brukerobjekter samtidig, vil bruk av script være mest hensiktsmessig.

Det er stilt mange spørsmål i forskjellige fora om hvordan sletting av «Child» objekter kan utføres med PowerShell, men det er ikke mange gode svar. Jeg har derfor valgt å vise hvordan jeg sletter «child» objekter med PowerShell. Første eksempel viser bruk av Microsofts Active Directory module og eksempel to gir samme resultat men benytter PowerShell snapin Quest Active Roles Management.

Sletting av «child» objekter med Microsoft Active Directory module:

# Microsoft Active Directory Module
function Del-LeafObject 
{
	<#
	.SYNOPSIS
	Del-LeafObject
	.DESCRIPTION
	Removes Child object from userobjects
	.NOTES
	AUTHOR:    Lars Jostein Silihagen
	#>
	param 
	(

	    [string]$ADUser
	)
	$LeafObject = Get-ADObject -Filter * -SearchScope oneLevel -SearchBase $ADUser.DistinguishedName        
	if($LeafObject)    
	{        
		Write-Host "Removes Child Objects for user "  $ADUser -ForegroundColor Yellow
		$LeafObject | Remove-ADObject -Recursive    
	}
	else
	{
		write-host "Can't find any child objects for user: " $UserName 
	}
} # end Del-LeafObject

Sletting av «child» objekter med Quest:

# Quest
function Del-LeafObject
{
	<#
	.SYNOPSIS
	Del-LeafObject
	.DESCRIPTION
	Removes Child object from userobjects
	.NOTES
	AUTHOR:    Lars Jostein Silihagen
	#>
	param 
	(
	    [string]$ADUser
	)
	$LeafObject = Get-QADObject -SearchScope onelevel -SearchRoot $ADuser
	if($LeafObject)    
	{       
		Write-Host "Removes Child Objects for user" $ADUser -ForegroundColor Yellow
		Remove-QADObject -Identity $LeafObject -deletetree -force
	}
	else
	{
		write-host "Can't find any child objects for user: " $UserName 
	}
} # end Del-LeafObject

Scriptene kan lastes ned fra MS TechNet Gallery: http://gallery.technet.microsoft.com/Deletion-of-Active-9c0dedd6

Post to Twitter Post to Facebook Post to LinkedIn

Get-InstalledApplications.ps1

By , 19 mars, 2012 10:52

Har publisert ett PowerShell script som er hendig for å hente ut oversikt over installerte applikasjoner på en Windows 7 klient.

Scriptet kan lastes ned fra Microsoft TechNet Gallery for Script Repository: http://gallery.technet.microsoft.com/scriptcenter/Get-InstalledApplicationsps-e2aee784

Scriptet henter alle installerte applikasjoner basert på avinstallasjonsinformasjon i Registry og oppretter en WQL-query for hver applikasjon. Scriptet kan for eksempel være til god hjelp for personell som arbeider med applikasjonsdistribusjon eller querys i SCCM.

Følgende objekter returneres:
• AppName
• AppVersion
• AppVendor
• UninstallString
• AppGui
• WQLQuery

Example:
Get a list of installed applications on local computer:

Get-InstalledApplications.ps1

AppName : Aruba Networks Virtual Intranet Access
AppVersion : 2.0.1.0.30205
AppVendor : Aruba Networks
UninstallString : MsiExec.exe /X{F5CE8021-D68C-44A9-A69E-14725B63212D}
AppGUID : {F5CE8021-D68C-44A9-A69E-14725B63212D}
WQLQuery : SELECT * FROM Win32Reg_AddRemovePrograms WHERE Displayname LIKE ‘Aruba Networks Virtual Intranet Access 2.0.1.0.30205′ AND Version LIKE ’2.0.1.0.30205′

Post to Twitter Post to Facebook Post to LinkedIn

MTUG – Microsoft Technology User Group og PKI foredrag

By , 10 mars, 2010 08:56

Tirsdag 16 mars vil brukergruppen Microsoft Technology User Group Oslo bli etablert. Brukergruppen vil være en non-profit brukergruppe med hovedvekt på Microsoft infrastruktur. Oppstart og informasjon om brukergruppen vil foregå hos Microsoft på Lysaker tirsdag 16 mars kl 18:00 og er ett gratis arrangement.

Sammen med oppstart av MTUG vil det bli holdt ett spennende foredrag av Nick Voicu fra Microsoft Redmond med tittelen – Tips and Tricks for making the best PKI deployment. PKI er en viktig del av grunnmuren som må på plass før man kan ta i bruk mye ny teknologi slik som blant annet DirecAccess og NAP, og er en teknologi vi som konsulenter må kunne noe om. Nick Voicu har de siste seks årene jobbet med utvikling av sikkerhetsteknologier i Windows og da spesielt PKI. Han kan med andre ord det han snakker om og er også en svært dyktig foredragsholder.

Påmelding: http://mtug.eventbrite.com/

Agenda for MTUG og PKI foredraget:

1800 – 1805 : Velkommen
1805 – 1820 : Introduksjon til MTUG
1830 – 2030 : Tips and tricks for making the best PKI deployment
2030 – 2100 : Q&A samt sosial mingling utover kvelden

”PowerShell guden” er på Oslo besøk
Om du jobber med Microsoft server produkter møter du Powershell – og hva er vel bedre enn å lære om Powershell fra kilden? Kom og hør Bruce Payette prate om Powershell. Bruce Payette er forfatter av boka «Powershell in action», og er Principal Developer hos Microsoft i Redmond.
Bruce vil starte med å gi ett innblikk i hva Powershell er per idag, og hva Microsoft mener med Powershell fremover. Han vil fortsette med å gi oss et dypdykk i bruk av Powershell, samt gi oss en innføring i hvordan vi selv kan utnytte avanserte funksjoner i Powershell.
Denne workshopen gir innsikt både til de som er ferske med Powershell, og de som har jobbet med Powershell en god stund.
Arrangementet er gratis og arrangeres av MTUG i samarbeid med Microsoft i auditoriet på Lysaker torsdag 18 mars og begynner kl 12:00.

Post to Twitter Post to Facebook Post to LinkedIn

PowerShell SendKeys

By , 15 november, 2009 22:59

# Login script burde inneholde litt god PowerShell kode..:
[void] [System.Reflection.Assembly]::LoadWithPartialName(«‘System.Windows.Forms»)
[System.Windows.Forms.SendKeys]::SendWait(«^%({DOWN})»)
# Gir brukerne en god start på dagen og kanskje support en liten utfordring.. :-)

I forbindelse med skripting er det av og til behov for å sende tastetrykk til applikasjoner eller til installasjonsprosedyrer. Eksemplet over viser hvordan ”tastetrykk” kan sendes med PowerShell, her med kombinasjonen ”ctrl + alt + down arrow”.  En kombinasjon som vil snu skjermbildet opp ned.

En liste over «kodene» for ”SendKeys”: http://www.microsoft.com/technet/scriptcenter/topics/winpsh/convert/wshsendkeys.mspx

Post to Twitter Post to Facebook Post to LinkedIn

Snart ferie…

By , 30 juni, 2009 23:29

Ferien begynner å nærme seg, og ferien skal krysses av i kalenderen the PowerShell way..

# LJ_Ferie.ps1
# Lars Jostein Silihagen, 01.07.2009
# Oppretter ny hendelse i Outlook kalender

# Setter Outlook som objekt og kobler mot kalender mappen
$outlook = New-Object -com outlook.application
$namespace = $outlook.GetNamespace("MAPI")
$calendar = $namespace.GetDefaultFolder(9) # 9 = kalender

# Legger til ferie i Outlook kalenderen
$ferie = $calendar.Items.Add(1)
$ferie.Start = "18. july 2009"
$ferie.AllDayEvent = $true
$ferie.End = "3. august 2009"
$ferie.Subject = "Lars Jostein har FERIE!!"
$ferie.Location = "Et sted med sol, blå himmel og fiskemuligheter"
$ferie.Importance = 2 # High importance
$ferie.BusyStatus = 3 # Out of office
$ferie.body = "http://www.yr.no/"
$ferie.save()
#EOF

Post to Twitter Post to Facebook Post to LinkedIn

Windows PowerShell BOF foredrag fra TechEd

By , 26 mai, 2009 16:27

Kom over en bra podcast fra et ”Birds of a Feather” møte om PowerShell som ble holdt på TechEd. Det sitter en del dyktige PowerShell guruer på møtet deriblant utvikleren av PowerGUI og svarer på spørsmål om PowerShell. Tittelen for møtet var ”Practical PowerShell: Best Practices from the Field” og inneholder blant annet:

  • Function naming
  • PowerShell Profiles
  • Execution policied and security
  • Remoting
  • Best practices

Link til podcast: http://media.libsyn.com/media/powerscripting/PSPodcast-070.mp3

Post to Twitter Post to Facebook Post to LinkedIn

[system.media.systemsounds]::Beep.Play();

By , 20 april, 2009 23:29

Jeg har gjort en del enringer på bloggen min, og har samtidig bestemt meg for å skrive på norsk! Tittelen spilles best i PowerShell..!

Post to Twitter Post to Facebook Post to LinkedIn

How to test a registry key in PowerShell

By , 31 august, 2008 23:25

In PowerShell you easley can test a registry key with the cmdlet Get-ItemProperty.

PS C:\> $key = $(Get-ItemProperty «HKLM:\SOFTWARE\LJS»).LarsJostein -eq «Silihagen»
PS C:\> $key
True

PowerShell example where  you test the installed Operations Manager Console version:
function OpsMgrVer
{
return $ver = $(Get-ItemProperty «HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup»).CurrentVersion
}
function TestVersion
{
$nr = OpsMgrVer
if (OpsMgrVer -ge «6.0.6270.0″)
{ Write-Host «SCOM 2007 SP1 is installed. ServerVersion: $nr» } else { Write-Host «SCOM 2007 SP1 is not installed. ServerVersion: $nr» }
}

Post to Twitter Post to Facebook Post to LinkedIn

Cmdlet verb names

By , 31 august, 2008 22:36

Last week I worked with a PowerShell script where I did a big blunder!   I had created a function with the name “Start” and I did not find the reason of why my script failed before at least one hour. Start is one of the PowerShell reserved verbs so stay away from them in your function names or variables!

List of reserved PowerShell verbs at Microsoft: http://msdn.microsoft.com/en-us/library/ms714428.aspx

Or you can of course list the verbs with PowerShell:
$verbs = [System.Reflection.Assembly]::LoadWithPartialName(«System.Management.Automation»)
$verbs.GetTypes() | where {$_.Name -match «Verbs»} | foreach {$_.GetFields() | foreach {$_.Name}} | sort

Post to Twitter Post to Facebook Post to LinkedIn

Panorama Theme by Themocracy