Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Wednesday, January 30, 2013

Installing Windows Server 2012 Hyper-V

Windows Server 2012 Hyper-V server is essentially Windows Server 2012 Server Core that is designed in only run Hyper-V.  You do not have to worry about purchasing a license for Hyper-V server.  The Host OS is free.  You do need to properly license any virtual machines (VMs) that you run on the Hyper-V server however.

Setup is a breeze. It was, for the most part, just like installing Server Core.  It is also very fast.  Just download the installation software from Microsoft. For this deployment, I plugged a keyboard, mouse , and monitor into my target server so I can observe all the action.  Really, there is not much to watch once you get things started.

Once the server starts up, you need to give it a password for the local administrator account. Then SCONFIG opens up.  Use SCONFIG with the following options to place this server in your domain and make it manageable.

8) Give this server a static IP address.

1) Add to the domain.  You can also rename it with this option.

7) Allow remote desktop connections to this server.

At this point, you can unplug the monitor, keyboard, and mouse.

Once the Hyper-V server reboots, go ahead and configure either your Windows Server 2012 graphical server or Windows 8 client with RSAT to manage this server.

In Server Manager, click All Servers.

Right click All Servers and select Add Server.

In the name field, type the name of your Hyper-V Server and click Find Now.

Select your server from the list and click the right pointing arrow.

Click OK.

In a few minutes, your Hyper-V server will be manageable from your Server 2012 or Windows 8 client.


Open Hyper-V on your graphical client.

Right click Hyper-V Manager and select  Connect to Server.

Type the name of your server and press Enter.

You can now manage the VMs running on this Hyper-V Server.

Monday, January 28, 2013

How to speed up the time out process in PowerShell

While executing scripts against a large number of clients in your organization, you will undoubtedly encounter a few that are offline.  This causes your script to hang on each one.  This pesky little behavior can be mitigated in a variety of ways.  The function below is what I use when I need to run a script synchronously.  You simple give it the name of the client you are attempting to contact and the number of retries it gets.  I usually only give it 1.  It will return TRUE if contact was made.  You then make a decision of what to do at that point. I allow the script to proceed if the response is TRUE or I send the client name to an error log if it is FALSE.
Function Test-ClientConnectivity
Param (
    $Loop = 4)

    # Set the control value to zero.
    $Count = 0
    Do {
        $Count ++
        $Result = Test-Connection $ComputerName -Count 1 -Quiet
        If ($Result)
            # If a positive responce is recieved, set the value
            # high to exit the loop.
            $Count = 1000000

    } while ($Count -lt $Loop)

    # Return the object to the calling statment.
    Write-Output $Result
} # End Function: Test-CliectConnectivity -------------------------------------

Wednesday, January 23, 2013

When did a client last start?

This is a question that I often have to ask a user.  The problem is that our users answers cannot always be considered…shall we say “reliable.”  Below is a PowerShell function that you can use to to determine when the client in question was last started.  Here is what you get when you run this function.

PS C:\windows\system32> Get-LastStartTime -ComputerName Work-PC

Last Startup Time: 12/31/2012 1:44:43 PM

I’m using this as part of the HelpDesk module that I creating for my up coming book and also I’ll be demonstrating the full module at the Cincinnati PowerShell users group meet up on Thursday, February 21, 2013.  Here is a link to the event.  Our focus will be on using PowerShell with your Help Desk.

# .............................................................................

# Function Get-LastStartTime

# Retrieves the last start time on the client machine.

Function Get-LastStartTime


Param ($ComputerName = ".",





    If (!$Quiet)


        Write-Host "Last Startup Time: " `

         -ForegroundColor Cyan `

         -BackgroundColor DarkBlue `





    $Events = Invoke-Command -ScriptBlock {



            $LogHash = @{LogName = 'System'; ID = 6005}

            Get-WinEvent -FilterHashtable $LogHash `

             -MaxEvents 1 `

             -ErrorAction Stop









        } -ComputerName $ComputerName


    If (!$Quiet)


        If ($Events -ne $Null)

        {Write-Host ($Events.TimeCreated).ToString() `

         -ForegroundColor Green `

         -BackgroundColor DarkBlue}


        {Write-Host "Could not determine the last start time." `

         -ForegroundColor Red `

         -BackgroundColor DarkRed}




    # If $Passthru is enabled, then return the results of this test

    # to the PowerShell pipeline.

    If($PassThru) {Write-Output $Events}






Returns the time the client was last started.



Returns the time the client was last started.


.PARAMETER ComputerName

the name of a client to connect to.



Returns the test result from this cmdlet.



Get-LastStartTime -ComputerName Work-PC

Last Startup Time: 12/31/2012 1:44:43 PM



Get-LastStartTime -ComputerName Work-PC -PassThru

Last Startup Time: 12/31/2012 1:44:43 PM


   ProviderName: EventLog


TimeCreated           Id   LevelDisplayName Message                                                          

-----------           --   ---------------- -------                                                         

12/31/2012 1:44:43 PM 6005 Information      The Event log service was started.    



} # End Function: Get-LastStartTime -------------------------------------------

Monday, January 21, 2013

Use PowerShell to Rebalance Your Portfolio

Years ago I was introduced to portfolio rebalancing by a friend that I used to work with.  In short, portfolio rebalancing allows you to sell off some stock in funds that have increased in value, and then buy more shares in funds that have decreased in value.  This allows you to sell high, buy low.  The company that currently manages my business retirement plan does not have an option for this, but I am allowed to transfer funds between different investments without fees.

Below is an example of two concepts that I use in my PowerShell classes.  One is how to gather information from the internet and the other is how to use the XML variable type in PowerShell.  You will have to create a CSV file that contains three pieces of information.  FUND, QUNATITY, ALLOCATION.  The Fund will be the ticker symbol for a stock or mutual fund.  The quantity will be how much of that fund you own.  The allocation is a percentage of how much of your portfolio you want that investment to consume.  Make sure the allocation column totals 100%.

Function Rebalance-Portfolio
Param (
    [Parameter(Position=0, Mandatory=$TRUE, ValueFromPipeline=$TRUE)]
#-- Support Functions ---------------------------------------------------------
 function Get-StockInfo
       param ($Sym)
       $Data = @()
       $Data += "Symbol,Name,Ask,Low,High,Low52,High52,Volume,DayChange,ChangePercent"
       $URL = "$Sym&f=snl1ghjkvw4P2"
       $Data += Invoke-RestMethod -Uri $URL
       $Data += "`n"
       $Data = $Data | ConvertFrom-csv
       Write-Output $Data
} # END: function Get-StockInfo

#-- End Support Functions -----------------------------------------------------

    # Import the portfolio file.
        $Funds = Import-csv -Path $Portfolio
        Write-Host "Data file not found." `
         -ForegroundColor Red `
         -BackgroundColor DarkRed

    # Object to hold stock information
    $StockInfo = @()

    # Total value of the portfolio
    [Single]$TotalValue = 0

    # Populate an object for each fund.
    ForEach ($Fund in $Funds)
            $Symbol = $Fund.Fund
            #$Info = Get-FundQuote -TICKER $Symbol
            $Info = Get-StockInfo -Sym $Symbol
            $Obj = New-Object -TypeName PSObject
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "Fund" `
                -Value $Info.Symbol
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "Quantity" `
                -Value $Fund.Quantity
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "PreviousClose" `
                -Value $Info.Ask
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "CurrentValue" `
                -Value ([Single]$Fund.Quantity * [Single]$Info.Ask)
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "Allocation" `
                -Value $Fund.Allocation
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "AllocationGoal" `
                -Value 0
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "ChangeAmount" `
                -Value 0
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "ChangeShares" `
                -Value 0
            $Obj | Add-Member -MemberType NoteProperty `
                -Name "NewShareBalance" `
                -Value 0
          $TotalValue += ([Single]$Fund.Quantity *[Single]$Info.Ask)
          $StockInfo += $Obj


    # Figure out allocations.
    ForEach ($Stock in $StockInfo)
        $Stock.AllocationGoal = "{0:N2}" -f ($TotalValue*([Single]$Stock.Allocation*.01))
        $Stock.CurrentValue = "{0:N2}" -f $Stock.CurrentValue
        $Stock.ChangeAmount =  $Stock.AllocationGoal - $Stock.CurrentValue
        $Stock.ChangeShares = "{0:N3}" -f ($Stock.ChangeAmount/$Stock.PreviousClose)
        $Stock.NewShareBalance = "{0:N3}" -f ([SINGLE]$Stock.Quantity + [SINGLE]$Stock.ChangeShares)
    $StockInfo | FT -AutoSize
Determines fund rebalancing amounts.

Returns the mutual fund reallocation amounts provided through a CSV file.  This
allows the user to properly rebalance an investment portfolio.  The CVS
file format is:
Fund, Quantity, Allocation

FUND: The ticker symbol of the mutual fund.
QUANTITY: The current quantity of the fund held.
ALLOCATION: The percentage that this fund should be of the total portfolio
if the portfolio was balances.

Once executed, the ChangeAmount property well tell the user how many dollars
of a fund should be purchased (Positive amount) or sold (Negative amount) in
offer to balance the portfolio.

Fund: One of your mutual funds.
Quantity: The amount of shares that you own.
PreviousClose: The last price of these shares.
CurrentValue: How much of the fund you own in dollars.
Allocation: A percentage of how much of your portfolio should be invested in
            this fund.
ChangeAmount: The number of dollars you need to buy or sell to bring this
              fund into balance.
ChangedShares: The number of shares you would have to buy or sell to bring
               this fund into balance.
NewShareBalance: The number of shares you need in each fund to bring them
                 into balance.

.PARAMETER Portfolio
The fill path of the CSV file containing the users portfolio data.  Referred
to the help file description for the proper format.

Rebalance-Portfolio -Portfolio "C:\Users\Jason\Documents\PowerShell\Code\Portfolio2.csv"

Fund  Quantity PreviousClose CurrentValue Allocation AllocationGoal ChangeAmount ChangeShares NewShareBalance
----  -------- ------------- ------------ ---------- -------------- ------------ ------------ ---------------
USAUX 290.769  33.51         9,511.05     25         8,757.31               -754 -22.501      268.268      
USCGX 383.996  7.03          2,638.05     5          1,751.46               -887 -126.174     257.822      
USEMX 353.756  17.98         6,236.72     15         5,254.39               -983 -54.672      299.084      
USGRX 294.151  16.57         4,759.36     15         5,254.39                495 29.873       324.024      
USAAX 374.512  17.30         6,321.76     20         7,005.85                684 39.538       414.050      
USISX 408.992  13.91         5,562.29     20         7,005.85               1444 103.810      512.802      

The ChangeAmount column tells you the dollar amount of shares that need to be
bought or sold for each fund in order to bring your portfolio into