Pokazywanie postów oznaczonych etykietą productivity. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą productivity. Pokaż wszystkie posty

sobota, 8 sierpnia 2015

Pixar workplace


Uważam, że Pixar jest bardzo produktywną firmą, gdzie bardzo zdolni i kreatywni pracownicy mogą realizować piękne projekty. Zastanawiam się czy prace Pixar'a są takie dobre z powodu bardzo uzdolnionych ludzi czy z powodu stworzenia miejsca pracy (środowiska współpracy) dzięki którym pracownicy są bardziej kreatywni.




niedziela, 12 lipca 2015

Zapytanie w jednej linijce w PS

Mam dla Ciebie szybki trick z PS.
Czasami muszę wysłać zapytanie w SQL w jednej linijce, ale w edytorze mam w wielu linijkach ( dla przejrzystości).
Poniżej jest template jak łatwo można napisać konwerter tekstu wielolinijkowego na tekst jednolinijkowy.

@"
     ...       
                
"@  -replace "`n|`r|\s+", " " | clip 
​

Przykład z SQLem wygląda tak:
@"
   SELECT 
       col1,
       col2,
       col3,
   FROM myTable
   Where 1=1
   Order by col1
                    
                
"@  -replace "`n|`r|\s+", " " | clip 
​

W tajemnicy powiem Ci, że możesz zastosować ten template nie tylko do SQL, ale również do innych języków np. do PowerShella :)

poniedziałek, 28 lipca 2014

Produktywne makra Visual Studio

Chcę Ci przedstawić 2 makra, które pomagają mi w pisaniu kodu. Pierwsze makro dodaje nawiasy okrągłe do zaznaczonego tekstu w edytorze. Super się sprawdza makro dla kodu w PowerShell czy dla FSharp. Poniższy kod wystarczy zapisać w makrze VS:
Public Module BracketIt
    Public Sub AddBrackets()
        Dim s As Object = DTE.ActiveWindow.Selection()
        If s.Text.StartsWith("(") And s.Text.EndsWith(")") Then
            s.Text = s.Text.Substring(1, s.Text.Length - 2)
        Else
            s.Text = "(" + s.Text + ")"
        End If
    End Sub
End Module
Skrótem klawiszowym do wywołania tego makra mam ustawione na:
Shift+CTRL+A, Shift+CTRL+B,
Równie dobrze można było dodać nawiasy ostrokątne do edycji plików xml.
Drugim makrem jest asercja sprawdzająca czy wartość jest nullem:
Public Module AddAssert
    Public Sub IsNotNull()
        Dim s As Object = DTE.ActiveWindow.Selection()
        Dim assertStr As String = "Assert.IsNotNull"

        If s.Text.Length > 0 Then
            s.Text = assertStr + "(" + s.Text + ")"
        Else
            s.Text = assertStr
        End If
    End Sub
End Module
A skrótem klawiszowym jest:
Shift+CTRL+A, Shift+CTRL+A
Te 2 makra u mnie się sprawdzają. Jeśli masz swój pomysł na makro to podziel się nim.

sobota, 19 lipca 2014

Reinstalacja pakietów nuget

Pewnie miałeś taką potrzebę reinstalacji pakietu nuget z poziomu Visual Studio. Domyślnie, nuget nie ma możliwości reinstalacji pakietu w jednej komendzie. Poniżej zamieszczam skrypt do wykonania tego zadania:
function Reinstall-Package {
    param(
        [Parameter(Mandatory = $true)]
        [string]
        $Id,

        [Parameter(Mandatory = $true)]
        [string]
        $Version,

        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string]
        $ProjectName,

        [switch]
        $Force
    )

    if (-not $ProjectName) {
        $ProjectName = (get-project).ProjectName
    }
    Uninstall-Package -ProjectName $ProjectName -Id $Id -Force:$Force
    Install-Package -ProjectName $ProjectName -Id $Id -Version $Version
}

Przykład wywołania dla reinstalacji danego pakietu dla wszystkich projektów w solucji jest poniżej:
Get-Project -All |
     ?{ $_ | Get-Package | ?{ $_.Id -eq 'bla.bla.bla' } } |
         %{ $_ | Reinstall-Package -Id 'bla.bla.bla' -version 1.0.0 -Force }

Nie będziesz mógł załadować modułów, więc będziesz musiał wywołać skrypt Reinstall-Package z nugetowej konsoli lub możesz dodać tą funkcję do pliku z profilem:
notepad $Profile​

niedziela, 6 lipca 2014

Sprawdzanie plików z datą

Jeżeli pracowałeś z źródłem danych w formie plików tworzonych każdego dnia, to za pewne miałeś problem ze sprawdzeniem czy są wszystkie pliki. Przesyłam proste skrypty sprawdzające takie pliki.
Na początku potrzebujemy funkcję do iteracji po dacie:
function Iterate-Date
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True,Position=1)]
        [ValidateNotNull()]
        [DateTime]
        $startDate
        , 
        [Parameter(Mandatory=$True,Position=2)]
        [ValidateNotNull()]
        [DateTime]
        $endDate
    )

    for($i = $startDate; $i -le $endDate; $i = $i.AddDays(1))
    {
        $i
    }
}
Potrzebna będzie funkcja sprawdzająca czy istnieje nazwa pliku z podanym patternem:
function Test-FileName    
{
    param(
        [string]$path='.'
    )

    process{
        $filter= $_
        $items = gci -Path $path -Filter $filter 

        new-object PSObject | Add-Member -MemberType NoteProperty -Name Filter -Value $filter -PassThru | 
        Add-Member -MemberType NoteProperty -Name Items -Value $items -PassThru |
        Add-Member -MemberType NoteProperty -Name Contains -Value ([bool]$items) -PassThru
    }
}
Samo sprawdzanie czy istnieje plik z patternem yyyy-MM-dd* jest poniżej:
Iterate-Date -startDate ([DateTime]("2005-02-13")) ([DateTime]("2014-06-16")) | 
%{ $_.ToString('yyyy-MM-dd') + "*"} | group | %{$_.name} |
Test-FileName |
? {-not $_.Contains}
Aby uprościć powyższe wywołanie to możemy zamienić group za pomocą poniższej funkcji:
function Get-KeyGroupObject
{
    param(
        [string]
        $keyPropName = 'name'
    )
    #in variable  $input (enumerator type) we have all items
    $Input | group | %{$_.$keyPropName​} 
}
A sprawdzanie wygląda następująco:
Iterate-Date -startDate ([DateTime]("2005-02-13")) ([DateTime]("2014-06-16")) | 
%{ $_.ToString('yyyy') + "*"} | Get-KeyGroupObject |
Test-FileName |
? {-not $_.Contains}

piątek, 28 lutego 2014

Generowanie start.bat dla projektu w VS

Czy kiedykolwiek musiałeś uruchomić aplikację z linii poleceń, która miała tak dużo linijek z argumentami, że nie mieściła się w oknie cmd? Ja miałe taką przyjemność i ten post jest właśnie o tym jak rozwiązać taki problem. Problem można rozwiązać za pomocą programu wsadowego (na ogół nazywam go start.bat). W nim zawarte jest polecenie startujące aplikację z argumentami. Aby debugować taką aplikację z poziomy VS to należy dodać parametry do właściwości programu. Poniżej są przedstawione 2 argumenty:
Napisałem skrypt w PS, aby wygenerować start.bat, który będzie mógł być wystartowany z tymi argumentami:
function New-StartBat
{
    param(
        [string] $csprojFilePath,
        [string] $outputDir = "." 
    )

    $userFileExtension = ".user"
    $startBatFileName = "start.bat"

    if(!(test-path $csprojFilePath))
    {
        throw "Wrong path to csproj file: $csprojFilePath"
    }

    [xml]$csprojContent = gc $csprojFilePath 
    [string]$outputType = ([string]$csprojContent.Project.PropertyGroup.OutputType)
               .Trim();

    if( -not($outputType -match  "Exe"))
    {
        throw "Output type is not exe"
    } 

    $assemblyName = ([string]$csprojContent.Project.PropertyGroup.AssemblyName)
                  .Trim()
    $startbarContent = "start /B $assemblyName.$outputType"
    $userFile = $csprojFilePath + $userFileExtension

    if(!(test-path $userFile))
    {
        Write-host "No user file for $csprojFilePath"
        $outputConditionStartBat  = join-path  $outputDir  $startBatFileName
        Write-Host "Genereting start.bat. Output is  $outputConditionStartBat"
        
        $startbarContent |
             out-file  $outputConditionStartBat  -Encoding ascii
    }
    else 
    {
        #region For each condition in user file
        [xml]$userFileContent = gc $userFile
        $userCondition = $userFileContent.Project.PropertyGroup.Condition

        $csProjConditions = $csprojContent.Project.PropertyGroup.Condition
        foreach($csprojCondition in $csProjConditions)
        {
            if($csprojCondition -eq $null)
            {
                continue;
            }

            [string]$conditionString =  ([string]$csprojCondition)
                                  .Trim()


            $indexOfequals = $conditionString.LastIndexOf("==")+2;
            if($indexOfequals -gt 2)
            {
                $conditionSimpleString = $conditionString
                     .Substring($indexOfequals)
                     .Trim()
                     .Replace("'","")
                     .Replace("|","_")

                if($contains =  $userCondition -contains $conditionString)
                {
                   $propertyGroup =  $userFileContent.Project.PropertyGroup | 
                                ?{$_.Condition -eq $conditionString }

                   $startArguments = $propertyGroup.StartArguments

                   $startBatContentWithArgs = $startbarContent+ " " + $startArguments 
           
                   $outputConditionStartBat  = join-path  $outputDir  ($conditionSimpleString + "_" +$startBatFileName) 

                   Write-Host "Genereting start.bat for $conditionSimpleString. Output file is $outputConditionStartBat"

                   $startBatContentWithArgs |
                    out-file  $outputConditionStartBat  -Encoding ascii
                }
            }

        }
        #endregion
    }
}
Dla różnej konfiguracji (Platform Configuration) możemy mieć różne parametry. Wygenerowany start.bat możemy uzyskać poprzez wywołanie polecenia:
New-StartBat -csprojFilePath "SuperProjectName.csproj" -outputDir ".\bin\Debug"

niedziela, 16 lutego 2014

Sprawdzanie sln'a

Często dostaje się błąd solucji z wiadomością:
"Error MSB4025: The project file could not be loaded. Data at the root level is invalid. Line 2, position 1."

Jest to błąd przy kompilowaniu solucji Visual Studio. Jest to problem z plikiem sln, najprawdopodobniej jest on związany z mergowaniem z innego brancha. Nie może zależ guid projektu lub guid jest z duplikowany. Aby sprawdzić czy wszystko jest ok, wystarczy uruchomić skrypt sprawdzający identyfikatory projektów:

function Test-Sln
{
    Param
    (
        [string] $slnPath
    )
    Write-Host "Testing sln in $slnPath"
    if(! (Test-Path($slnPath)))
    {
        throw "No file for $slnPath"
    }
    else
    {
        $slnContent = gc $slnPath
        $regex_id = '(\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\})'
        $regex_id_proj = '(\"{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}")'
        $matches_id =  [regex]::Matches($slnContent,$regex_id)
        $matches_id_proj =  [regex]::Matches($slnContent,$regex_id_proj)
        $dict_id =   Count-List $matches_id 
        $dict_id_proj = Count-List $matches_id_proj
        $returnValue = $true
        $keyChecked = 0
        $dict_id.Keys | foreach {
          $key=  $_
          $count = $dict_id[$key]
          $key_proj = '"' +  $key + '"'

           if( $dict_id_proj.Keys -contains $key_proj)
           {
                $count_proj = $dict_id_proj[$key_proj]
                if(($count -ne $count_proj) -and ($count_proj -gt 1))
                {
                     Write-Error "Wrong amount of reference for id $key. $count refers to $count_proj projects"
                     $returnValue=$false
                } 
                else
                {
                    Write-Host "Project with id $key is ok"
                }
           }
           else
           {
                Write-Error "Problem on id $key. There are $count refers in sln"
                $returnValue=$false
           }
           $keyChecked+=1
        }
        Write-host "Checked $keyChecked projects"
        return $returnValue
    }
}

Do tego potrzebujemy funkcję zliczającą ilość elementów w liście:
function Count-List ($List) #not explicitly list type 
{
$dic = @{}
$List| Foreach {
$id = $_.ToString()
    if($dic.ContainsKey($id))
    {
      $counter =  $dic.Get_Item($id);
      $counter +=1
      $dic.Set_Item($id,$counter);
    }
    else
    {
      $dic.Add($id,1)
    }
}
return $dic
}

Przykład wywołania jest poniżej:
if(!(Test-Sln "SuperSolution.sln"))
{
   throw "Errors in sln file" 
}

sobota, 15 lutego 2014

Skróty klawiszowe do VS

Jak wiadomo skróty klawiszowe są bardzo przydatne bo polepszają naszą produktywność, więc dobrze jest mieć skróty dopasowane do własnych potrzeb. Z indywidualnymi skrótami klawiszowymi jest jeden problem - osoba, która nie zna twoich skrótów może mieć problemy z obsługą środowiska programistycznego, już nie mówiąc o takim dziwnym tworze jak Ping-Pong Pair Programming. Ja mam skróty dopasowane do siebie i osoby na moim komputerze nie wiedzą jak ja mogę w ogóle kodować :)

Poniżej jest tabelka ze skrótami. Wywołanie polecenia składa się z kombinacji skrótów. Pierwszy skrót oznacza grupę, a drugi skrót już konkretne polecenie. Jeżeli chcesz odpalić polecenie debugowania to korzystasz z grupy RUN (CTRL + R) i polecenie Debug.Start (CTRL + D). Jeżeli bez chcesz uruchomić bez debagowania to pod tej samej grupie jest polecenie Debug.StartWithoutDebugging (CTRL + SHIFT + D).
Niektóre skróty już coś oznaczają (CTRL + F czy CTRL + A), więc musiałem dołożyć dodatkowy klawisz.



Plik z ustawieniami importu w Visual Studio jest poniżej:


Moje skróty ewoluują, Wcześniej miałem skrót do zen codingu, czy do GhostDoc'a. Czasami skróty są zależne od projektu.

niedziela, 19 stycznia 2014

Troszkę więcej niż VS Clean za pomocą PS

Komenda Clean w Visual Studio jest do czyszczenia zawartości ostatnio kompilowanego projektu. Nie oznacza to usunięcie całej zawartości folderów bin lub obj (lub subfolderów Debug/Releas), ale usunięcie tylko execów, dllki itp plików. Jest to problem kiedy chcemy mieć pewność, że wszystko zostało wyczyszczone lub kiedy musimy co jakiś czas archiwizować buildy. Nie wiem czy jest taka opcja w Visual Studio, aby za pomocą jednego polecenia dało się usunąć całą zawartość folderów bin i obj.

Standardowo musiałem ręcznie usuwać zawartość tych katalogów, ale pomyślałem sobie czy nie lepiej jest napisać skrypt w PowerShell, który mógłby tą czynność wykonywać za mnie.
function Remove-CsprojBuildFiles
{
    param(
    [string]$dirPath = "."
    )

    $buildDirName = "bin","obj"
    
    Write-Host "Deleting all `"$buildDirName`" dirs from $dirPath"

    $dirsThatAreContainers = get-childitem  $dirPath -Recurse | 
        ? { $_.PSIsContainer}  

     $dirsThatAreBuildNames =    $dirsThatAreContainers |
        ? {$buildDirName -contains $_.Name  }

        $dirsWhichContainsCsprojFile = $dirsThatAreBuildNames |
        ? { ((gci  -path $_.Parent.FullName) |?{$_.FullName.Contains("csproj") } | Test-Any )}


       $dirRemovedCounter= 0
       foreach($dir in $dirsWhichContainsCsprojFile)
       {
            $dirFullPath  = $dir.FullName
            if(Test-path $dirFullPath )
            {
                Remove-Item -Path $dirFullPath -Recurse
                $dirRemovedCounter+=1
            }
            else 
            {
                Write-Error "Dir $dirFullPath not exists"
            }
       }

    Write-Host "$dirRemovedCounter dirs removed from $dirPath"
}

Przydatna będzie funkcja test-any (taki Any z Linq), którą zapożyczyłem stąd.
function Test-Any() {
    begin {
        $any = $false
    }
    process {
        $any = $true
    }
    end {
        $any
    }
}

Wywołanie polecenie do usuwania katalogów jest następująca:
Remove-CsprojBuildFiles "C:\code\'folder_to_solution'"

sobota, 4 stycznia 2014

7 nawyków

Chciałbym przedstawić Ci książkę, która odmieniła mój światopogląd i spowodowała, że stałem się produktywniejszy oraz szczęśliwy. Ta książka to "7 nawyków skutecznego działania" napisana przez Stephena R Coveygo. Nie jestem w stanie opisać jak dużo zawdzięczam tej książce, ale uważam ją za nr 1 wśród książek o rozwoju osobistym. Jest to ważniejsza książka niż GTD Davida Allena, kolekcji książek i audiobooków Brian Tracy, poradniki Timotha Ferrissa, książki o przyjaciołach Dalea Carnegiego. Nie wiem czy książka Napoleona Hilla nie była by ważniejsza niż 7 nawyków, ale na dzień dzisiejszy książka Coveya jest nr 1.


Dlaczego ta książka jest ważna dla mnie. Z paru powodów:
- pozwoliła mi rozwijać charakter, nie osobowość
- udowadniła, że doskonałość to nie jest kwestia talentu, ale nawyków
- wytłumaczyła, że jestem wolny, bo nie jest ważne co się wydarzyło, ale w jaki sposób reagujesz na różne sytuacje
- żyj zgodnie z rozsądnymi zasadami takimi jak uczciwość, godność, jakość, cierpliwość, wytrwałość, opiekuńczy oraz odwaga
- cele zawsze powinny mieć dla mnie wartość
- uświadomiła mi, że powinienem określić swoje osobiste cele
- zastanowiłem się co ludzie powiedzą o mnie, kiedyś ... trakcie mojego pogrzebu
- powinienem co jakiś czas zastanawiać się nad moim postępowaniem i co jakiś czas powinienem naostrzyć piłę

Książka była publikowana w latach 90 i stała się najbardziej znaną książką Coveyego. W tej książce autor zawarł najważniejsze 7 nawyki, są nimi:
1) Przejmij inicjatywę i bądź proaktywny
2) Bądź skoncentrowany na celach i myśl o końcowym rezultacie
3) Ustalaj priorytety
4) Działaj zgodnie z zasadą Win/Win
5) W komunikacji staraj się zrozumieć innych, a później abyś ty był zrozumiany.
6) Współpracuj z innymi (synergia)
7) Zastanów się nad swoimi błędami i staraj się je naprawić (Sharp the Saw)

wtorek, 12 listopada 2013

Automatyczna aktualizacja SVN

Chcę Ci przedstawić jeden z najbardziej używanych przeze mnie skryptów ( przynajmniej 2 razy w ciągu dnia m.in jak zaczynam prace przy komputerze ) - skrypcik do aktualizacji kodu źródłowego w SVN napisany w PowerShell. Skorzystamy z programu TortoiseProc, który może wykonać polecenia z linii komend:
function Invoke-Svn{
Param(
     
     [string] $command = "properties",
     [string] $path = ((get-location).Path)

)
$svnPath = "C:\Program Files\TortoiseSVN\bin\"
$appSvn = $svnPath+ "svn.exe" 
& $appSvn info


$appTortoise = $svnPath + "TortoiseProc.exe"
$commandLine = '/command:' + $command + ' /notempfile /path:"' + $path + '"'
& $appTortoise $commandLine

}
Aby wykonać aktualizację kodu źródłowego to wystarczy wywołać komendę update:
function Update-Svn{
Param(
     [string] $path = ((get-location).Path)
     )
     
Invoke-Svn -path $path -command "update"
}
Więcej komend można znaleźć na stronie automatyzacji TortoiseSVN. Możemy sprawdzić rejestr svn za pomocą komendy log:
function Log-Svn{
Param(
     [string] $path = ((get-location).Path)
     )
     
Invoke-Svn -path $path -command "log"
}
Aby zaktualizować kilka projektów wystarczy wykonać:
Write-Host "Updating"
Update-Svn -path C:\Code\Path1\Project1
Update-Svn -path C:\Code\Path2\Project2
Update-Svn -path C:\Code\Path3\Project3
Update-Svn -path C:\Code\Path4\Project4
Wywołanie takiego skryptu za pomocą pliku bat jest podane poniżej:
powershell -File "C:\Scripts\Invoke-Svn.ps1"



niedziela, 31 marca 2013

Get-Date w PowerShell

Get-Date jest poleceniem wyświetlającym aktualną date i godzinę. Zamiast Get-Date możesz użyć [DateTime]::Now. Przy okazji muszę się przyznać, że zawsze mam problemy z formatem datetime dla Get-Date.

Co ciekawego można zrobić z Get-Date. Na przykład możesz sprawdzić jakie procesy działają dłużej niż dany okres czasu. Stwórzmy zmienną $1HourFromNow, która będzie trzymała date przed 1 godziną i wybierzmy wszystkie procesy, które jeszcze działają.
PS>$1HourFromNow = (get-date).AddHours(-1)
PS>Get-Process |where {$_.StartTime -ge $1HourFromNow }

Innym ciekawym skryptem jest wybranie wszystkich plików z danego katalogu, które w przeciągu ostatniego dnia był modyfikowane.
PS> $1DayFromNow = [DateTime]::Now.AddDays(-1)
PS>gci -recurse | where {$1DayFromNow -le $_.LastWriteTime }

środa, 6 marca 2013

Zmiana rozmiaru zdjęć za pomocą PowerShell

Czy masz może bardzo dużo zdjęć w jednym katalogu, musisz zmienić rozmiar tych zdjęć i za każdym razem uruchamiasz program graficzny, aby zmienić rozmiar zdjęcia??
Ja akurat tak miałem wiele razy :)
Jeśli coś powtarzasz wielokrotnie to postaraj się zautomatyzować tą czynność. Poniżej jest skrypt, który zmienia rozmiar zdjęcia.
function Resize-Image {
[CmdletBinding()]
Param(
     [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
     [System.io.FileInfo] $filepath,
     [int] $width=100,
     [int] $height=100,
     [string]$prefix="rs_"
)

PROCESS{
        $filePathFullName = $filepath.FullName
        if( Test-Path $filePathFullName)
        {
            $destName = $prefix+$filepath.name
            $destPath = Join-Path -path  $filepath.DirectoryName $destName
            
            import-bitmap $filePathFullName | resize-bitmap -Width $width -Height $height | export-bitmap  -Path $destPath 
            Write-Host "Resizing into $destPath"
                   
        }
        else {
            Write-Host "Path not found."
            }
        }
}
Przykład użycia jest przedstawiony poniżej:
gci -filter *.bmp |  Resize-Image 

Ten skrypt może u ciebie nie działać, bo prawdopodobnie nie masz PowerShell Community Extensions. Skrypt korzysta z poleceń import-bitmap,resize-bitmap i export-bitmap, które znajdują się w PSCX. Aby zainstalować PSCX, to wystarczy pobrać paczkę ze strony internetowej. Rozpakować do jednej z lokalizacji zawartej w zmiennej $Env:PSModulePath. A na końcu wywołać poniższy skrypt:
Import-Module Pscx -arg ~\PSCX\Pscx.UserPreferences.ps1
Get-Module

Mam nadzieję, że skrypt się przyda :)

wtorek, 5 marca 2013

Problemy z produktywnością


Znasz może ten żart:

Są rodzaje seksu: więzienny, studencki, przedszkolny i filozoficzny.
Więzienny: Jest gdzie, ale nie ma z kim,
Studencki: Jest z kim, ale nie ma gdzie.
Przedszkolny: Jest gdzie, jest z kim, ale nie ma czym.
Filozoficzny: Jest gdzie, jest z kim, ale czy jest sens...?



Wydaje mi się, że tak sam podział może być z problemami produktywności.

Przedszkolny: nie ma zadań, nie wiadomo jak, nie ma narzędzi.
Studencki: są zadania, nie ma wiedzy(jeszcze nie), są narzędzia.
Więzienny: są zadania, jest wiedza, nie ma narzędzi.
Filozoficzny: są zadania, jest wiedza, są narzędzia, ale jaki to ma sens?



Jeżeli jesteś typem przedszkolaka to nie musisz dbać o produktywność bo nie masz zadań. I z tego też powodu wszyscy ci zazdroszczą.

Jeżeli jesteś typem studenta to już powinieneś dbać o produktywność bo są zadania. Pomimo tego, że masz dostęp do narzędzi nie wykorzystujesz je. Mi bardzo brakuje dostępu do DreamSparka. Stamtąd można było pobrać bardzo dużą ilość programów za darmo. Doceniłem to dopiero po studiach.

Jeżeli jesteś typem więźnia to masz zadania i wiedzę, które mogą zwiększyć produktywność. Ale nie masz wymaganych narzędzi. Z taką sytuacją może się spotkać, gdy pracujesz w firmie, gdzie nie ma dostępu do potrzebnych narzędzi.

Jeżeli jesteś filozofem. to masz zadania do zrobienia, potrzebną wiedzę, wymagane narzędzia, ale nie obchodzi cię czy jesteś produktywny. Masz swoje przyzwyczajenia, które nie chcesz zmieniać.


niedziela, 13 stycznia 2013

Czyszczenie kolejek MSMQ w PowerShell

Parę razy musiałem wyczyścić kolejki w MSQM. Standardowe ręcznie usuwanie i tworzenie kolejkę jest bardzo pracochłonne. Po paru takich powtórzonych czynnościach, postanowiłem napisać skrypt w PS. Skrypt wykorzystuje bibliotekę System.Messaging.


[Reflection.Assembly]::LoadWithPartialName("System.Messaging")

$michineName = $env:COMPUTERNAME

$queueNames =  [System.Messaging.MessageQueue]::GetPrivateQueuesByMachine($michineName) | 
% {".\" + $_.QueueName} 

$queueNames  = $queueNames  |  
?{ $_ -like "*my.special*"}

$queueNames | 
foreach {
 [System.Messaging.MessageQueue]::Delete($_);
 [System.Messaging.MessageQueue]::Create($_, [bool]1) ;
 }

Krótki opis co robi skrypt:
1. Ładuje referencje do biblioteki Messaging
2. Pobiera nazwę komputera
3. Pobiera listę prywatnych kolejek i zwraca ich nazwy
4. Wybiera kolejki mające w nazwie "my.special"
5. Iteruje po wszystkich znalezionych kolejkach
6. Usuwa kolejkę
7. Tworzy transakcyjną kolejkę

Próbowałem zmienić proces usuwania i dodawania tej samej kolejki na pojedynczy proces czyszczenia kolejki, ale natrafiałem na pewne ograniczenia :/ Nie miałem wystarczającej ilości czasu, aby zamienić ten skrypt. Gdybyś znal inne sposoby na czyszczenie kolejek MSMQ to napisz w komentarzu.

sobota, 5 stycznia 2013

Porównanie 2 repozytoriów

Czy natrafiłeś na taka sytuacje, ze musiałeś porównać 2 repozytoria??
Mi parę razy się tak zdarzyło, a dokładnie musiałem porównać 2 wersje tego samego projektu. Przygotowałem skrypt, który pobiera z pierwszego repozytorium wszystkie pliki .cs, .sln i .user i porównuje je z plikiem w drugim repozytorium. Jako aplikacja do porównania plików wybrałem KDiff3. Poniżej przedstawiam skrypt w PowerShell:
function Compare-Repo {

Param(
     
     [string] $firstlocation = "C:\sourcecodes\ProjectX_ver1",
     [string] $secondLocation = "C:\sourcecodes\ProjectX_ver2",
     [int] $takeFileNumber =10
)


$fileExtension = @(".cs", ".sln", ".user")
$appToCompare = "C:\Programs\KDiff3\kdiff3.exe" 
#



$itemsFirstlocation  = gci -recurse  -Path $firstlocation  |
 where { ! $_.PSIsContainer -and $fileExtension -contains $_.Extension.ToLower()}

$itemsFirstlocation = $itemsFirstlocation | 
select -first $takeFileNumber

$itemsFirstlocation | foreach {

        $fileEnding = $_.FullName.Replace($firstlocation,"");
        $firstItem = $_.FullName;

        $secondItem = $secondLocation  + $fileEnding ;
        if(Test-Path($secondItem))
        {
            Write-Host "Comparing file $firstItem with $secondItem";

            & $appToCompare $firstItem $secondItem 
            #Run compare app
        }
    }
}

Więcej o KDiff3 można poczytać w obszernej dokumentacji.

niedziela, 30 grudnia 2012

Konwersja z bmp na jpeg w PowerShell

Kiedy masz dużo plików graficznych w bmp, warto jest zastanowić się nad zmiana formatu na jpeg. Pliki mają mniejszy rozmiar, a nie tracą tak bardzo na kompresji. Napisałem skrypt do konwertowania plików z jednego formatu na drugi. Wystarczy w kodzie wyselekcjonować pliki, które są bmp i w potoku wpisać nazwę funkcji:
gci -filter *.bmp | Convert-Jpeg

Poniżej cała implementacja funkcji zamieniająca bmp na jpeg:
[Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null

function Convert-Jpeg {
[CmdletBinding()]
Param(
     [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
     [System.io.FileInfo] $filepath
)

BEGIN {
     Write-Host "Converting Bitmaps to Jpegs" 
     $fileConvertedCounter= 0
}

PROCESS{
        $filePathFullName = $filepath.FullName
        if( Test-Path $filePathFullName)
        {
            $image  = [System.Drawing.Image]::FromFile($filepath.FullName)
            $bitmap = new-object System.Drawing.Bitmap($image)
            $newFileName = ($filePathFullName -replace '([^.]).bmp','$1') + ".jpg"
            $bitmap.Save($newFileName, ([system.drawing.imaging.imageformat]::jpeg))
            $fileConvertedCounter++
            Write-Host "Converted $filePathFullName into $newFileName"
            $bitmap.Dispose()
            $image.Dispose()        
        }else {
            Write-Host "Path not found."
        }
}

END{
    Write-Host "It was $fileConvertedCounter converted files" 
}

}

sobota, 29 grudnia 2012

Kopiowania kodu bez svn

Jeżeli masz kod źródłowy, który jest podpięty pod system kontroli wersji (svn) to ciężko jest skopiować tylko sam kod bez plików do kontroli wersji. Za pomocą PowerShell można to osiągnąć znacznie szybciej niż ręcznie wykonując kopiowanie .
function Copy-File-Exclude-Svn {
Param(
    [string] $sourceLocation=".",
    [string] $destinationClocation=".\No_SVN"
)
$files = gci -force  -exclude *.svn-base,".svn",".gitignore"  $sourceLocation  | ? {  $_.PSIsContainer -and $_.Length -lt 230 } | gci -recurse

$files | foreach {
        $fileEnding = $_.FullName.Replace($sourceLocation, "");
        $firstItem = $_.FullName;
        $secondItem = $destinationClocation  + $fileEnding ;
        Write-Host "Copy from $firstItem to $secondItem";
        Copy-Item $firstItem $secondItem;
    }
}


Wywołanie kopiowania plików wygląda następująco:
Copy-File-Exclude-Svn 
-sourceLocation "C:\Source\Project1" 
-destinationClocation ""C:\Source\Project1_without_svn"


środa, 12 grudnia 2012

Problem rozwiązany przez czas

Wszyscy mówią, aby 'nie odkładać rozwiązania problemu na później', 'to co masz zrobić jutro, spróbuj zrobić dzisiaj' itd. Ja sam nie jestem specialistą od prokrastynacji, ale mam swoją metodę na rozwiązywanie problemów, a dokładnie na ich odkładanie. Nie staraj się od razu rozwiązać jakiś problem, ale ustal czy ten problem jest nieszkodliwy i niepilny. Mogą być problemy, które są nieszkodliwe i pilne (np. spóźnienie się na zajęcia, rozmowa telefoniczna z trudnym klientem), ale również mogą być szkodliwe i niepilne (np. problem w relacjach ze znajomymi, odkładanie na emeryturę). Jeżeli twój problem jest nieszkodliwy i niepilny to ustal jego ramy czasowe. Ustal do kiedy chcesz rozwiązać ten problem. Pamiętaj o tym, że każde rozwiązanie potrzebuje trochę czasu na realizację. Zapisz sobie ten problem i po jakimś czasie spróbuj powrócić do niego. Takie odkładanie problemów może spowodować, że te problemy same się rozwiążą. Czasami nie warto zamęczać się rozważaniami nad rozwiązaniem problemu. Czasami jest tak, że dany problem zostanie rozwiązany przez kogoś innego. Może się zdarzyć, że ten problem zostanie zastąpiony szkodliwszym problemem, a wtedy ten wcześniejszy przestanie istnieć.

Klasyfikowanie problemów ze względu na szkodliwość i pilność ma dużo wspólnego z macierzą Eisenhowera. Macierz(matryca) Eisenhower'a (Eisenhower matrix) można też nazywać Systemem Eisenhower’a (Eisenhower system), Siatką Eisenhower’a (Eisenhower grid), Polami Eisenhower’a (Eisenhower boxes) lub Kwadrat Eisenhower’a (Eisenhower square). Najważniejszą cechą macierzy jest pomoc w ustalaniu priorytetów w działaniach. Każdy cel, zadanie i czynność można nanieść na odpowiednią ćwiartkę.



Interpretacja macierzy jest następująca:
Ćwiartka I: rzeczy ważne i również pilne, które powinniśmy zrealizować sami lub delegować dla innych ( w natłoku innych spraw). W tej ćwiartce to zazwyczaj sytuacje nagłe, trudne do przewidzenia, lub skutki zaniedbania i niewykonywania regularnej pracy oraz sytuacje kryzysowe.

Ćwiartka II: rzeczy ważne, ale niepilne, które możemy rozłożyć w czasie lub wykonywać regularnie. Czynności, które mogłyby się znaleźć w tej części to: rekreacja, szkolenia, ćwiczenia fizyczne, przygotowania do projektu, regularna praca nad sobą.

Ćwiartka III: rzeczy pilne, jednak mało ważne – powinniśmy wykonać lub zlecić w drugiej kolejności, zaraz po zadaniach z części A. Czynności z tego obszaru nie są istotne lecz wymagają jak najszybszego wykonania, możemy do nich zaliczyć np. uregulowanie rachunków, rozmowa telefoniczna lub wizytę u znajomych

Ćwiartka IV: rzeczy mało ważne i mało pilne – po prostu możesz te rzeczy olewać. Najlepszym miejscem dla czynności z tej części jest kosz. Nie są one dla nas istotne. Zazwyczaj to one są tzw. pożeraczami czasu. Przykłady tej czynności to bezcelowe patrzenie w TV podczas nudnego programu. Zadania z tej ćwiartki można bez problemu przesunąć na dalszy plan. Odkładanie problemu nieszkodliwego i niepilnego należy do 4 ćwiartki.

Oczywiście trudno jest nakreślić uniwersalny schemat postępowania dla wszystkich ponieważ, wszystko jest uzależnione od naszych prywatnych preferencji.

Jak przyspieszyć kodowanie cz.4 (testy sparametryzowane)

To, co mi się najbardziej podoba w NUnit to 'sparametryzowane testy'. Najlepiej na przykładzie będę mógł pokazać ci piękno tego rozwiązania. Dajmy na to, że mamy klasę z 'skomplikowaną' logiką.
public class Sum
{
 public int Value1 { get; set; }
 public int Value2 { get; set; }

 public int Result
 {
    get { return Value1 + Value2; }
 }
}
Klasa Sum w polu Result zwraca sumę pól Value1 i Value2. Użycie tej klasy wygląda następująco:
var sum =  new Sum { Value1 = value1, Value2 = value2 };
sum.Result;
Stwórzmy do niego test sprawdzający działanie przykładowych liczb, dodawanie elementu neutralnego (zero) oraz dodawanie liczby przeciwnej.
        [Test]
        public void It_should_return_sum_3()
        {
            int value1 = 1;
            int value2 = 2;
            var sum = new Sum { Value1 = value1, Value2 = value2 };
            Assert.AreEqual(3, sum.Result);
        }

        [Test]
        public void It_should_return_0_because_number_of_opposing()
        {
            int value1 = 1;
            int value2 = -1;
            var sum = new Sum { Value1 = value1, Value2 = value2 };
            Assert.AreEqual(0, sum.Result);
        }

        [Test]
        public void It_should_return_0_because_adding_neutral_nuber()
        {
            int value1 = 2;
            int value2 = 0;
            var sum = new Sum { Value1 = value1, Value2 = value2 };
            Assert.AreEqual(2, sum.Result);
        }
Mamy 3 metody, które testują 3 różne przypadki. Od razu widać, że kod się powtarza, więc chcemy zredukować powtarzający się kod w tych testach. Możemy zastosować atrybut TestCase. W tym atrybucie podajemy wartości obiektów z jakimi ma być wywołana metoda. Przykład jest poniżej:
        [TestCase(1, 2, 3)]
        [TestCase(2, 0, 2)]
        [TestCase(1, -1, 0, TestName = "Because number of opposing")]
        public void It_should_return_sum(int value1, int value2, int expected)
        {
            var sum = new Sum { Value1 = value1, Value2 = value2 };
            Assert.AreEqual(expected, sum.Result);
        }
Dokładnie to mi się najbardziej podoba w NUnit. Mamy przetestowane 3 różne przypadki użycia i napisało się tylko jedną metodę. W tej metodzie 2 pierwsze argumenty atrybutu są jako dane wejściowe naszej operacji, a 3 argument jest jako wynik tej operacji. Dla poszczególnych przypadków testowych (TestCase), można jeszcze określić nazwę testu, opis, jaki wyjątek ma być wyrzucony oraz jaka wartość ma być zwracana przez tą metody. Możemy wykorzystać ten ostatni parametr.

        [TestCase(1, 2, Result = 3)]
        [TestCase(1, -1, Result = 0, TestName = "It should return 0")]
        [TestCase(2, 0, Result = 2, TestName = "Adding zero")]
        public int It_should_return_sum2(int value1, int value2)
        {
            var sum = new Sum { Value1 = value1, Value2 = value2 };
            return sum.Result;
        }
Przekształcenie bardzo przypomina 'normalną' (bez aserci) metodę, ale z atrybutami. Mam diaboliczny pomysł. Parametr Result możemy dodać do normalnej metod statycznej. W taki sposób można mieć kod implementacyjny i testy w jednym projekcie - it's crazy.

    public class SumFactory
    {
        [TestCase(1, 2,  Result = 3)]
        [TestCase(1, -1, Result = 0, TestName = "It should return 0")]
        [TestCase(2, 0,  Result = 2, TestName = "Adding zero")]
        public int Sum(int value1, int value2)
        {
            return value1 + value2;
        }
    }
To jest pierwszy przykład jak możemy wykorzystać TestCase - drugi przykład jest dla TestFixture. Napiszmy generyczną klasę, która będzie dodać 2 zmienne:

    public class GenericSum<T>
    {
        public T Value1 { get; set; }
        public T Value2 { get; set; }

        public T SumValue
        {
            get { return (dynamic)Value1 + (dynamic)Value2; }
        }
    }
I chcielibyśmy przetestować dodawanie domyślnych wartości dla zmiennych typu int i double.
    [TestFixture(typeof(int))]
    [TestFixture(typeof(double))]
    public class GenericTestNUnit<T>
    {
        [Test]
        public void It_should_return_default_value()
        {
            var sum = new GenericSum<T> { Value1 = default(T), Value2 = default(T)};
            Assert.AreEqual(default(T), sum.SumValue);
        }
    }
Argument w atrybucie TestFixture odnosi się do typu T. Takie sparametryzowane testy mają zastosowanie w testowaniu klas dziedziczących.

    public abstract class AsBiOperation
    {
        public int Value1 { get; set; }
        public int Value2 { get; set; }
        public abstract int Result { get; }
    }
    public class SumOperation : AsBiOperation
    {
        public override int Result
        {
            get { return Value1 + Value2; }
        }
    }
    public class MultiplicationOperation : AsBiOperation
    {
        public override int Result
        {
            get { return Value1*Value2; }
        }
    }
Do stworzonej klasy abstrakcyjną i napiszemy test dla wszystkich klas dziedziczących po niej. Dodatkowo mamy możliwość wprowadzenia przykładowych wartości.

    [TestFixture(1,2,3,     TypeArgs = new[] { typeof(SumOperation)} )]
    [TestFixture(0, 0,0,    TypeArgs = new[] { typeof(SumOperation) })]
    [TestFixture(-1, 1, 0,  TypeArgs = new[] { typeof(SumOperation) })]

    [TestFixture(1, 0, 0,   TypeArgs = new[] { typeof(MultiplicationOperation) })]
    [TestFixture(1, 5, 5,   TypeArgs = new[] { typeof(MultiplicationOperation) })]
    [TestFixture(5, 5, 25,  TypeArgs = new[] { typeof(MultiplicationOperation) })]    
    public class AsBiOperationTests<T>
        where T:AsBiOperation, new()
    {
        T operation;
        int _value2;
        int _value1;
        int _result;

        public AsBiOperationTests(int value1, int value2, int result)
        {
            _result = result;
            _value1 = value1;
            _value2 = value2;
        }

        [SetUp]
        public void SetUp()
        {
            operation = new T();
        }


        [Test]
        public void It_should_calculate()
        {
            operation.Value1 = _value1;
            operation.Value2 = _value2;
            Assert.AreEqual(_result,operation.Result);
        }
        
    }

Testy sparametryzowane to fantastyczne rozwiązanie, aby mniej kodować, mieć większe pokrycie kodu i móc więcej przetestować przypadków. Bardzo żałuje, że w MSTest jeszcze nie ma takiego featura (chociaż nie bezpośrednio). Jednak mam nadzieję, że w bliskiej przyszłości coś się z tym zmieni. Oprócz NUnit'a sparametryzowane test są w MBUnit.