Test-Administrator

Po vcerejsi ukazce jak sputit PowerShell s admin pravy, si ukazeme, jak zjistit zda s admin pravy bezime:

function Test-Administrator
{
       $NTIdentity  = [Security.Principal.WindowsIdentity]::GetCurrent()
       $NTPrincipal = [Security.Principal.WindowsPrincipal] $NTIdentity
       
       $NTPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

       $NTIdentity.Dispose()
}
Posted 12 června 07 09:00 by jachymko | 0 Comments   
Filed under , ,
ObjectCache<T>

V jednom soukromem projektu jsem potreboval po urcitou dobu cachovat urcity objekt. ASP.NET obsahuje skvely cachovaci mechanismus, ale ja jsem potreboval neco mnohem jednodussiho, a co je hlavni, nemohu se spolehnout ze vzdy budu mit k dispozici nejaky HttpContext. Proto jsem si napsal vlastni jednoduchouckou in-memory cache:

public delegate T Producer<T>();

public class ObjectCache<T>
{
    private readonly Producer<T> _producer;
    private readonly TimeSpan _duration;

    private T _cachedObject;
    private DateTime? _cachedOn;

    public ObjectCache(Producer<T> producer)
        : this(producer, TimeSpan.FromMinutes(1))
    {
    }
    public ObjectCache(Producer<T> producer, TimeSpan duration)
    {
        _producer = producer;
        _duration = duration;
    }

    public T Instance
    {
        get
        {
            if (_cachedOn == null || (DateTime.Now - _cachedOn.Value) > _duration)
            {
                _cachedObject = _producer();
                _cachedOn = DateTime.Now;
            }

            return _cachedObject;
        }
    }
}
Posted 11 června 07 07:15 by jachymko | 2 Comments   
Filed under
Admin shell

Nejsnazsi zpusob, o kterem vim, jak na Viste spustit PowerShellovy prompt s admin pravy, je timto skriptem:

$psi = [diagnostics.processstartinfo]"$PSHOME\PowerShell.exe"
$psi.verb = 'runas'
[diagnostics.process]::start($psi)
Posted 11 června 07 07:00 by jachymko | 1 Comments   
Filed under , ,
OT: Kavarna POTME

Vcera jsme s pritelkyni navstivili kavarnu POTME, kterou na Ovocnem trhu provozuje sdruzeni Svetluska. Bude tam jeste do stredy, tak nevahejte a stavte se na kavu nebo caj. Stoji to opravdu za to, clovek si uvedomi jak moc na zrak spoleha, a zjisti, ze kava vypita potme chutna uplne jinak. Navic tim podporite nevidome, dozvite se o jejich zivote, a dostanete pekny hrnicek :)

Posted 11 června 07 03:00 by jachymko | 0 Comments   
Filed under
Prirazovani poli

Vsichni zname standardni syntax $pole[$index] pro pristup k polozkam poli. Co je mene zname, je fakt, ze v PowerShellu se pole nemusi objevovat pouze vlevo od hranatych zavorek, ale i vevnitr. Tam pole integeru predstavuje indexy polozek ktere chceme ziskat. V nasledujicim priklade si vytvorime pole znaku od 'a' do 'z' a vratime si 1., 5., a desatou az patnactou polozku. Scitani ma nizsi prioritu nez .., tudiz se scitaji dve pole a ne 4+9.

[char[]] $znaky = ([char]'a'..[char]'z')
$znaky[(0,4)+(9..14)]

Pokud by nekoho zajimalo, proc je treba vyraz ([char]'a'..[char]'z') pretypovat na pole znaku, ackoliv oba dva operandy jsou jiz chary, je to proto ze operator .. pracuje s a vraci integery. Char si na integer dokaze pretypovat sam, ale pak uz nevi, ze vstupem puvodne byly chary.

Dalsi vec, kterou se hodi vedet, je ze prirazovaci operator muze mit na leve strane vice promennych. To se da vyuzit na jednoduche naparsovani nejakeho retezce, treba takto:

# $text = 'aaa;bbb;ccc;ddd'
# $zza, $zzb, $zzc = $text.Split(';')[0..2]
# dir variable:zz* | ft -a

Name Value
---- -----
zzc  ccc
zzb  bbb
zza  aaa
Posted 04 června 07 03:19 by jachymko | 0 Comments   
Filed under ,
Hratky s ucty

Jeden kolega se vcera na interni diskuzni skupine ptal jak lze overit zda retezec ve forme "DOMENA\JmenoUctu" reprezentuje existujici Active Directory ucet. Premyslel jsem zda to resit pomoci LDAP/GC ADSI providera, nebo pomoci lehce obsolete WinNT providera, ale jde to udelat snadno pomoci .NET 2.0 IdentityReference trid.

function Test-AccountName($name) {
    trap { $false; continue }

    [bool] (([Security.Principal.NTAccount] $name).Translate([Security.Principal.SecurityIdentifier]))
}

Dalsi kolega dnes resil ze potrebuje ziskat login name ze jmena k zobrazovani, neboli z "Pepa z depa", ziskat "josef.von.depo". Neni nic snazsiho nez udelat malou LDAP query

function Get-AccountName($cn)
{
    [DirectoryServices.DirectorySearcher]$search = "(cn=$cn*)"
    [void]$search.PropertiesToLoad.Add('sAMAccountName')
    $result = $search.FindOne()

    if ($result)
    {
        $result.Properties['samaccountname']
    }
}
Jak zabit vzdalenej proces

Stala se mi takova nemila vec, nejak se zblaznil explorer.exe na Longhornu, a zustal viset Alt-Tab dialog pres celou obrazovku. Task Manager se objevil, aby vzapeti tez prestal reagovat. Uz jsem se bal ze se budu muset odlogovat, nebo dokonce masinu rebootnout, ale protoze ostatni procesy vypadaly ze celkem ziji, zkusil jsem chcipla okna odstranit z notebooku vedle. Jak jinak nez PowerShellem.

param($machine, $processName) 

Get-WmiObject `
	-ComputerName $machine `
	-Class Win32_Process `
	-Filter "Name LIKE '%$processName%'" |% `
{
	if ($_.Terminate().ReturnValue -ne 0)
	{
		Write-Error "Failed to terminate $processName on $machine."
	}
}
Posted 31 května 07 11:22 by jachymko | 0 Comments   
Filed under ,
UIAutomation

Soucasti WPF je novy UI-automation framework nahrazujici starsi Active Accessibility. Vice se dozvite na MSDN:

http://msdn2.microsoft.com/en-us/library/ms747327.aspx

130# $null = import-assembly 'UIAutomationClient' 131# 131# function Process-Element($el, $indent=0) { >> >> "$(New-Object String ' ', (2 * $indent))$($el.Current.LocalizedControlType): $($el.Current.Name)" >> >> $children = $el.FindAll('Children', [Windows.Automation.Condition]::TrueCondition) >> >> foreach($c in $children) { >> Process-Element $c ($indent + 1) >> } >> } >> 132# $wordpad = Get-Process wordpad -ea SilentlyContinue | Select -First 1 133# 133# if (-not $wordpad) { >> & "$Env:ProgramFiles\Windows NT\Accessories\wordpad.exe" >> sleep -milli 600 >> >> $wordpad = Get-Process wordpad >> } >> 134# $windowHandle = $wordpad.MainWindowHandle 135# $window = [Windows.Automation.AutomationElement]::FromHandle( $windowHandle ) 136# 136# Process-Element $window window: Document - WordPad pane: For Help, press F1 pane: Standard pane: Formatting pane: Arial pane: Arial pane: 10 pane: 10 pane: Central European pane: Central European pane: Standard pane: pane: 137#
PowerShell Community Extensions 1.1
Mezi nove vlastnosti patri
  • LDAP provider, prikazy pro praci s Active Directory
  • zakldadni podpora .lnk shortcutu, NTFS symlinku, junctions...
  • vytvareni zip, bzip2, gzip a tar souboru
  • provider poskytujici pristup do GACu, prikazy pro loadovani assemblies
  • nahrada ping.exe
  • prikazy pro praci s clipboardem
  • prikazy pro zakladni manipulaci se System.Drawing.Bitmap
  • prikazy pro spravu remote desktop sessions
  • nova tab expansion
  • integrace less.exe

PowerShell Community Extensions 1.1

Posted 08 března 07 04:04 by jachymko | 0 Comments   
Filed under
PowerShell Community Extensions

Velice zajimavy projekt na CodePlexu, jehoz cilem je doplnit do PowerShellu co nejuzitecnejsi vlastnosti, ktere v prvni verzi chybi. Obsahuje mimo jine cmdlety pro praci se clipboardem, filesystemem, upravu textu, formatovani xml, nebo treba provider pro Common Feed Store v IE7.

Takze nevahejte a stahujte na http://www.CodePlex.com/PowerShellCX!

Posted 14 prosince 06 06:30 by jachymko | 3 Comments   
Filed under
LINQ May 2006 CTP

Ackoliv to uz davno neni zadna zhava novinka, porad je kvetnove CTP LINQu posledni verzi, pouzitelnou alespon na testovani ve stavajicim Visual Studiu 2005. Bude soucasti Orcasu, nicmene ve Virtual PC imagi rijnoveho CTP toho jeste moc neni.

No ale hlavni duvod proc o tom pisu: instalace velice rada pada s chybou 2738. Nejak souvisi s VBScriptem, ktery instalacni balicek pravdepodobne pouziva. Aby se vam LINQ povedlo nainstalovat, staci znovu zaregistrovat vbscript.dll.

regsvr32 $Env:SystemRoot\system32\vbscript.dll
Posted 11 prosince 06 02:27 by jachymko | 0 Comments   
Filed under
Set-PSDebug

Nastrojem, bez ktereho se nemuzete obejit pri psani byt jen trochu slozitejsiho skriptu, je commandlet Set-PSDebug. Tento prikaz umoznuje zapnout trasovani, krokovani, a mod, kdy PowerShell nedovoli pouzit promenne jimz jeste nebyla prirazena hodnota. Ma tyto parametry:

  • -trace: Tento parametr muze nabyvat hodnot 0, 1, nebo 2. Level 1 zobrazuje spoustene radky kodu, podobne jako ECHO ON v cmd.exe. Level 2 je zobrazuje tez, plus navic vypisuje prirazeni promennych a volani funkci a skriptu.
  • -step: Tento prepinac zapne krokovani (a trasovani minimalne na uroven 1). Pred spustenim kazdeho radku zobrazi prompt, ktery umoznuje jeden nebo vsechny radky povolit ci zamitnout, nebo otevrit "nested prompt", ve kterem muzete prozkoumat ci pozmenit stav skriptu, a po opusteni prikazem exit pokracovat v krokovani, jako by se nic nestalo.
  • -strict: Uzitecny prepinac, ktery zpusobi chybu pokud zkousite pouzit promennou, kterou jste jeste nepriradili, podobne jako Option Explicit ve Visual Basicu.

Poslednim parametrem je prepinac -off, ktery vsechny vyse zminene funkce jednoduse vypne.

Posted 07 prosince 06 05:05 by jachymko | 0 Comments   
Filed under
TranslateFrom-Czech

Prestoze jsem rikal ze napsani skriptu na prekladani z cestiny necham na vas, napsal jsem ho take. A kdyz uz jsem na to sahal, tak jsem upravil puvodni funkci aby v pripade vice nez dvaceti prekladu slova stahla i nasledujici stranky.

function Global:TranslateFrom-Czech(
    [string]$Czech,
    [switch]$English,
    [switch]$Deutsch,
    [switch]$Francais) {

                        $lang = 1
        if($Deutsch)  { $lang = 3 }
    elseif($Francais) { $lang = 7 }
    
    SlovnikAtlasCZ $czech $lang
}

function Global:TranslateTo-Czech(
    [string]$English, 
    [string]$Deutsch, 
    [string]$Francais) {
    
                        $lang = 0; $word = $English
        if($Deutsch)  { $lang = 2; $word = $Deutsch  }
    elseif($Francais) { $lang = 6; $word = $Francais }

    SlovnikAtlasCz $word $lang
}

function Script:SlovnikAtlasCz([string]$word, [int]$lang) {

    $webclient = (new Net.WebClient)
    $webclient.Encoding = [Text.Encoding]::UTF8

    $word = [Web.HttpUtility]::UrlEncode($word)
    $url = "http://slovnik.atlas.cz/?utf=y&lang=$lang&word=$word"

    $result = new PSObject

    do {
        $response = $webclient.DownloadString($url)
    
        $regex = new regex '<span class="a3r2"><a href="([^"]*)">další</a></span>', 'Multiline,IgnoreCase'
        $match = $regex.Match($response)
        
        if($match.Success) { $url = "http://slovnik.atlas.cz/$($match.Groups[1].Value)" }
        else               { $url = $null }
    
        $regex = new regex 'id="results">.*<ul>(.*)</ul>', 'Singleline,IgnoreCase'
        $definitions = $regex.Match($response).Groups[1].Value
        
        $regex = new regex '<li><strong>(.*):</strong>(.*)</li>', 'Multiline,IgnoreCase'
        $match = $regex.Match($definitions)
        
        while($match.Success) {     
            $result | add-member NoteProperty ($match.Groups[1]).Value.Trim() ($match.Groups[2]).Value.Trim() -Force 
            $match = $match.NextMatch()
        }  
    } while($url)
    
    $result
}

Posted 06 prosince 06 06:12 by jachymko | 0 Comments   
Filed under ,
PowerShell + Team Foundation Server

Jak jsem zminil v predchozim postu, posledni verzi sveho profilu drzim v Team Foundation Serveru, jelikoz jsem liny porad zmeny rucne synchronizovat mezi vsemi pocitaci ktere pouzivam. No a protoze jsem opravdu hodne liny, tak me ani nebavi po kazde zmene vsude rucne otevirat studio a klikat na get latest version. Nastesti TFS ma krasne .NETove API, ktere primo vybizi k tomu aby bylo pouzito z PowerShellu.

Prvni jednoduchoucka funkce, abychom si neupsali prsty, na pripojeni k TFS. Casem asi pridam podporu pro zadani uzivatelskeho jmena a hesla, ale zatim to nepotrebuji.

function Get-Tfs($ServerUri) {
    new Microsoft.TeamFoundation.Client.TeamFoundationServer $ServerUri
}

Dalsi jednoducha funkce, ktera najde lokalni workspace podle zadane cesty ve filesystemu a pripoji se k source control serveru.

function Get-TfsWorkspace($LocalPath, $Server) {
    $workstation = [Microsoft.TeamFoundation.VersionControl.Client.Workstation]::Current
    $workspace = $workstation.GetLocalWorkspaceInfo($LocalPath)
    
    if(-not $Server) {
        $server = Get-Tfs $workspace.ServerUri
    }
    
    $workspace.GetWorkspace($Server)
}

A jako tresnicka na dortu funkce, ktera stahne posledni verzi profilu. Aby fungovala, staci mit nastavenou promennou $ProfileDir, treba pomoci tohoto vyrazu, a promennou $ProfileTfs, ktera obsahuje URL Team Foundation Serveru.

function Get-LatestProfile($TeamFoundationServer) {
    $workspace = Get-TfsWorkspace $ProfileDir $ProfileTfs
    $workspace.Get()
}

Metoda Get() vrati objekt ktery vypada asi nasledovne. Ma metodu, ktera umoznuje ziskat seznam konfliktu, ale na to uz je pohodlnejsi Visual Studio, takze se spokojim se statistikou kolik se toho povedlo a kolik ne.

[93] » Get-LatestProfile

NumFailures            : 0
NumOperations          : 1
NumConflicts           : 0
NumWarnings            : 0
NoActionNeeded         : False
HaveResolvableWarnings : False

[94] »

Aby byly pouzivane typy k dispozici, je potreba (z GACu) naloadovat assembly Microsoft.TeamFoundation.VersionControl.Client. Uplne nejsnazsi, byt do budoucna nepodporovany (!) zpusob je pomoci [Reflection.Assembly]::LoadWithPartialName

Prenositelny profil

Jelikoz muj PowerShellovy profil jiz za dva roky rozsirovani narostl do dost obludnych rozmeru, musel jsem ho rozdelit do vice souboru. Take k nemu patri sada formatovacich a typy-rozsirujicich .ps1xml souboru, a musel jsem vyresit jak je vsechny spravne naloadovat.

Prvni, primocary pokus o ziskani cesty na ktere se profil nachazi, spocival v jednoduchem $ProfileDir = (split-path $Profile). To fungovalo dokud se tam profil opravdu nachazel. V $Profile totiz je cesta k profilu specifickemu pro konkretni powershellovy host a aktualniho uzivatele. Ale napriklad ve virtualnich masinach, kde pouzivam vice uctu, bych chtel mit profil v adresari \Windows\System32\WindowsPowerShell\v1.0\ abych ho nemusel synchronizovat nebo slozite vytvaret junctions.

PowerShell nastesti, kdyz loaduje profil, nastavi promennou $MyInvocation, a z ni se da regularnim vyrazem vyziskat cesta. Jen se musi zaridit aby tato promenna vypadala stejne i kdyz je profil na netradicnim miste. Ja to resim tak, ze si z Team Foundation stahnu profil treba do D:\SharedProfile, a do souboru "$Env:SystemRoot\System32\WindowsPowerShell\v1.0\Profile.ps1" vlozim dot-sourcovane volani hardcodovane cesty, to znamena

. D:\SharedProfile\Profile.ps1

No a jak vypada ten vyraz ktery ziska adresar ve kterem se profil opravdu nachazi?

   $Global:ProfileDir = $(
        $line = $MyInvocation.Line
        
        write-debug "invocation line = $line"
    
        if($line -match "^\.?\s*['|`"]?(.*)['|`"]?\s*;?") {
            (split-path ($matches[1].Replace(':\\', ':\')))  
        }
        else {
            (split-path $Profile)
        }
    )
    
    $Global:Profile = (join-path $ProfileDir 'Profile.ps1')

Posted 05 prosince 06 04:00 by jachymko | 1 Comments   
Filed under ,
Vyvojar.cz na prodej!