DCSIMG
September 2008 - Posts - Shay Levy

Shay Levy

If you repeat it, PowerShell it!

News


btn_donate_LG

View Shay Levy's profile on LinkedIn Follow Shay Levy at Twitter Shay Levy's Facebook profile Subscribe to my FriendFeed


site statistics




September 2008 - Posts

Exchange 2007 TechNet Labcasts

clip_image002

What is a labcast

An online presentation with guided video demonstrations where you also get the chance to perform these same exercises on your own hands-on virtual lab that we provide during the session.  As you face challenges in your lab, our instructors virtually take control of your lab to guide you through the tasks, giving you experience-based knowledge on the Microsoft product or topic.

Registration and seating for the upcoming live event is limited. If you are watching the on-demand version, there are no live instructors or registration limitations.

 


P.S Does anybody know the URL for the first one? Thanks Andy!

Write-Zip files

The other day I was trying to use the PowerShell Community Extensions (PSCX) Write-Zip cmdlet to archive my local scripts folder, but when I opened the compressed file I could see that all the folders, and subfolders  were stored at the root level even though I didn't use the -FlattenPaths parameter. This is the command I used:

PS > dir d:\scripts -rec | Write-Zip -level 9 -IncludeEmptyDirectories -OutputPath D:\Scripts.zip 

Why is that? Unfortunately, when binding from input objects, Write-Zip doesn't know how to preserve the paths in a reliable way. Files coming in could be coming from different parts of the filesystem and there is no way to represent all of the source files in a single relative hierarchy (which is how zips store things) because the files might be coming from different drives, from folders inside other folders, etc.

But there is a way around it:

PS > Write-Zip -level 9 -IncludeEmptyDirectories -Path d:\scripts -OutputPath D:\Scripts.zip 

That way, Write-Zip knows that the source is from a single hierarchy and it can definitely represent that in the zip. In addition, it will recurse all subfolders too, if you specify a folder to -OutputPath.

I want to thank Oisin, a fellow MVP and one of the master minds behind the PSCX project, for helping me out with it. You should definitely try PSCX if you haven't so far!

List of cmdlets in PSCX v1.1

ConvertFrom-Base64             ConvertTo-Base64
ConvertTo-MacOs9LineEnding     ConvertTo-UnixLineEnding
ConvertTo-WindowsLineEnding    Convert-Xml
Disconnect-TerminalSession     Export-Bitmap
Format-Byte                    Format-Hex
Format-Xml                     Get-ADObject
Get-Clipboard                  Get-DhcpServer
Get-DomainController           Get-ExportedType
Get-FileVersionInfo            Get-ForegroundWindow
Get-Hash                       Get-MountPoint
Get-PEHeader                   Get-Privilege
Get-PSSnapinHelp               Get-Random
Get-ReparsePoint               Get-ShortPath
Get-TabExpansion               Get-TerminalSession
Import-Bitmap                  Join-String
New-Hardlink                   New-Junction
New-Shortcut                   New-Symlink
Out-Clipboard                  Ping-Host
Remove-MountPoint              Remove-ReparsePoint
Resize-Bitmap                  Resolve-Assembly
Resolve-Host                   Select-Xml
Send-SmtpMail                  Set-Clipboard
Set-FileTime                   Set-ForegroundWindow
Set-Privilege                  Set-VolumeLabel
Split-String                   Start-Process
Start-TabExpansion             Stop-TerminalSession
Test-Assembly                  Test-Xml
Write-BZip2                    Write-Clipboard
Write-GZip                     Write-Tar

Get-DNS

Looking for an easy way to query DNS servers in PowerShell? Check out Joel's blog, he just made it possible with Get-Dns.

Keep in-sync with SysInternals tools

As you already know, all SysInternals utilities are available as a file share. Meaning you can run the tools directly from the Internet (e.g http://blogs.microsoft.co.il/controlpanel/blogs/$live.sysinternals.com\<toolName>), navigate to them with your browser or even map a drive on your local computer.

The SysInternals tools suite is a must have on any sysadmin machine. On my computer I keep them in a special directory (c:\sysint). From time to time the tools get updated or new tools get published and you might not know when it happens.

This is where Get-SysInternals comes into place. It lists the file share and compares each file's last modified date to the corresponding file on the local directory (if exists). If the 'live' file is newer, it is copied to the local directory and a yellow message in echoed to the console, new tools are painted in green. A log file is also generated into the specified directory by the name of changes.log.

At first I thought to compare the utilities file version info, but as you can see from the below, not all files have a version so I used the last modified date (lastWriteTime) instead.

PS > dir \\live.sysinternals.com\Tools -filter *.exe | select -expand vrsionInfo | ft @{l="Name";e={split-path $_.fileName -leaf}},FileVersion -auto

Name            FileVersion
----            -----------
accesschk.exe   4.20
AccessEnum.exe  1.32
accvio.EXE
ADExplorer.exe  1.01
ADInsight.exe   1.01
adrestore.exe
Autologon.exe   2.10
autoruns.exe    9.33
autorunsc.exe   9.33
Bginfo.exe      4, 14, 0, 0
Cacheset.exe
Clockres.exe
Contig.exe      1.54
ctrl2cap.exe
Dbgview.exe     4.75
DEFRAG.EXE
Desktops.exe    1.00
diskext.exe     1.1
Diskmnt.exe
Diskmon.exe     2.01
DiskView.exe
du.exe          1.31
efsdump.exe
Filemon.exe     7.04
handle.exe      3.41
...

The default local destination directory for the files is 'c:\sysint' and it will be created automatically if it doesn't exist. If you want another directory of your choice then simply run it like so: 'Get-SysInternals D:\otherDirName'  

           

function Get-SysInternals { param ( $sysIntDir="c:\sysint" ) if(!(Test-Path -Path $sysIntDir -PathType Container)) { $null = New-Item -Type Directory -Path $sysIntDir -Force } $log = join-path $sysIntDir "changes.log" Add-Content -force $log -value "`n`n[$(get-date)]SysInternals sync has been started" dir \\live.sysinternals.com\tools -recurse | foreach { $fileName = $_.name $localFile = join-path $sysIntDir $_.name $exist = test-path $localFile $msgNew = "new utility found: $fileName , downloading..." $msgUpdate = "file : $fileName is newer, updating..." $msgNoChange = "nothing changed for: $fileName" if($exist){ if($_.lastWriteTime -gt (Get-Item $localFile).lastWriteTime) { Copy-Item $_.fullname $sysIntDir -force Write-Host $msgUpdate -fore yellow Add-Content -force $log -value $msgUpdate } else { Add-Content $log -force -value $msgNoChange Write-Host $msgNoChange } } else { if($_.extension -eq ".exe") { Write-Host $msgNew -fore green Add-Content -force $log -value $msgNew } Copy-Item $_.fullname $sysIntDir -force } } }

 

And a sample output

PS > Get-SysInternals
File: accesschk.exe is newer, updating... File: AccessEnum.exe is newer, updating... New utility found: accvio.EXE, downloading... File: AdExplorer.chm is newer, updating... File: ADExplorer.exe is newer, updating... File: ADInsight.chm is newer, updating... File: ADInsight.exe is newer, updating... File: adrestore.exe is newer, updating... File: Autologon.exe is newer, updating... File: autoruns.chm is newer, updating... File: autoruns.exe is newer, updating... File: autorunsc.exe is newer, updating... File: Bginfo.exe is newer, updating... File: Cacheset.exe is newer, updating... File: Clockres.exe is newer, updating... File: Contig.exe is newer, updating... File: ctrl2cap.amd.sys is newer, updating... File: ctrl2cap.exe is newer, updating... File: ctrl2cap.nt4.sys is newer, updating... File: ctrl2cap.nt5.sys is newer, updating... File: dbgview.chm is newer, updating... File: Dbgview.exe is newer, updating... New utility found: DEFRAG.EXE, downloading... New utility found: Desktops.exe, downloading... File: diskext.exe is newer, updating... File: Diskmnt.exe is newer, updating... File: Diskmnt.hlp is newer, updating... File: Diskmon.exe is newer, updating...
...


Now all that is left to do is run it once in a while (I run it on every Sunday) and see if there were any changes to the live share. This is what I use to *schedule* it, put it in your PowerShell profile and wait for next Sunday ;-):


if( (get-date -f dddd) -eq "sunday") { Get-SysInternals }