Tuesday, 5 March 2019

Powershell Web Access

Sometimes we used to monitor some websites continually for getting a specific information, like breaking news, online product availability checks etc: Here I am showing how can we capture a website information suing powershell. From the below example I am capturing information from one of the online newspaper and displaying as a popup notification, I used windows form to create the popup notification. Please follow the below script to capture some information from a website and display as a popup notification on your desktop.
There are three faces in this script,                               
  1. Capture the information from a website.
  2. Create a windows form to display the output.
  3. Schedule a task to run the script in a specific time\date.

We are using Invoke-WebRequest PowerShell cmdlet to capture the information from the website, please go through the below Microsoft website to know more about the cmdlet

Before we start we need to have some basic understanding about HTML to identify what is an HTML “Class” and “tags” (Div, H2, UL Etc.), then decide what information we are going to capture from the website and access the DevTool (Developer Console) from the website. Below are some examples to capture the information from the website

Browse the website by typing the URL

Right click on the page (The area which we are going to capture) and click on Inspect (I am using Chrome, it’s Inspect element in IE) to access the DevTool, we can easily identify the required HTML tag and class from DevTool.

As per the above example, we are going to display the news headlines which is arranged using an HTML List tag (UL Tag) and its class name is list8 – Based on the website design change, the HTML class name and tag may get changed. 

Let’s start Part -1 Getting Information from the website

We are going to load the newspaper page on a PowerShell console, before loading the website I have declared some variable for getting the basic details about the website name, URL, html tag and class name

$WebsiteURL = "https://timesofindia.indiatimes.com/"
$WebsiteName = "Time of India"
$Class = "list8"

$TypeClass = "ul"  

I am saving the website page in a variable, please check the below screenshot to know more about the properties of the web request stored in the variable. The variable contains a huge amount of details about the website

$WebRequest = Invoke-WebRequest $WebsiteURL

$News = ($WebRequest.ParsedHtml.getElementsByTagName("$TypeClass"| Where$_.className -eq "$Class" } ) | Select-Object -ExpandProperty innertext -First 1

ParsedHtml – It is basically taking in HTML code and extracting relevant information like the title of the page, paragraphs in the page, headings in the page, links, bold text etc.

GetElementsByTagName – The getElementsByTagName() method returns a collection of all elements in the document with the specified tag name, as a NodeList object.

Part 2 - Creating a Windows form to display the news

Follow my below post about “How to build a form in PowerShell?” to understand more about the windows form.

We have captured the required information from the website and stored in a variable called $News, we need to now display the information on a window, please follow the below cmdlet to create a windows form to hold the information

Basic Form creation cmdlet, I did some customization in our form.

$Form = New-Object system.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(800,400)
$Form.AutoSize = $false
$Form.AutoSizeMode = "GrowAndShrink"
$Form.Text = "News Update"
$Form.StartPosition = "CenterScreen"
$Form.FormBorderStyle = 'Fixed3D'
$Form.KeyPreview = $True
$Form.MaximizeBox = $false

Below is the output display part of the form, you can customize based on your requirement.

$Font = New-Object System.Drawing.Font("Segoe UI",15,[System.Drawing.FontStyle]::Italic)
$outputBox = New-Object System.Windows.Forms.TextBox
$outputBox.Location = New-Object System.Drawing.Size(10,10)
$outputBox.Size = New-Object System.Drawing.Size(780,330)
$outputBox.Font = $Font
$outputBox.MultiLine = $True
$outputBox.ScrollBars = "Vertical"
$outputBox.BackColor = "skyblue"
$Date = get-date
$OutputBox.AppendText("Updated : $Date")

Below is the hyperlink creation in form in the bottom of the window to navigate to the website to read more information

$LinkLabel = New-Object System.Windows.Forms.LinkLabel
$LinkLabel.Location = New-Object System.Drawing.Size(10,345)
$LinkLabel.Size = New-Object System.Drawing.Size(100,50)
$LinkLabel.LinkColor = "BLUE"
$LinkLabel.ActiveLinkColor = "RED"
$LinkLabel.Text = "$Websitename"

Now add all the controls to form and display the output


Finally, below is the output

Part-3 Schedule a task to run the script in a specific time\date.

Now we can run the below PowerShell command for scheduling our news update. Please note that the task scheduler command works only on the latest Powershell version, if you are using old PowerShell version, please import the module frPowerShellell gallery.

$Trigger= New-ScheduledTaskTrigger -At 10:00am –Daily
$UserDetails = "administrator"
$Action= New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "D:\Powershell Script\NewsScript.ps1"
Register-ScheduledTask -TaskName "NewsUpdate" -Trigger $Trigger -User $User -Action $Action -RunLevel Highest –Force

Bellow is the another example of collecting HTML details from an online shopping website, we can create a script to get notifications for product availability - Please try to create the script. 

Friday, 22 February 2019

Word documentation using PowerShell

Powershell With MS Word

Recently I got a request from one of my friend for automating the word document editing which was very interesting for me. When we need to create a word reports on a regular basis, we can automate this to avoid spending more time on documentation, sometimes it’s boring to do the same reports every day by changing a few items in the documents (It’s my friend’s comment), also we may miss to change something like date, name etc. in the document which is very important. We can automate documentation when we pull the reports from either a server, system or from a database using PowerShell and insert the report into the word document to have an automated word documenting system. We can also trigger an email from PowerShell by attaching this word documents which means reports are fully automated 
We are using com abject to interact with office application from PowerShell.  Below are the com object for office application and we are using the word com abject to interact with word using PowerShell.


Please refer the below link to understand more about office Object model.  Before we start, make sure that we have installed MS office application on the machine
New-Object -ComObject Word.Application
I have highlighted the important properties in the object, please have a look.

As soon as you executed the cmdlet, you can see a word process in the task manager, please go to task manager and check if you got a word process (Close all the other word document you opened before executing the cmdlet to make sure that that word is executed from PowerShell)

You can also check the process status using PowerShell as shown below.

We need to enable the word visibility if you need to see the word document on the screen. I have highlighted the “Visible” property in the screenshot for your reference. To enable the visibility, follow the below cmdlet, this cmdlet is same for all the office applications.

$Word.Visible = $True

Once you execute the cmdlet you can see the Microsoft Word pup up with a blank page

Let’s start - I am printing a simple asset inventory report in the word document, this is a small example which shows how to create, format and save the word document using PowerShell

$Word = New-Object -ComObject word.application $Word.Visible = $true
$Docs = $Word.Documents.Add()
$Selection = $Word.Selection

Below are the few formatting which I have done, you can see the word color code from the below link, please note that some of  the formattings do not work if you are not using the latest PowerShell version

$Selection.Style = 'Heading 1'
$Selection.Font.Bold = 1
$Selection.Font.Color = '26367'

After the formatting, we can start adding the information into the word document. The information can be stored in a PowerShell variable after collecting from preferred sources, I am collecting a few system information using a WMI query and passing the information to a word document. Below is the information I am collecting for our word document.

$Sysdetails = Get-WmiObject -Class Win32_computersystem  | select -ExpandProperty TotalPhysicalMemory
$Osname = Get-WmiObject -Class Win32_OperatingSystem | select -ExpandProperty caption

I have collected the machine's operating system name and total physical memory available on the machine Follow the below command to write the collected information in a word document, after executing the command you can see the information is appearing in the word document, I have used a TypeParagraph() command which will print the details in the next line

$Selection.TypeText("Server Inventory Report for $(get-date) ")
$Selection.TypeText("Operating System Name = $osname")
$Selection.TypeText("Physical Memory = $sysdetails")

Finally, we got the below word document created using PowerShell 😊 

We need to save the document now, follow the below command to save the word document. $WordPath = "D:\Temp\TestDocument.docx"

I just covered a very basic topic in this session for you to start using the PowerShell to create a word document, please explore more about adding content, formatting, editing etc. I am planning to post another session with more details on creating a word document using PowerShell.
Click here to download the script

Saturday, 31 March 2018

SCCM Device Collection Details with No deployment

How to get SCCM collection names where No deployments are targetted?

Sometimes we need to clear all the unwanted collection as part of our SCCM maintenance activity. Usually, we used to delete the device collection from the Assets and Compliance workspace, select Device Collections, check the collection members and it's targetted deployments, right click on the collection and delete. This task will take a lot of time if we have a huge number of collections in our organization, So I thought of to automate this process using PowerShell script.I have also included the collection's member count which will be helpful in case if we need to delete the collection based on the collection's member count

Please follow the below PowerShell script to check SCCM device collections with No deployment and delete it if the collection is no longer required.

We need to modify the report path in the 1st line of this script, highlighted in yellow

$reportpath = "K:\OSDLogs\Result.csv" # Provide CSV path with CSV Name

Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + '\ConfigurationManager.psd1')
$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-location $SiteCode":"
$details = @()
$CollectionList = Get-CmCollection | Where-Object {$_.CollectionID -notlike 'SMS*' -and $_.CollectionType -eq '2'} | Select-Object -Property Name,MemberCount,CollectionID,IsReferenceCollection

foreach ($Collection in $CollectionList)
    $NumCollectionMembers = $Collection.MemberCount
    $CollectionID = $Collection.CollectionID
    $GetDeployment = Get-CMDeployment | Where-Object {$_.CollectionID -eq $Collection.CollectionID}  
    if ($GetDeployment -eq $null)
        $collectionName = $Collection.Name
        $Membercount = $Collection.MemberCount
        $Result = [ordered]@{
        Collection_NAME     = "$collectionName"
        Member_Count     = "$Membercount" }
        $Details += New-Object PSObject -Property $Result

The output of this script will be as shown below - 

As per the above script, we are not deleting the collection which doesn't have any deployments targetted to it. If we wanted to delete the collections with no deployments targetted, we need to modify the script under "IF" loop as shown below. 

Please note: The collection will be deleted forcefully without any notifications as per the below script, you can make the modification if required

        Remove-CMCollection -Id $CollectionID -Force
        $collectionName = $Collection.Name
        $Membercount = $Collection.MemberCount
        $Result = [ordered]@{
        Collection_NAME     = "$collectionName"
        MemberCount     = "$Membercount" }
        $Details += New-Object PSObject -Property $Result

Click here to download the script