Archive for the 'KB' Category

New in PowerShell 3: Parse HTML without IE object (unless a local file)

Remember how in PowerShell v1 and v2 we used to have to create Internet Explorer object each time we wanted to parse HTML page? This kind of works but has a few inconveniences such as having to insert Start-Sleep every now and then because IE can be busy and fail if you request too much from it too quickly.

In PowerShell v3, for web pages, things become much easier. Just do:

$p = Invoke-WebRequest "https://dmitrysotnikov.wordpress.com"

And $p.ParsedHtml.body will let you iterate though all web page elements!

However, there is a scenario in which you will have to revert to the old IE ways – local files. If the HTML file is on your local disk, $p will not have the ParsedHtml property. And you will have to use the IE COM object like you did in earlier versions of PowerShell:

$ie = new-object -com "InternetExplorer.Application"
# The easiest way to accomodate for slowness of IE
Start-Sleep -Seconds 1
$ie.Navigate("D:\SavedPage.htm")
# The easiest way to accomodate for slowness of IE
Start-Sleep -Seconds 1
$ParsedHtml = $ie.Document

Happy scripting!

Advertisements

Fix PowerGUI shortcuts in Start menu

ISSUE

PowerGUI 3.0 accidentally shipped with Windows Start menu shortcuts being called just “Administrative Console” and “Script Editor”. Which means that if you are used to starting applications by typing keywords in Start menu, you won’t be able to find the tools by typing PowerGUI:

SOLUTION

Open PowerGUI Script Editor (or native PowerShell command line), run the following command in the PowerShell Console window:

dir “$($env:ProgramData)\Microsoft\Windows\Start Menu\Programs\PowerGUI” | where {$_.Name -notmatch “PowerGUI”} | Rename-Item -NewName {“PowerGUI ” + $_.Name}

This will rename the shortcuts for you:

PowerGUI Editor 2.4 and AD cmdlets 1.4 compatibility issue

[UPDATE] This issue has been fixed in AD cmdlets 1.5.1 – please download the latest version of AD cmdlets here.

We have found a compatibility issue between PowerGUI Script Editor 2.4 and AD cmdlets 1.4 (these are the current versions at the time I am writing this post.)

SYMPTOMS

You execute a script which is using QAD cmdlets. The first time the script executes fine. However when you try to execute it again, the script fails with the “Object reference not set to an instance of an object.” error.

ISSUE

The issue is related to the way QAD cmdlets are handling initialization and unloading of the snapin.

SOLUTION

Set PowerGUI Script Editor to not reset PowerShell runspaces between the debug sessions:
1. Go to Tools / Options / Debug Options,
2. Select the Run all scripts in the same runspace option.
3. Restart PowerGUI Script Editor.

We are sorry for the inconvenience and are working on fixing the issue in the next releases.

Unblocking PowerGUI Add-Ons and PowerShell Modules

When trying to use a Script Editor add-on or a PowerShell module or script you downloaded from the internet, you might every now and then get an error message like this:

Import-Module : File C:\Users\dsotnikov\Documents\WindowsPowerShell\Modules\Add-on.HelpBrowser\Add-on.HelpBrowser.psm1 cannot be loaded. The file C:\Users\dsotnikov\Documents\WindowsPowerShell\Modules\Add-on.HelpBrowser\Add-on.HelpBrowser.psm1 is not digitally signed. The script will not execute on the system. Please see “get-help about_signing” for more details..At line:1 char:184+ @(‘C:\Users\dsotnikov\Documents\WindowsPowerShell\Modules\Add-on.HelpBrowser\Add-on.HelpBrowser.psd1’) | Where-Object { @(Get-Module | %{$_.Path} ) -notcontains $_ } | %{ Import-Module <<<<  $_ }    + CategoryInfo          : NotSpecified: (:) [Import-Module], PSSecurityExc    eption    + FullyQualifiedErrorId : RuntimeException,Microsoft.PowerShell.Commands.ImportModuleCommand

This happens when the downloaded file comes from the internet, is not signed and thus conflicts with your PowerShell execution policy (e.g. RemoteSigned).

If you do trust this particular add-on/module/script to not be malicious (comes from a trusted source, has been inspected and so on), the workaround is quite easy – simply right-click the file (or the entire zip file if the files were zipped) and click Unblock in the Properties dialog box:

(You can also unblock files from PowerShell command-line – and in bulk! – by using Remove-DownloadFlag from PoshCode module.)

Hope this helps!

Dmitry

PowerGUI Editor 2.1.1 and AD cmdlets 1.4 compatibility issue

[UPDATE] This issue got fixed in PowerGUI 2.2.

We have found that in some cases when you are using version 1.4.0 of QAD cmdlets inside PowerGUI Script Editor 2.1.1, and invoke a script with the cmdlets for the second time you may get the error: “Object reference not set to an instance of an object.

This is obviously very unfortunate and we are working on fixing the issue. In the meantime there are a couple of workarounds you can use:

A. Run Script Editor in MTA mode (if you don’t know what STA/MTA mean – this means that you would likely not notice any difference – but as a side-effect it might affect some script editor add-ons or your scripts using WPF)

To do this, just modify the PowerGUI Script Editor shortcut:

and add the -MTA switch to the command line:

B. Alternatively, you can set PowerGUI Script Editor to reset PowerShell runspace each time you start debugging:

1. In PowerGUI Script Editor, on the Tools menu, click Options,

2. In Debug Options, select Reset PowerShell runspace each time debugging is started.

Again, we appologise for the inconvenience and are working on a perminent fix.

Set -WhatIf ON by default

Making PowerShell safe by default is trivial. Ulf here suggested that “socially responsible” PowerShell needs to use -WhatIf by default for all operations, and actually perform the actions only if explicitly asked to do so.

To make PowerShell operate in this mode, all you need to do is set $WhatIfPreference variable to $true, and use -WhatIf:$false when you do want something to be executed. (colon is mandatory by the way – because this is a switch parameter).

Here’s my session (copy/pasted from PowerShell Console pane of PowerGUI Script Editor):

C:\> $WhatIfPreference
False
C:\> $WhatIfPreference = $true
C:\> $WhatIfPreference
True
C:\> Get-Process notepad

Handles  NPM(K)  PM(K)   WS(K)  Id  ProcessName
-------  ------  -----   -----  --  -----------
     63       3   2372    6668  66      notepad


C:\> Get-Process notepad | Stop-Process
What if: Performing operation "Stop-Process" on Target "notepad (4708)".
C:\> Get-Process notepad | Stop-Process -WhatIf:$false

Tags: , ,

Fastest way to retrieve AD objects

DontUseDefaultIncludedProperties is the AD cmdlets parameter you need when you want to get AD objects fast without extra properties you do not need. For example, I have just used it in my script to locate the largest groups in our Active Directory. Let’s talk about how effective it really is and how it works under the covers.

First, of all, let me prove that it is indeed very efficient. Here’s the same Get-QADUser run 100 times with and without the parameter:

[PS] C:\>Measure-Command { for ($i=0;$i -lt 100;$i++) { $a = Get-QADUser -SamAccountName dsotnikov -DontUseDefaultIncludedProperties } }

...
Seconds : 3
Milliseconds : 951
...


[PS] C:\>Measure-Command { for ($i=0;$i -lt 100;$i++) { $a = Get-QADUser -SamAccountName dsotnikov } }

...
Seconds : 7
Milliseconds : 526
...

That’s twice as fast with the parameter than it is without it!

Why? Because DontUseDefaultIncludedProperties makes the cmdlet only retrieve 2 attributes: distinguishedName и objectClass, whereas the cmdlet without it will go get quite a few other properties.

You can easily see which attributes got retrieved by running:
$a = Get-QADUser -SamAccountName dsotnikov -DontUseDefaultIncludedProperties
$a.Cache.AttributesInCache

The interesting thing is that the cmdlet is even smarter with subsequent use of the object. For most properties (to be specific, for all regular .NET properties of the object but not PowerShell dynamic NoteProperties), we will go and retrieve the property once you request it later on. E.g. this will actually work and give you the account description:

$a = Get-QADUser -SamAccountName dsotnikov -DontUseDefaultIncludedProperties
$a.Description

And this will retrieve a whole bunch of attributes:
Get-QADUser -SamAccountName dsotnikov -DontUseDefaultIncludedProperties | Format-List *

You can obviously keep using $a.Cache.AttributesInCache to check which ones we retrieve.

Pretty cool, isn’t it?

The only other thing I would note is the difference between:

Get-QADUser -SamAccountName dsotnikov -DontUseDefaultIncludedProperties

and

Get-QADUser dsotnikov -DontUseDefaultIncludedProperties

The former is way more efficient than the latter because the -SamAccountName parameter (or any other parameter besides the generic implied -Identity) lets us optimize the query specifically to search by that attribute rather than do the Ambiguous Name Resolution which we use otherwise. Be specific in your parameters and we will give you the fastest results!

Tags: , , , , , ,


My Recent Tweets

Legal

The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

October 2017
M T W T F S S
« Aug    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

%d bloggers like this: