Tuesday, October 20, 2009

Windows 7 madness

I think that every geek is googling for phrases like “Windows 7 tips and tricks” or “Windows 7 secrets” once he thinks he knows enough about new product.

Windows 7 is new IT phenomenon – you can discuss it, disagree with it, hate it, but that’s about it. Let’s have a look at Google Trends:

Win7 vs Leopard

Blue represents Windows 7, red is main competitor Snow Leopard

Just for fun, below is similar graph comparing Windows 7, Windows XP and Windows Vista.

Windows family

Windows 7 vs Windows XP vs Windows Vista

First, let me give you my presentation from 1.10.2009 about Windows 7.

Second, I was reading through a lot of tips and tricks pages. Today I noticed article called 77 Windows 7 Tips. To make long story short, it’s obvious that number 77 was chose first and then they started to think about the content :( Otherwise I don’t see any explanation for some of those tips.

On the other hand, there are other articles that are discussing new features and tips\tricks and are great. To mention just a few of them, Tim Sneath got great article and I also liked a lot article from TechRadar.

So, I decided to write a series of articles about Windows 7. Currently I got 91 tips, but I started yesterday, so it shouldn’t be problem to get to 100. Some of the tricks are really simple and can be explained on 2-3 lines, some will require a lot more space. I don’t want to simply publish tricks, but also explain how some new technologies works and provide some additional details (for example performance comparison of older Robocopy and new one). I will call these articles Windows 7 Maddness and I will try to group tips together.

Hold on to see more :)

Friday, September 25, 2009

Sorting hashtable in Powershell

I am using hashtables (or dictionaries) more and more in Powershell – once I figured out that syntax $Hashtable.Key works, it turned out to be extremely useful as something similar to custom class.

However I run into an issue (maybe bug?) with sorting hashtables:

PS C:\> $X.Martin = "Zugec"
PS C:\> $X.Kamila = "Vlasakova"
PS C:\> $X.Filip = "Puntik"
PS C:\> $X.Tereza = "Liska"
PS C:\> $X | Sort Name

Name                           Value
----                           -----
Filip                          Puntik
Kamila                       Vlasakova
Tereza                      Liska
Martin                       Zugec

As you can see, output is not sorted. After a while I tried to use raw method that is used in .NET:

PS C:\> $X.psbase.GetEnumerator() | Sort Name

Name                           Value
----                           -----
Filip                          Puntik
Kamila                       Vlasakova
Martin                       Zugec
Tereza                      Liska

As you can see, everything is sorted out correctly in this case. Another scenario where you could use GetEnumerator is if you want to handle name (key) and value:

PS C:\> $X.psbase.GetEnumerator() | Where {$_.Name -eq "Martin"}

Name                           Value
----                           -----
Martin                         Zugec

Without using enumerator, you got access only to values.

Monday, September 7, 2009

How to display all performance counters in console

Just run into this today – I am writing some scripts for Citrix License server and wanted to see which performance counters are available…

Turned out to be pretty simple – just use “TypePerf” command with –q:

   1: C:\Users\Martin>typeperf -q | more



   2: \TBS counters\CurrentResources



   3: \TBS counters\CurrentContexts



   4: \WSMan Quota Statistics(*)\Active Users



   5: \WSMan Quota Statistics(*)\Active Operations



   6: \WSMan Quota Statistics(*)\Active Shells



   7: ...


Friday, August 28, 2009

Get or set file\directory attributes using Powershell

This is just “reminder post” for me if I will need to use it in future…

I wanted to create hidden folder using Powershell – in fact, it’s not very hard:

$(MkDir “Martin Zugec”).Attributes = ‘Hidden’

.Attributes is FileAttributes enumeration, so you use same syntax when you want to create files. Below are available values:

Archive Applications use this attribute to mark file\folder for backup or removal
Compressed Is compressed
Device N/A – in future maybe ;) Looks promising :)
Directory “File is directory” :)
Encrypted Encrypted
Hidden Hidden
Normal If no other attributes are applied
NotContentIndexed Skip for indexing
Offline File\Folder is offline
ReadOnly File\Folder is read-only
ReparsePoint Contains reparse point. Reparse point is user data associated with this entry – one example where reparse points are used is when you mount folder into another.
SparseFile Sparse files are usually large files whose data are mostly zeros. To be honest, I never saw sparse file as far as I know – even fake huge files (FSUtil File CreateNew) are not sparse files.
System System file
Temporary If file is marked as temporary, file system will try to keep all the data in memory for quicker access instead of flushing data back to harddisk. Of course temporary file should be deleted as soon as possible if not needed ;)

If you want to change attribute of existing folder\file, it’s also very easy:

$(Get-Item “Martin Zugec”).Attributes = ‘Hidden’

Wednesday, August 26, 2009

How to return multiple values from Powershell function

I used this trick few times when I had function that had to return more values…

As I wrote here, you can access dictionary object using syntax $Dictionary.Key… If your function returns dictionary, then you can use it to your advantage :)

   1: Function Get-MultiValue () { 



   2:  [hashtable]$Return = @{} 



   3:  



   4:  $Return.Success = $True 



   5:  $Return.PercentComplete = 100 



   6:  $Return.ReturnTime = $(Get-Date) 



   7:  $Return.Username = "Martin Zugec" 



   8:  



   9:  Return $Return 



  10: }




Usage is pretty obvious:





   1: $Var = Get-MultiValue 



   2:  



   3: If ($Var.Success) { 



   4:     $Var.UserName 



   5:     $Var.ReturnTime 



   6: }




Easy and useful sometimes…

Monday, August 24, 2009

New-Enum for Powershell v2

Recently I wrote about new-enum function that should work both in Posh v1 and v2… Well, it doesn’t, because v1 will throw an error on @Args.

Below is updated version that should work in both powershells:

# Supports creation of custom Enums during runtime. 
# Because CoreFunctions and CustomFunctions requires already some enumerations (specifically LogType), it must be initialized in main script.
function Global:S4M\New-Enum ([string] $name, [switch]$FixMode, [array]$Members = @()) {

$Members += $Args

$appdomain = [System.Threading.Thread]::GetDomain()
$assembly = new-object System.Reflection.AssemblyName
$assembly.Name = "EmittedEnum"
$assemblyBuilder = $appdomain.DefineDynamicAssembly($assembly,
[System.Reflection.Emit.AssemblyBuilderAccess]::Save -bor [System.Reflection.Emit.AssemblyBuilderAccess]::Run);
$moduleBuilder = $assemblyBuilder.DefineDynamicModule("DynamicModule", "DynamicModule.mod");
$enumBuilder = $moduleBuilder.DefineEnum($name, [System.Reflection.TypeAttributes]::Public, [System.Int32]);

for($i = 0; $i -lt $Members.Length; $i++) {
If (([string]($Members[$i])).Contains("=")) {
[string]$EnumName = [string](($Members[$i].Split("="))[0])
$Null = $enumBuilder.DefineLiteral($EnumName, [int]($Members[$i].Split("="))[1]);
} Else {
$Null = $enumBuilder.DefineLiteral($Members[$i], $i);
}
}

$enumBuilder.CreateType() > $Null;

#Used to fix issue with Powershell v2
If ($Host.Version.Major -eq 1 -or $FixMode) {
$enumBuilder.CreateType() > $Null;
} Else {
S4M\New-Enum -FixMode -Name $name -Members $Members
$enumBuilder.CreateType() > $Null;
}
}

Friday, August 14, 2009

Bug in PowerShell?

Yesterday I wrote about a way how to use [HashTable] type as single storage for different values… Well, code has to be changed a bit.

Remember that you can access member by using $People.$Foo? But it doesn’t work always, so you should use $People.[string]$Foo instead.

Have a look at following code:

[hashtable]$Collection = @{}
For ($i = 0; $i -lt 10; $i += 1) {$Collection.$i = $i}



Looks fine, doesn’t it? Well, let’s have a look at keys:



PS C:\> $Collection.Keys
9
8
7
6
5
4
3
2
1
0



Still ok. Now try to retrieve value for one of the keys:



PS C:\> $Collection.9
Unexpected token '.9' in expression or statement.
At line:1 char:14
+ $Collection.9 <<<<
+ CategoryInfo : ParserError: (.9:String) [], ParentContainsError
RecordException
+ FullyQualifiedErrorId : UnexpectedToken



Hmmmmmm, error. Let’s have a look at key type:



PS C:\> $Collection.Keys | ForEach {$_.GetType()}

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType



Have you noticed something? Key should be always string, however in this case, PowerShell doesn’t convert it automatically. Surprisingly, this allows us to have 2 keys with same name – something that should never happen ;)



PS C:\> $Collection."9" = 9
PS C:\> $Collection.Keys
9
9
8



Ok, and here comes solution. Whenever you assign key, specify that it is string:



[hashtable]$Collection = @{}
For ($i = 0; $i -lt 10; $i += 1) {$Collection.[string]$i = $i}