View all posts filed under 'General'

WeekOfMonth

Tuesday, 9. March 2010 19:05

Today I needed small function to determine what is the number of current week (usually referred as WeekOfMonth).

Code is very simple in fact:

Function Get-WeekOfMonth ([datetime]$Date = $(Get-Date)) {
	[int]$Day = $Date.Day
	Return [math]::Ceiling($Day / 7)
}

 

Martin

Category:General, PowerShell, Scripting, Windows PowerShell | Comment (0) | Author: Martin Zugec

Powershell coding style

Wednesday, 24. February 2010 10:41

I was reading very interesting post from Jeffrey Hicks called PowerShell Picasso today and I must say that I agree with him 99%.

If you know the way I script, then you have probably noticed that it is hybrid code between PowerShell and .NET. For example I don’t like ForEach-Object cmdlet – from my perspective, it makes code much LESS readable. I would compare it to question sentence in English and in Spanish. In Spanish, every question sentence begins with question mark (for example ¿Cómo estás?) and you immediately know it is going to be the question.

For same reason, I always use ForEach ($X in $Y) {…}. I find it much easier to undestand $X. than $_… If I have a quick peek at code, using $Service.Status immediately tells me what I need, while $_.Status requires me to read preceding code to understand what type of object is $_. Organizing code to blocks is my preferred method (while many Powershell guys organize code to sentences :) ).

Second side effect is that by using .NET syntax, people much quickly adopt the fact that Powershell is based on .NET object and is object-oriented language. Later on, these administrators can read and understand MSDN documentation or examples that are written in C#. To summarize it, my point is that for many people, Powershell can be used as entry point to .NET world (.NET for Administrators).

I fully agree with rest of the Jeffrey’s article. “Problem” as I see it is that most people use Posh in interactive mode – and there is huge difference in writing few functions for yourself and trying to build complex framework out of Powershell (just checked – my framework currently consists of almost 4000 files, even though it is based on modules). In case you don’t think about readability of your code, you will get lost when you will need to write the complex modules (thousands of lines).

Martin

Category:General, Gotcha, PowerShell, PowerShell News, Scripting, Windows PowerShell | Comment (0) | Author: Martin Zugec

Working with local administrator

Wednesday, 17. February 2010 21:52

When working with local administrator account, there are 3 possible tasks you usually want to accomplish:

1.) Change password

2.) Rename account

3.) Disable\Enable account

Below are snippets of Powershell code that can help you to achieve that. First line is always used to retrieve local account with RID 500 (built-in administrator account, no matter what is the name), rest than depends on what you want to achieve.

1.) Change password

<P>$LocalAdministrator = $(Get-WmiObject –Query ‘Select * from Win32_UserAccount
Where (LocalAccount="True" and SID like "%-500")’)</P>
<P>$AdminReference = [adsi]("WinNT://./" + $LocalAdministrator.Name + ", user")
$AdminReference.psbase.invoke("SetPassword", "new and shiny password")</P>

2.) Rename account

<P>$LocalAdministrator = $(Get-WmiObject –Query ‘Select * from Win32_UserAccount
Where (LocalAccount="True" and SID like "%-500")’)</P>
<P>$LocalAdministrator.Rename("LocalAdmin")</P>
<P>$LocalAdministrator.Put()</P>

3.) Disable\Enable account

<P>$LocalAdministrator = $(Get-WmiObject –Query ‘Select * from Win32_UserAccount
Where (LocalAccount="True" and SID like "%-500")’)</P>
<P>$LocalAdministrator.Disabled = $False</P>
<P>$LocalAdministrator.Put()</P>

Martin

Category:General, PowerShell | Comment (0) | Author: Martin Zugec

Zero Touch Installation with MDT 2010

Tuesday, 16. February 2010 10:59

Henk Hofs – known as the geek with an opinion ;-) – has posted a nice PowerShell script to achieve ZTI functionality with Microsoft Deployment Toolkit 2010: ZeroTouch for MDT 2010 without SCCM!

Category:General | Comment (0) | Author: Frank-Peter

Which countries are most interested in Powershell? Surprise :)

Wednesday, 10. February 2010 9:46

During my recent investigation, I wanted to be sure that Powershell is really getting adopted and that it grows every year…

You can either try to get some results from companies like Gartner, but I usually don’t trust them too much. For me, best resource is of course Google ;)

According to Google, we can see that interest in powershell is still growing:

Posh

I was also curious which countries are mostly interested in Powershell. Did you expect to see here U.S., UK, Germany or similar countries?

1. Russian federation

2. Norway

3. Czech republic :)

If you want to see report yourself, simply follow this link.

Martin Zugec

Category:General, Internet, PowerShell, PowerShell News | Comment (0) | Author: Martin Zugec

grep for PowerShell

Tuesday, 2. February 2010 23:07

Hello again. This time I will share a small function that resides in my PowerShell profile script: grep. What is grep? grep is a text search utility originally written for Unix. The command name is an abbreviation for “global regular expression print”. The original grep – and my PowerShell grep function as well – searches files for lines matching a given regular expression and displays the matches in standard output.

Here comes the ready for use function…

function grep (
    $File = $(throw "Empty value for the File parameter."),
    $Pattern = $(throw "Empty value for the Pattern parameter."),
    [switch]$Recurse
) {
    if ($Recurse) {
        $Files = @(Get-ChildItem $File -Recurse)
    } else {
        $Files = @(Get-ChildItem $File)
    }
    if ($Files.Count -eq 0) {
        Write-Host "File(s) not found - $File"; return $null
    }
    $Results = $Files | Select-String -Pattern $Pattern
    if (!$Results) {
        Write-Host "No matches found in $File"; return $null
    }
    $Results | Format-List FileName,LineNumber,Line
}

Actually the grep function simplifies the usage of a command line like below:

PS C:\> gci c:\windows\windowsupdate*.log | Select-String "2009-12" | fl FileName,LineNumber,Line

Using grep you just need to type this:

PS C:\> grep -File C:\Windows\WindowsUpdate*.log -Pattern "2009-12"

Ah, almost I forgot to mention that the Select-String cmdlet is PowerShell’s grep.

Category:General, PowerShell | Comments (1) | Author: Frank-Peter

Copy Con For PowerShell?

Wednesday, 27. January 2010 23:30

Hello again! This time I share a quick tip.

MS-DOS and cmd.exe shell power users remember for sure how easy it was to write a script (or any other text file) quickly from the command line without an editor. It was possible to copy the CON device (which stands for Console meaning keyboard/input and monitor/output as one device) to a file, for example COPY CON TEST.CMD. Once a COPY CON command has been invoked, it was possible to type whatever you want, even multiple lines were possible. When completed you could save the file and return to the prompt by pressing CTRL-Z (or F6) which would create ^Z (end of file) and then press Return.

In PowerShell there’s a similar approach as well but it doesn’t correspond one-to-one. The trick takes advantage of a single-quoted here-string to create a script:

PS C:\Users\Pit> @'
>> "Hello, $Env:USERNAME!"
>> "There are $((Get-ChildItem).Count) files and folders in this directory: $pwd"
>> '@ > .\test.ps1
>>
PS C:\Users\Pit> type .\test.ps1
"Hello, $Env:USERNAME!"
"There are $((Get-ChildItem).Count) files and folders in this directory: $pwd"
PS C:\Users\Pit>
PS C:\Users\Pit> .\test.ps1
Hello, Pit!
There are 15 files and folders in this directory: C:\Users\Pit
PS C:\Users\Pit>

Actually, Here-strings are used to embed more or less large text blocks inline in scripts. Here-strings start with “@” plus double- or single-quote followed by newline and end with newline, double- or single-quote followed by “@” .

Category:General, PowerShell | Comments (1) | Author: Frank-Peter

Low-Tech Encryption

Sunday, 10. January 2010 21:47

Hello again. This time I want to share a function to convert a plain-text string to an encoded string, ConvertTo-BlurredString, and a function to decode an encrypted string, ConvertFrom-BlurredString. The function names contain the wording “blurred” because my encryption method should be considered very, very basic. It is a real low-tech security solution. Please keep that in mind!

I wrote the algorithm a couple of years ago in order to save sensitive data like email addresses in HTML files or passwords in INI files in a more secure manner than in plain-text. At least the blurred string protects the data from reading out accidentally if a curious user is watching an admin at work.

Enough talk – here comes function #1, ConvertTo-BlurredString:

function ConvertTo-BlurredString {
    <#
    .SYNOPSIS
        Converts a plain-text string to a blurred string.
    .DESCRIPTION
        The ConvertTo-BlurredString function converts a plain-text string into
        a blurred string. It is used with ConvertFrom-BlurredString. The blurred
        string can be used in configuration files (.ini or .xml for example) in
        order to prevent unwanted readout by curious people.
        ConvertTo-BlurredString is a very basic security solution. Do not use it
        in high security scenarios.
    .EXAMPLE
        PS C:\> ConvertTo-BlurredString "Hello, World!"
        81:648:909:972:972:999:396:288:783:999:1026:972:900:297
        PS C:\>
    .EXAMPLE
        PS C:\> $blurred = "Hello, World!" | ConvertTo-BlurredString
        PS C:\> $blurred
        55696:16992:23836:25488:25488:26196:10384:7552:20532:26196:26904:25488:23600:7788
        PS C:\>
    #>
    param(
        [Parameter(ValueFromPipeline=$true)]
        [string]
        $String
    )
    begin {
        function BlurString ($String) {
            $Random = (New-Object System.Random).Next(2,254)
            $Key = [string]($Random * $Random)
            [string]$ReturnValue = $Key
            $String.ToCharArray() | ForEach-Object {
                $ReturnValue += ":" + ([Byte][Char]$_) * $Random
            }
            $ReturnValue
        }
    }
    process {
        if ($_) {
            $String = $_
        } elseif (!$String) {
            $String = $(Read-Host "Supply a value for the String parameter")
        }
        BlurString $String
    }
}

And now the according ConvertFrom function, ConvertFrom-BlurredString:

function ConvertFrom-BlurredString {
    <#
    .SYNOPSIS
        Converts a blurred string to a plain-text string.
    .DESCRIPTION
        The ConvertFrom-BlurredString function converts an blurred string into
        a plain-text string. It is used with ConvertTo-BlurredString.
    .EXAMPLE
        PS C:\> "81:648:909:972:972:999:396:288:783:999:1026:972:900:297" | ConvertFrom-BlurredString
        Hello, World!
        PS C:\>
    #>
    param(
        [Parameter(ValueFromPipeline=$true)]
    	[string]
        $BlurredString
    )
    begin {
        function UnravelString ($String) {
            $Chars = $String.Split(':')
            if ($Chars.Count -lt 2) {
                throw "'$String' is not blurred with ConvertTo-BlurredString"
            }
            [string]$ReturnValue = ""
            $Key = $Chars[0]
            foreach ($Char in $Chars[1..$Chars.Count]) {
                $ReturnValue += [Char][Byte]($Char/[math]::Sqrt($Key))
            }
            $ReturnValue
        }
    }
    process
    {
        if ($_) {
            $BlurredString = $_
        } elseif (!$BlurredString) {
            $BlurredString = $(Read-Host "Supply a value for the BlurredString parameter")
        }
        UnravelString $BlurredString
    }
}

How about using this functions as a module? Ok, just follow this steps:

Create a new directory in your Modules directory, for example “BlurStrings”.

Save the two functions in this folder.

Type the following commands in a text editor and save it as psm1 file, for example BlurStrings.psm1

. $psScriptRoot\ConvertTo-BlurredString.ps1
. $psScriptRoot\ConvertFrom-BlurredString.ps1

That’s all. The module is ready for use. If you enter

Get-Module –ListAvailable

you’ll see a new script module called BlurStrings (for example). If you need to use the module’s functions type

Import-Module BlurStrings

Now, the functions are ready to use. Hope you like it.

Category:General, PowerShell | Comment (0) | Author: Frank-Peter

Easy PowerShell Script Signing

Monday, 4. January 2010 14:19

Hello again. Wish you all the best for 2010.

My first blog post of the new year deals with the signing of PowerShell scripts. I want to share a function called Sign-Script that eases the process of adding a signature to one or more PowerShell scripts:

function Sign-Script ([String[]]$FilePath, [String[]]$PfxCertificate)
{
	begin
	{
		function sign ($filename, $cert)
		{
			Set-AuthenticodeSignature -FilePath $filename -Certificate $cert -WhatIf
		}
		if ($PfxCertificate)
		{
			$cert = Get-PfxCertificate -FilePath $PfxCertificate
		}
		else
		{
			$cert = @(Get-ChildItem -Path cert:\CurrentUser\My -CodeSigningCert)[0]
		}
	}
	process
	{
		if ($_)
		{
			if ($_ -is [IO.FileInfo])
			{
				sign -filename $_.FullName -cert $cert
			}
			else
			{
				sign -filename $_ -cert $cert
			}
		}
	}
	end
	{
		if ($FilePath)
		{
			foreach ($file in $FilePath)
			{
				sign -filename $file -cert $cert
			}
		}
	}

}

Basically, the Sign-Script function invokes the Set-AuthenticodeSignature cmdlet accordingly for each script file that was either passed as value of the FilePath parameter or as pipeline input (see lines 7, 24, 28, and 38).

By default, the function uses the Get-ChildItem cmdlet to get a code-signing certificate in the cert:\CurrentUser\My subdirectory of the certificate store (see line 11). Alternatively, the function will use the Get-PfxCertificate cmdlet to find the .pfx certificate that was passed as value of the PfxCertificate parameter (see line 15).

The Sign-Script function should be considered very basic. You can test it without any risks as I have used the WhatIf parameters in line 7 that invokes the Set-AuthenticodeSignature cmdlet. Hope you like it anyways.

Category:General, PowerShell | Comments (3) | Author: Frank-Peter

List available COM objects

Monday, 16. March 2009 8:32

A nice oneliner I found here will list all available COM object for your machine:

gci HKLM:\Software\Classes -ea 0| ? {$_.PSChildName -match ‘^\w+\.\w+$’ -and (gp “$($_.PSPath)\CLSID” -ea 0)} | ft PSChildName

Category:General, PowerShell | Comment (0) | Author: Dennis Damen