New-ItemProperty "HKCU:\Software\Microsoft\Office\14.0\Outlook\Options\Calendar" EnableDirectBooking -Value 1 -PropertyType DWORD
Tuesday, January 24, 2012
Direct Booking does not successfully book a resource in Outlook 2010
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')
Monday, January 9, 2012
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 -AutoSizeOf 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
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
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".