Sunday, December 23, 2012

Getting more detail from Azure PowerShell Cmdlet 400 errors

Some of the Azure PowerShell Cmdlets return less than useful errors:
New-AzureDeployment : The remote server returned an unexpected response: (400) Bad Request.
At line:1 char:5
+     New-AzureDeployment -Slot $slot -Package "$root\NewSite.Azure\bin\Release\ap ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [New-AzureDeployment], ProtocolException
    + FullyQualifiedErrorId : Microsoft.WindowsAzure.Management.ServiceManagement.HostedServices.NewAzureDeploymentCommand
The way to get more detailed information is on this blog:
(New-Object System.IO.StreamReader($Error[0].Exception.InnerException.Response.GetResponseStream())).ReadToEnd()
I have simply formatted this into a useful PowerShell oneliner. Note that this command can only be run once. The problem in my case was that I had changed my storage account to camel case, but it must be all lower case.
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Code>BadRequest</Code>
  <Message>The name is not a valid storage account name. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.</Message>
</Error>

Friday, December 14, 2012

Checking if a TCP port is listening in PowerShell (TCP Ping)

In older versions of Windows, the telnet command could be used to test a TCP connection to another machine. However, this is not installed by default on newer versions of the O/S. The solution is to use a .NET class from PowerShell:
New-Object System.Net.Sockets.TcpClient machinename, 1337

Error configuring CredSSP

I was trying to configure CredSSP from a Windows 8 machine to Windows Server 2008 R2, but ran into the issue below:
C:\Windows\system32> Enable-WSManCredSSP -Role Client -DelegateComputer remotepc

CredSSP Authentication Configuration for WS-Management
CredSSP authentication allows the user credentials on this computer to be sent to a remote computer. If you use CredSSP
 authentication for a connection to a malicious or compromised computer, that computer will have access to your user
name and password. For more information, see the Enable-WSManCredSSP Help topic.
Do you want to enable CredSSP authentication?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"):
Enable-WSManCredSSP : The client cannot connect to the destination specified in the request.
Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation
for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM
service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".

At line:1 char:1
+ Enable-WSManCredSSP -Role Client -DelegateComputer COMPUTER
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.String[]:String[]) [Enable-WSManCredSSP], InvalidOperationExce
   ption
    + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.EnableWSManCredSSPCommand
I was baffled for a while, since WinRM was correctly configured on the remote PC. However, procmon showed that the local command was trying to connect to port 47001 on my local machine, which is the local WinRM service. After starting my local WinRM service, everything worked correctly.

Wednesday, December 12, 2012

Git client configuration

This is the Git configuration I use for my local repositories.
[core]
 autocrlf = false
[push]
 default = simple
[rerere]
 enabled = true
[diff]
 tool = p4merge
[difftool "p4merge"]
 cmd = p4merge \"$LOCAL\" \"$REMOTE\"
[merge]
 defaultToUpstream = true
 tool = p4merge
[mergetool "p4merge"]
 cmd = p4merge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
 keepTemporaries = false
 trustExitCode = false
 keepBackup = false
[gc]
 auto = 0

Thursday, November 22, 2012

jQuery UI widget pseudo-selectors

I stumbled across a very handy feature from jQuery UI today - widget pseudo-selectors. This page describes the feature well, but I have copied a common scenario here:
$.widget('ui.mywidget',{});
$(':ui-mywidget') //find all ui.mywidget instances

Saturday, November 17, 2012

Configuring a Git server

To publish an HTTP server, I use WebGitNet and the following system configuration:
receive.denynonfastforwards=true
gc.auto=0
core.logallrefupdates=true

receive.denynonfastforwards=true

Prevents people from accidentally pushing (using -force) a non-fast-forward update. This happened to me when I wanted to push a non-fast-forward update, but did not specify the single branch i.e. I used git push -f, which by default pushes all branches using the force flag.

gc.auto=0

There can be a lot of useful information in the 'garbage' of a git repository. My policy is to never delete that garbage.

core.logallrefupdates=true

The reflog is useful, but unfortunately it is not kept for remote bare repositories. This re-enables the reflog.

Thursday, November 15, 2012

Launching a PowerShell script in 64 bit mode on a 64 bit machine

If a 32-bit process launches PowerShell on a 64 bit machine, it will launch powershell.exe from the 32 bit system32 folder rather than the 64 bit one. Some scripts need to run in 64 bit mode, so the solution is to have the script relaunch itself in 64 bit mode if it detects that it has been run in 32 bit mode. This is one way to do it:
$powerShellExe = join-path $env:WINDIR SysNative\WindowsPowerShell\v1.0\powershell.exe
if(test-path ($powerShellExe)) {
    if([System.Runtime.InterOpServices.Marshal]::SizeOf([System.IntPtr]) -eq 4) {
        write-host "Re-launching script in native 64 bit mode..."
        & $powerShellExe $MyInvocation.MyCommand.Definition $PSBoundParameters.Values
        $host.SetShouldExit($LASTEXITCODE) 
        exit
    }
}

Wednesday, November 14, 2012

Getting an accurate list of dependencies from SSMS

The dependency dialog in SQL Server Management Studio does not appear to be particularly reliable, not returning some dependencies. The solution is to use the sys.dm_sql_referenced_entities table function:
select * from sys.dm_sql_referenced_entities (<ENTITY>, 'object')

Tuesday, November 13, 2012

Correctly Executing a PowerShell script from MSBuild

It took me a while to find out how to execute a PowerShell script from within an MSBuild script while propagating errors to MSBUILD. I tried several approaches, including the usual -File argument, but this is what I came up with in the end:
<Exec Command="powershell -Command &quot;&amp;{ .\Deploy.ps1 scriptArg1 scriptArg2 }&quot;" />

Tuesday, November 6, 2012

Configuring a new Windows Server 2012 instance using PowerShell


  1. Join the domain (prompt for user name and password of domain administrator):
    Add-Computer -DomainName {Domain Name}
  2. Add a domain user as an administrator:
    net localgroup administrators {Domain Name}\{User Name} /add
  3. Name the computer:
    Rename-Computer {New Name}
  4. Enable PowerShell remoting (note: no double hops):
    Enable-PSRemoting
  5. Restart the computer:
    Restart-Computer

Wednesday, October 24, 2012

WARNING: The generated type defines no public methods or properties

I received the following warning while using the Add-Type CmdLet in PowerShell:
WARNING: The generated type defines no public methods or properties.
Since I was aware that this was the case, I suppressed the warning using the following parameter to Add-Type:
Add-Type -WarningAction SilentlyContinue ...

Monday, October 22, 2012

Text bootloader in Windows 8

Windows 8 installs a new, quite nice looking, graphical bootloader. Unfortunately, this bling comes with a fairly serious drawback - Windows 8 needs to boot before the bootloader is displayed on the screen, which can take 20 seconds or so, and then if you have the audacity to want to boot into another operating system, the machine will be rebooted, forcing you to endure another BIOS POST sequence.

The workaround is to enable the text based bootloader using bcdedit (note that the backticks (`) are required in PowerShell to escape the braces):
bcdedit /set `{current`} bootmenupolicy legacy
To switch back to the graphical bootloader, run the following command:
bcdedit /set `{current`} bootmenupolicy standard
You'll need to run these PowerShell commands as an administrator.

Friday, October 19, 2012

After recently importing a Subversion repository into Git, along with the associated .gitignore file, I noticed that git status was performing poorly. The solution was to split the monolithic .gitignore file in the root folder into multiple .gitignore files spread throughout the repository.

I wrote the following PowerShell script to do so:
$content = type .gitignore | % { $_.Trim() } | ? { $_.StartsWith('/') } | % { $_.SubString(1) }
$content | % {
    $folder = split-path -Parent $_    
    if($folder.length -gt 0) {
        if(-not (test-path $folder)) {
            md $folder | Out-Null
        }
        $pattern = split-path -Leaf $_
        $newPattern = '/' + $pattern
        $ignoreFile = "$folder\.gitignore"
        $exists = $false
        if((test-path $ignoreFile ) -and (type $ignore) -notcontains $newPattern) {
            $exists = $true
        }
        if(!$exists) {
            Add-Content -Force -Path $ignoreFile $newPattern
        }
    }
}

Friday, October 12, 2012

Adding credentials to the Windows credential store from the command line

Service users often do not have permission to start GUI applications, so the following tool can be used to store credentials that can be used to access a server, for example to copy a backup onto a remote file share.

cmdkey.exe

The syntax to add credentials to the store is:

cmdkey /add:targetname /user:username /pass

Monday, October 8, 2012

Git Cookbook

This page lists some useful commands that I use with Git:
  • Show all branches that contain a commit. Useful to see which branches a topic branch has been merged into.
    • git branch --all --contains commit
  • Show which branches have not been merged into the current or specified branch.
    • git branch --all --no-merge [branch]
  • Pretty-print history tree
    • git log --oneline --graph --decorate --all
  • List all changes that will be sent with the next push
    • git log --branches --not --remotes
  • Update from remote
    • git fetch
    • git rebase -p
  • Get name of remote tracking branch for the current branch
    • git branch -vv | ? { $_ -match '^\*' } | % { $_ -match '\[([^:]+)' | Out-Null; $Matches[1] }
  • Get the most recently modified topic branch
    •  git for-each-ref --sort=-committerdate --format='%(refname)' refs/remotes/origin/topic | select -first 1

Wednesday, June 20, 2012

Get status of all Git repositories using PowerShell

The following PowerShell one-liner will get the status of all Git repositories:
dir -r -i .git -fo | % { pushd $_.fullname; cd ..; write-host -fore yellow (get-location).Path; git status; popd }
Note that this will not work for bare repositories.

Wednesday, June 6, 2012

Installing (and booting) Windows 8 on a VHD

Windows 8 (and Server 2012) greatly simplifies installing Windows 7 / Windows Server 2008 R2 / Windows 8 / Windows Server 2012 to a VHD or VHDX for booting without having to mess around with partitions. Convert-WindowsImage.ps1 is a fantastic tool that you can run from Windows 8 or Server 2012 to install a new operating system without rebooting your machine. To install Windows 8 Release Preview on a VHDX, I did the following:

  1. Download and unblock the PowerShell script Convert-WindowsImage.ps1. I couldn't find the unblock checkbox on the file properties dialog, so I used the Sysinternals streams.exe utility to remove the block:
    streams -d Convert-WindowsImage.ps1
  2. I then mounted the Windows 8 ISO image by double clicking on it in Explorer, taking advantage of the belated ISO mounting feature. In my case, it mounted to E:.
  3. Next, I ran Convert-WindowsImage.ps1 with the following command line:
    .\Convert-WindowsImage.ps1 -SourcePath E:\sources\install.wim -VHDFormat VHD -SizeBytes 50GB -VHDPath Windows8RP.vhd -VHDType Fixed -Edition Professional
  4. Mount the VHDX using diskmgmt.msc. I tried using Mount-DiskImage, but kept running into the following error: "Mount-DiskImage : One or more parameter values passed to the method were invalid." My drive was mounted as F:
  5. Run the following command to add your new VHD to the boot menu:
    bcdboot F:\Windows
  6. Reboot and select the new O/S in the boot menu.

Saturday, April 14, 2012

Redirecting all output from a PowerShell script using the new PowerShell 3.0 asterisk / star / * redirection:


powershell -Command { .\scriptfile.ps1 *> out.log }

Other types of redirection:
  • Pipeline: 1
  • Error: 2
  • Warning: 3
  • Verbose: 4
  • Debug: 5
  • All streams: *

Thursday, April 5, 2012

NuGet and Semantic Versioning

NuGet version 1.6 introduced support for Semantic Versioning, however I have since discovered that NuGet only supports v1.0.0 of the SemVer specification. Unfortunately, this is much more limiting than the latest version, which supports more and better scenarios such as continuous integration builds.

Semantic versions in NuGet must match the following regular expression:


(?\d+(\.\d+){2})(?-[a-z][0-9a-z-]*)?

This means a version number with three components (e.g. 1.0.0) optionally followed by a pre-release version number. The pre-release version number must start with a dash (-) and a letter between a-z, and can then be any number of digits, letters and dashes (-). The regular expression is case insensitive.

For example,

  • 0.1.0
  • 0.1.0-alpha
  • 0.1.0-Alpha
  • 0.1.0-a-2

Saturday, March 31, 2012

B1248 LED Name Badge C# / .NET API

I am working on an open source API for the B1248 LED name badge that I got from CodeMania in Auckland, New Zealand. So far, it is possible to send any ASCII message to the device in the first slot, so it is useful as a display attached to a computer.

The code is not complete and I am definitely open to contributions!!

Find the code at BitBucket: https://bitbucket.org/bartj/led

Friday, March 23, 2012

Work with a "shadow copy" of your file system

Sometimes it is useful to be able to take a snapshot of the file system as it currently stands while still having programs use / access it. The reason I wrote this PowerShell script is that I want to be able to copy virtual machines around while still accessing them. Unfortunately, copying virtual machines takes a long time due to their size, so it is useful to be able to copy them while they are in use. This script allows me to shut down the virtual machine, start the copy operation, and then restart the virtual machine while the copy is still in progress.

Notes / caveats:

  • This script requires administrative privileges.
  • The script is naive and does not work if the folder you want to work with is inside a mount point or directory junction (this situation is usually rare).
  • The script leaves a symbolic link in the temp folder, so these may accumulate over time.

function CreateShadowCopy([string]$LocationToOpen) {
    if(-not $LocationToOpen -or -not (test-path $LocationToOpen)) {
        $LocationToOpen = get-location
    }
    if(-not (get-item $LocationToOpen).PSIsContainer) {
        $LocationToOpen = split-path -Parent $LocationToOpen
    }
 
    $fullPath = (resolve-path $LocationToOpen).Path
    $fileRoot = [system.io.path]::GetPathRoot($fullPath)
    $shadow = (Get-WmiObject -list win32_shadowcopy).Create($fileRoot, "ClientAccessible") 
    $shadowRoot = join-path $env:temp $shadow.ShadowID
    $shadowPath = gwmi win32_shadowcopy | ? { $_.Id -eq $shadow.ShadowID } | select -ExpandProperty DeviceObject
    cmd /c mklink /d $shadowRoot $shadowPath\ | out-null
    $rootlessCurrentPath = $fullPath.substring($fileRoot.length)
    join-path $shadowRoot $rootlessCurrentPath
}

$shadowPath = CreateShadowCopy D:\
try {
    pushd $shadowPath

    ls .
    echo "Do stuff..."
}
finally {
    popd
    cmd /c rd $shadowPath
}

Tuesday, January 24, 2012

Direct Booking does not successfully book a resource in Outlook 2010

The Microsoft support article entitled Direct Booking does not successfully book a resource in Outlook 2010 discusses how to solve a problem booking resources in Outlook 2010. The following PowerShell one-liner will fix the problem:
New-ItemProperty "HKCU:\Software\Microsoft\Office\14.0\Outlook\Options\Calendar" EnableDirectBooking -Value 1 -PropertyType DWORD

Wednesday, January 18, 2012

Installing printers using PowerShell

Our developer team has a wiki page that describes very clearly how to use the Windows 7 UI to install network printers into developer machines. The document is well written, with all steps accompanied by screenshots. However, it is tricky and boring to follow, so I thought there must be a simpler way to add printers using PowerShell - and it turns out there is.

$net = New-Object -Com WScript.Network
$net.AddWindowsPrinterConnection('\\server\printer')

Saturday, January 7, 2012

Removing old versions of Chrome using PowerShell

Google Chrome leaves older versions of itself on disk, which can cause useful vulnerability scanners such as the fantastic Secunia PSI to report Chrome as vulnerable although the older version is not in use.

To automatically remove older versions from the current user, run the following PowerShell one-liner.

dir ~\AppData\Local\Google\Chrome\Application | ? { $_ -match '\d+\.\d+\.\d+\.\d+' } | % { @{ File=$_; Version=(New-Object System.Version $_.Name) } } | sort -Descending Version | select -Skip 1 | % { del -fo -r $_.File.PSPath }

Versioning .NET assemblies

Providing meaningful version numbers to PE binaries (.EXEs and .DLLs) is a very good way to make sure that you can always find the correct source code that was used to build. Note that this should be used in conjunction with a symbol server, which is so trivially easy to set up in TFS 2010 that everyone should be doing it.

This is my currently recommended way for using the various versions available in .NET assemblies. Note that it is subject to change as new and better ideas come along!


The AssemblyVersion.cs file

Set up a single C# file that you will include in all your assemblies that need to be given the same version number. I currently give all the DLLs in a single releasable product the same version number so future releases of an assembly will have a new version number, regardless of whether any of the code in that DLL has actually changed. I find this the simplest way to ensure consistency of the product through the full SDLC. In this C# file, which could be called AssemblyVersion.cs, your continuous integration (CI) server will generate something like the following code:

using System.Reflection;

[assembly: AssemblyVersion("1.0.2.23456")]
[assembly: AssemblyInformationalVersion("1.0.1beta1 ($/Project/Main;223456)")]

You will need to put this file in a common location and include it as a linked file in each of your projects. This common file replaces the versioning information that is usually in AssemblyInfo.cs, so you will need to remove those attributes from each project that you include AssemblyVersion.cs in.


AssemblyVersion.cs in development and production

I like to make version number obviously different when building on developer machines, so I typically set the version to 0.0.0.0 or - in case Visual Studio Code Analysis complains - 0.0.0.1. The following AssemblyVersion.cs file would be checked into source control:

using System.Reflection;

[assembly: AssemblyVersion("0.0.0.0")]
[assembly: AssemblyInformationalVersion("development")]
And the following PowerShell script would be launched from within TFS, Jenkins, Cruise Control, or your CI server of choice to modify AssemblyVersion.cs.
param(
        [parameter(mandatory=$true)][int]$MajorVersion,
        [parameter(mandatory=$true)][int]$MinorVersion,
        [parameter(mandatory=$true)][int]$SourceRevision,
        [parameter(mandatory=$true)][string]$SourceBranch
)

#validate source parameters
if($SourceRevision -lt 0 -or $SourceRevision -gt 6553565535) {
    throw "Invalid SourceRevision."
}
if($MajorVersion -lt 0 -or $MajorVersion -gt 65535 -or $MinorVersion -lt 0 -or $MinorVersion -gt 65535) {
    throw "Invalid major / minor version."
}

$scriptFolder = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$versionFile = resolve-path (join-path $scriptFolder 'AssemblyVersion.cs') # script must be in the same folder as AssemblyVersion.cs

if(-not (test-path $versionFile)) {
    throw "Unable to find version file."
}

#calculate Build/Revision version component
if($SourceRevision -le 65535) {
    $rev1 = 0
    $rev2 = $SourceRevision
} 
else {
    $verStr = $SourceRevision.ToString()
    $rev2 = [int][string]::Join('', $verStr[-5..-1])
    if($rev2 -gt 65535) {
        $rev2 = [int][string]::Join('', $verStr[-4..-1])
    } 
    $rev1 = [int]$verStr.SubString(0, $verStr.length - $rev2.ToString().length)
}

$assemblyVersion = "$MajorVersion.$MinorVersion.$rev1.$rev2"
$humanVersion = $SourceBranch + ':' + $SourceRevision

Write-Host "Setting assembly version to $assemblyVersion and human readable version to '$humanVersion'."

(type $versionFile) -replace '0.0.0.0',$assemblyVersion -replace 'development',$humanVersion | Out-File -Encoding UTF8 $versionFile

AssemblyVersionAttribute

The Assembly version will by default also be set as the AssemblyFileVersion if the latter is not explicitly specified. One important piece of information I want to include is the revision number of the source code that was used to make the build. Each component in the AssemblyVersion is limited to 65535 (16 bit). Since it won't take long for 65535 revisions to be committed when checking in early and often, I spill over into the build number in a human readable fashion, so version 1.0 built from revision 223456 would be 1.0.2.23456.


AssemblyInformationalVersionAttribute

The AssemblyInformationalVersion attribute is a very useful free text string that will appear in the Product Version field when looking at the details of the DLL in Windows Explorer. I sometimes use a semantic version as the first part of that string, and always include an unambiguous reference to the source code that was used to build it i.e. branch and revision details for whatever source control system is in use.

Friday, January 6, 2012

Listing all keyboard shortcuts in Visual Studio 2010

The NuGet package manager for Visual Studio comes with a hidden gem - a PowerShell console called Package Manager Console. This console not only allows developers to install and configure NuGet packages, but also has a useful variable called $dte, which is the Visual Studio automation COM object.

To demonstrate the usefulness of this feature, I thought it would be interesting to list all the keyboard shortcuts that I currently had bound. To do this, I ran the following PowerShell one-liner:

$dte.Commands | ? { $_.Bindings.length -ne 0 -and $_.name.length -ne 0 } | sort Name | select Name, Bindings | % { $b = $_.Name; $_.Bindings | % { $_ -match '(.*)::(.*)' | out-null; new-object psobject -Property @{ Name = $b; Context = $Matches[1]; Key = $Matches[2]} } } | sort Context, Name, Key | select Context, Name, Key | ft -AutoSize
Of course, if you want to grab this information and format it for better printing, just replace the last step in the pipeline (ft -AutoSize) with ConvertTo-Csv | clip. This will copy all your shortcuts into the clipboard in CSV format, and you can paste them into Excel for better formatting and printing.

Wednesday, January 4, 2012

Requiring administrative access in Visual Studio 2010 C++ projects

In previous versions of Visual Studio, making any changes to the application manifest file for a C++ application required you to code one up manually, removing the advantages of the built-in manifest generation tool. However, in Visual Studio 2010, common tasks such as setting the UAC execution level are now baked into the project settings.

Below is a screenshot of how to set the execution level (requestedExecutionLevel) or UI protection (uiAccess) settings in the manifest using the project settings.


Tuesday, January 3, 2012

Name files by last write date

I have a Samsung HMX-H200BP/XSA camcorder, which I am really happy with. However, according to exiftool, it does not seem to stamp the record date and time into the movie metadata. Instead, it relies on the last write date.

The PowerShell command below will bulk rename all the MP4 files in the current folder so that they are named by the date and time taken i.e. the last write date.

dir hdv_*.mp4 | % { ren $_.Name ($_.LastWriteTime.ToString('yyyy-MM-dd HH-mm') + '.mp4') }

Monday, January 2, 2012

Undocumented PowerShell 2 Tail Functionality

One feature that I have often thought was missing from PowerShell is the equivalent to the *nix tail functionality, which will display lines as they are added to a log file. I have used the PowerShell Community Extensions (PSCX) Get-FileTail cmdlet, but that can be frustrating because it is not available on all the computers I use, so I wanted to find a built-in equivalent.

It turns out that there is an undocumented built-in tail function. Use the Get-Content (alias = gc) cmdlet with the undocumented -Wait parameter. Apparently, it has performance issues with large files, so you may still need to carry a copy of PSCX around with you on a USB stick, but this should suffice for most scenarios.

Below is the documentation for Get-Content for PowerShell 2.0, with no mention of the -Wait parameter.


NAME
    Get-Content
    
SYNOPSIS
    Gets the content of the item at the specified location.
    
    
SYNTAX
    Get-Content [-LiteralPath]  [-Credential ] [-Exclude ] [-Filter ] [-Force
    ] [-Include ] [-ReadCount ] [-TotalCount ] [-UseTransaction] []
    
    Get-Content [-Path]  [-Credential ] [-Exclude ] [-Filter ] [-Force] [-Inc
    lude ] [-ReadCount ] [-TotalCount ] [-UseTransaction] []
    
    
DESCRIPTION
    The Get-Content cmdlet gets the content of the item at the location specified by the path, such as the text in a fi
    le. It reads the content one line at a time and returns an object for each line.
    

PARAMETERS
    -Credential 
        Specifies a user account that has permission to perform this action. The default is the current user. 
        
        Type a user name, such as "User01" or "Domain01\User01", or enter a PSCredential object, such as one generated 
        by the Get-Credential cmdlet. If you type a user name, you will be prompted for a password.
        
        This parameter is not supported by any providers that are installed with Windows PowerShell.
        
    -Exclude 
        Omits the specified items. The value of this parameter qualifies the Path parameter. Enter a path element or pa
        ttern, such as "*.txt". Wildcards are permitted.
        
    -Filter 
        Specifies a filter in the provider's format or language. The value of this parameter qualifies the Path paramet
        er. The syntax of the filter, including the use of wildcards, depends on the provider. Filters are more efficie
        nt than other parameters, because the provider applies them when retrieving the objects, rather than having Win
        dows PowerShell filter the objects after they are retrieved.
        
    -Force []
        Overrides restrictions that prevent the command from succeeding, just so the changes do not compromise security
        . For example, Force will override the read-only attribute or create directories to complete a file path, but i
        t will not attempt to change file permissions.
        
    -Include 
        Retrieves only the specified items. The value of this parameter qualifies the Path parameter. Enter a path elem
        ent or pattern, such as "*.txt". Wildcards are permitted.
        
    -LiteralPath 
        Specifies the path to an item. Unlike Path, the value of LiteralPath is used exactly as it is typed. No charact
        ers are interpreted as wildcards. If the path includes escape characters, enclose it in single quotation marks.
         Single quotation marks tell Windows PowerShell not to interpret any characters as escape sequences.
        
    -Path 
        Specifies the path to an item. Get-Content retrieves the content of the item. Wildcards are permitted. The para
        meter name ("Path" or "FilePath") is optional.
        
    -ReadCount 
        Specifies how many lines of content are sent through the pipeline at a time. The default value is 1. A value of
         0 (zero) sends all of the content at one time. 
        
        This parameter does not change the content displayed, but it does affect the time it takes to display the conte
        nt. As the value of ReadCount increases, the time it takes to return the first line increases, but the total ti
        me for the operation decreases. This can make a perceptible difference in very large items.
        
    -TotalCount 
        Specifies how many lines of content are retrieved. The default is -1 (all lines).
        
    -UseTransaction []
        Includes the command in the active transaction. This parameter is valid only when a transaction is in progress.
         For more information, see about_Transactions.
        
    
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer and OutVariable. For more information, type,
        "get-help about_commonparameters".
    
    -------------------------- EXAMPLE 1 --------------------------
    
    C:\PS>get-content -Path C:\Chapters\chapter1.txt
    
    Description
    -----------
    This command displays the content of the Chapter1.txt file on the console. It uses the Path parameter to specify th
    e name of the item. Get-Content actually passes the content down the pipeline, but because there are no other pipel
    ine elements, the content is formatted and displayed on the console.
    
    
    
    
    -------------------------- EXAMPLE 2 --------------------------
    
    C:\PS>get-content c:\Logs\Log060912.txt -totalcount 50 | set-content sample.txt
    
    Description
    -----------
    This command gets the first 50 lines of the Log060912.txt file and stores them in the sample.txt file. The command 
    uses the Get-Content cmdlet to get the text in the file. (The name of Path parameter, which is optional, is omitted
    .) The TotalCount parameter limits the retrieval to the first 50 lines. The pipeline operator (|) sends the result 
    to Set-Content, which places it in the sample.txt file.
    
    
    
    
    -------------------------- EXAMPLE 3 --------------------------
    
    C:\PS>(get-content cmdlets.txt -totalcount 5)[-1]
    
    Description
    -----------
    This command gets the fifth line of the Cmdlets.txt text file. It uses the TotalCount parameter to get the first fi
    ve lines and then uses array notation to get the last line (indicated by "-1") of the resulting set.
    
    
    
    
REMARKS
    To see the examples, type: "get-help Get-Content -examples".
    For more information, type: "get-help Get-Content -detailed".
    For technical information, type: "get-help Get-Content -full".