Michael's profileThe Old Dogs Scripting B...BlogListsNetworkMore Tools Help

Blog


    December 05

    Excel 'sheetToCopy'

    Whenever I see a post from Kiron I know it will be good.


    This copies the 'sheetToCopy' sheet from a source workbook (Book1.xlsx) to a destination workbook (Book2.xlsx).
    I've commented the steps but if you'd like a better description of the process let me know and I'll try my best...

    $file1 = 'C:\Book1.xlsx'                            # source's fullpath
    $file2 = 'C:\Book2.xlsx'                       # destination's fullpath
    $xl = new-object -c excel.application
    $xl.displayAlerts = $false                      # don't prompt the user
    $wb1 = $xl.workbooks.open($file1, $null, $true) # open source, readonly
    $wb2 = $xl.workbooks.open($file2)                         # open target
    $sh1_wb2 = $wb2.sheets.item(1)    # first sheet in destination workbook
    $sheetToCopy = $wb1.sheets.item('sheetToCopy')   # source sheet to copy
    $sheetToCopy.copy($sh1_wb2) # copy source sheet to destination workbook
    $wb1.close($false)                   # close source workbook w/o saving
    $wb2.close($true)                 # close and save destination workbook
    $xl.quit()
    spps -n excel

    --
    Kiron

    November 19

    Search Email AND output TAB delimited

    I was trying to help someone who wanted a TAB delimited output file in PowerShell.
     
    After some searching around and some help from the boards, I came up with this;
     
    <------------ Start POSH ----------------------------------------------------------------->
     
    $info = New-Object -ComObject Outlook.Application
    $objNamespace = $info.GetNamespace("MAPI")
    $objFolder = $objNamespace.GetDefaultFolder(6).Folders.Item("Reporting")
    $colItems = $objFolder.Items
    foreach ($item in $colItems) {
     If ($item.SenderEmailAddress -eq "Bill.Smith@myob.com") {
     Write-Host "$($item.SenderEmailAddress) `t $($item.SentOn) `t $($item.Subject)"
                       }
            }
     
    <-----------End Script ---------------------------------------------------------------------->
     
    Or you could output to a file by removing the Write-Host and adding | Add-Content $path
     
    <----------------- Start POSH --------------------------------------------------------------> 
    $path = "c:\temp\email.txt"
    $info = New-Object -ComObject Outlook.Application
    $objNamespace = $info.GetNamespace("MAPI")
    $objFolder = $objNamespace.GetDefaultFolder(6).Folders.Item("Merchant Reporting")
    $colItems = $objFolder.Items
    foreach ($item in $colItems) {
     If ($item.SenderEmailAddress -eq "Bill.Smith@myob.com") {
    ("$($item.SenderEmailAddress) `t $($item.SentOn) `t $($item.Subject)")| Add-Content $path
                       }
            }
     
    < -------------- End Script ---------------------------------------------------------------------------->
    What does it do?
     
    Searches the In box for a sub folder and then for a sender.
    writes them out to the screen or a file in a tab delimited format
    Includes Senders name, Date/time sent and subject.
    Its the `t that adds the tabs. `n adds a new line.  'r adds a line feed  
     
    November 13

    How do I find the last used row in Excel

    So I saw a question on the Posh board yesterday and being a wise guy, I had to answer it.
     
    Q:
    I know how to open spreadsheet via powershell, question is whether there is
    a way to determine the rows that contain data

    Eg  I coded row less than 5000

    for($row = 2; $row -lt 5000; $row++)
    {

    ## i m looking at cell 1, so if cell 1 on the next row is empty, i will quit
    the program
     $computername = $ws.Cells.Item($row,1).text
     if ($computername.length -eq 0) {exit}

    }

     Is there a way to define number of rows rather than i put a number of 5000
    or any other number  ?
     
    My Answer:
     
    You could try selecting the Active Range. That is all the Rows and
    columns that have Data in them;
    Then you go to the last used row;

    In Powershell;

    <------ PS Script ---------------------------------> 

    $xlCellTypeLastCell = 11
    $xl = New-Object -c excel.application
    $wb = $xl.Workbooks.Open("C:\Scripts\Book5.xlsx")  #<-- Your spreadsheet name goes here
    $sh = $wb.worksheets.item('Sheet1') #<-- the sheet number or name goes here.
    $xl.visible = $true
    $used = $sh.usedRange
    $lastCell = $used.SpecialCells($xlCellTypeLastCell)
    $newRow = $lastCell.row + 1
    $sh.cells.item($newRow, 1).value2 = 'This is the new last row now'

     <----------- End Script --------------------------------->

     Or in vbScript

    <------vbScript --------------------------------->

    Const xlCellTypeLastCell = 11
    Set oXL = CreateObject ("Excel.Application")
    oXL.Visible = True
    oXL.DisplayAlerts = False

    Set objWorksheet = book1.Worksheets(1)
    Set objRange = objWorksheet.UsedRange
    objRange.SpecialCells(xlCellTypeLastCell).Activate
    intNewRow = oXL.ActiveCell.Row + 1
    strNewCell = "A" &  intNewRow
    oXL.Range(strNewCell).Activate

    <----------- End Script --------------------------------->
     

     
    November 12

    Is It Unix or Windows ?

     

    So someone hands you list of servers and they want to know everything there is to know about said servers by COB today.

     
    Time for a script! But wait, when you run your script, you get several servers that do not reply or give you RPC failures.
    Are they dead? Disconnected? or are they Unix?
     
    Vadims Podāns on the PowerShell google group had this to say,
    Well, here is a quick and dirty way to find out if they are Unix or Windows.
    You can simply ping remote the host.
    By default all *nix (Linux) reply with TTL=64 and Windows hosts reply with
    TTL=128 this helps only determine the host is UNIX or not and you will unable to
    determine Unix version. Be aware that at ICMP packet passage through each router ttl decreases by 1.
     
    So using Vadims information, I came up with this Posh script.
    #<---------------- Begin ----------------------------------------------->
    $ping = New-Object System.Net.NetworkInformation.Ping
    $computerlist = Get-Content 'c:\scripts\Servers.txt'
    foreach ($srv in $computerlist)
    {
            $reply = $ping.Send($srv)
            if ($reply.status -eq "Success")
            {
                    if ($reply.Options.ttl -le 64)
                    {
                    Write-Host $srv " probably is a Unix host"
                            }
                    Else
                            { if ($reply.Options.ttl -ge 65)
                                    {
                            Write-Host $srv " probably is a Windows host"
                                    }
                    }
            }
            Else { Write-Host $srv " Does Not Ping"
                     }
    }
    #<----------------------- End Script -------------------------------------­----->
     
    So I was getting some inconsistent results on my Vista work station, so I re-wrote the script like so;
     
      $computerlist = Get-Content 'c:\scripts\Servers.txt'
     foreach ($srv in $computerlist)
     {
    $response = Get-WmiObject -query "Select * From Win32_PingStatus Where Address = '$srv'"
     
      if( ($response -eq $null) -or ($response.StatusCode -ne 0)) {
                    Write-Host $srv " Does Not Ping"
            } else { if ($response.TimeToLive -le 64)
                           {
                    Write-Host $srv " probably is a Unix host"
                            }
                    Else {
                            Write-Host $srv " probably is a Windows host" 
                           }
                    }
            }
     

    Setting up SNMP via a script

    I have been trying to do this for way too long. There does not seem to be a way that I understand to set up SNMP via a script.
     
    I did, however discover this little gem;
     
    sysocmgr that you can read about here: http://support.microsoft.com/kb/222444
     
    Usage:
     
    sysocmgr /i:c:\Windows\inf\sysoc.inf /r /u:c:\temp\snmp_cfg.txt
    And \c:\temp\snmp_cfg.txt looks like this:
     
    [Components]
    NetOC=on
    [NetOptionalComponents]
    SNMP=1
    [SNMP]
     Accept_CommunityName = public:Read_Create
     Any_Host = Yes
     Community_Name = public
     Contact_Name = "OldDog"
     Location = "MYOB, SF, Ca"
     Traps = 172.xx.xxx.xxx <- where you want them sent. My HP-SIM server or SCOM or wherever.
     Service = Physical, Applications, Datalink, Internet, End-to-End
    November 07

    Reading Email with a script and doing stuff

    I am setting up HP-Sim for a client. One of the things they wanted was for SIM alerts to go directly to their Incident manager software.
    If the Email is formatted correctly, it will generate a Trouble Ticket automatically. Unfortunately, the email from HP-Sim is set in stone.
    You can change the subject line but not the body of the message. And that's where my customer needs the properly formatted information.
    So, I set up a Rule in Outlook that runs an application upon receipt of a message with specified words in the Subject line.
    The scrip reads the mail, and then re-sends it to the help-desk app in the proper format. 
    Here is the script, I think it's a good example of how to read and act upon an email message.
     
    <--------------VBScript ------------------------------------->
     
    Set objOL = WScript.CreateObject ("outlook.application")
    Set olNS = objOL.GetNameSpace("MAPI")
    Set fld = olNS.GetDefaultFolder(6)
    set msg = fld.items
     
      For Each item In msg
     
        If item.SenderEmailAddress = "system.generated@myob.com" Then '<--- must come from this address
          ProductionMsg = item.body ' <---- all the info in the message
          Mailit(ProductionMsg)
        Else
                 On Error GoTo 0
                 WScript.Quit
        End If
     Next
    Sub Mailit(ProductionMsg)
    adminmail = "helpdesk@myob.com"
    '
    Cat="Category=System Generated Requests" '<-this is what the Incident Manager wants to see
    CatSub="CategorySub=HP-SIM" '<-this is what the Incident Manager wants to see
    Sev="Severity=Tier 3"  '<-this is what the Incident Manager wants to see
    ProductionMsg = Cat & VbCrLf & CatSub & VbCrLf & Sev & VbCrLf &  VbCrLf & ProductionMsg
     smtp = "smtp.myob.com"
     Set mailing = CreateObject("CDO.Message")
     Set wshNet = CreateObject("WScript.Network")
     
     mailing.From = ("system.generated@myob.com")
     mailing.To = adminmail
     mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
     mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtp
     mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
     
    ' Only required if your SMTP server requires a user name and password

    'mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = cdoBasic
    'mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusername") = "Ja...@company.com"
    'mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "SomePassword"



    mailing.Subject = header & "HP-Sim Alert"
     mailing.TextBody = ProductionMsg
     mailing.Configuration.Fields.Update
     mailing.Send
     On Error GoTo 0
    End Sub
    <----------- End VBScript --------------------------------->
     
    You can also do stuff with PowerShell;
     
    <------------POSH Script ---------------------------------->
    $info = New-Object -ComObject Outlook.Application
    $objNamespace = $info.GetNamespace("MAPI")
    $objFolder = $objNamespace.GetDefaultFolder(6).Folders.Item("HPSIMNotify")
    $colItems = $objFolder.Items
    foreach ($item in $colItems) {
     Write-Host $item.SentOn
    }
     
    <---------------End POSH Script ----------------------------------------------->
     
    This looks in the inbox (6) and looks for a sub folder called ("HPSIMNotify")
    It then tells you the date and time the message was sent.
     
    What other folders can you look in?
     
    Name Value Description
    olFolderCalendar 9 The Calendar folder.
    olFolderConflicts 19 The Conflicts folder (subfolder of Sync Issues folder). Only available for an Exchange account.
    olFolderContacts 10 The Contacts folder.
    olFolderDeletedItems 3 The Deleted Items folder.
    olFolderDrafts 16 The Drafts folder.
    olFolderInbox 6 The Inbox folder.
    olFolderJournal 11 The Journal folder.
    olFolderJunk 23 The Junk E-Mail folder.
    olFolderLocalFailures 21 The Local Failures folder (subfolder of Sync Issues folder). Only available for an Exchange account.
    olFolderManagedEmail 29 The top-level folder in the Managed Folders group. For more information on Managed Folders, see Help in Microsoft Office Outlook. Only available for an Exchange account.
    olFolderNotes 12 The Notes folder.
    olFolderOutbox 4 The Outbox folder.
    olFolderSentMail 5 The Sent Mail folder.
    olFolderServerFailures 22 The Server Failures folder (subfolder of Sync Issues folder). Only available for an Exchange account.
    olFolderSyncIssues 20 The Sync Issues folder. Only available for an Exchange account.
    olFolderTasks 13 The Tasks folder.
    olFolderToDo 28 The To Do folder.
    olPublicFoldersAllPublicFolders 18 The All Public Folders folder in the Exchange Public Folders store. Only available for an Exchange account.
    olFolderRssFeeds 25 The RSS Feeds folder.
     
    Want to see what the body of the message looks like?
     
    Write-Host $item.body
     
    How about the subject?
     
    Write-Host $item.Subject
     
    All together now;
     
    <------------- Begin POSH Script -----------------------------------------------------> 
    $info = New-Object -ComObject Outlook.Application
    $objNamespace = $info.GetNamespace("MAPI")
    $objFolder = $objNamespace.GetDefaultFolder(6).Folders.Item("HPSIMNotify")
    $colItems = $objFolder.Items
    foreach ($item in $colItems) {
     Write-Host "date/time sent: "$item.SentOn
     Write-Host "Subject: " $item.Subject
     Write-Host "Body Text: "$item.body
    }
     <-------------- End POSH Script --------------------------------------------------->
     
     

    October 24

    Powershell and HP Sim

    I just ran across something that I found interesting.
    If you use HP/Compaq servers and you have installed the Management agents,
    You will find a Name Space called root\HPQ that has 363 classes associated with it.
     
    Basically, every thing the HP Management agents know about the server is available.
     
    I found it by using the Scriptomatic PowerShell Version by Ed Wilson.
    Avilable here:
     
    While I have not gone through every Class, I think this opens up a whole new world to us scripting maniacs.
     
    Enjoy!
    October 23

    Short File and Path Names

    I know you can quote your strings to get around long file names and even longer path names. It also helps with spaces in the names.
    However, getting the quotes in the right places is often a pain, so I use short file names whenever I can.
    One of my customeres was worried that a new file or directory could be created and change the number of my file or directory.
     
    For example;
     

    10/21/2008  12:55 PM    <DIR>          CONFIR~4     ConfirmTHEOrder

    10/17/2008  09:39 AM    <DIR>          CONFIR~3     ConfirmTHEClub

    10/17/2008  09:39 AM    <DIR>          CONFIR~2     ConfirmTHEClubUS

    10/21/2008  09:25 AM    <DIR>          CONFIR~1     ConfirmTHEOrders

     

    What would happen if another directory was created between THEOrder and ConfirmTHEOrders?

     

    So I did a little looking around and found this.

     

    Set objFile=objFSO.GetFile(strPath1)
        strCMD1="Wscript " &  objFile.ShortPath

     

    That's right, I put the fully quallified path in strPath1 and it returns the short path name.

    Too cool.

     

    Here is the sample I found by Jeffery Hicks for wrapping up powershell in a VBScript:

     

    Dim objShell,objFSO,objFile

    Set objShell=CreateObject("WScript.Shell")
    Set objFSO=CreateObject("Scripting.FileSystemObject")

    'enter the path for your PowerShell Script
    'strPath="e:\documents and settings\jhicks\my documents\scripts\posh\Get-DiskSize.ps1?

    'verify file exists
    If objFSO.FileExists(strPath) Then
    'return short path name
        set objFile=objFSO.GetFile(strPath)
        strCMD="powershell -nologo -command " & Chr(34) & "&{" &_
         objFile.ShortPath & "}" & Chr(34)
        'Uncomment next line for debugging
        'WScript.Echo strCMD

        'use 0 to hide window, True makes it wait until it's finishes.
        objShell.Run strCMD,0, True

    Else

    'Display error message
        WScript.Echo "Failed to find " & strPath
        WScript.Quit

    End If

     

    In case you are wondering; the Chr(34) puts a double quote in the string.

    Yet another way of dealing with quotes.

     


    Or in Pure Powershell:


    $a = New-Object -ComObject Scripting.FileSystemObject $f = $a.GetFile("C:\Program Files\Internet Explorer\ExtExport.exe") $f.ShortPath

    October 15

    Sending mail with PowerShell

    The process to send mail is pretty simple.
    It's the attachment process that gets a little complicated.
     
    I found this at http://blogs.inetium.com/blogs/mhodnick/archive/2006/11/29/powershell...

    Which answered the question, How do I attach a file?

    [System.Net.Mail.Attachment] $attachment = new-object
    System.Net.Mail.Attachment $file

    It is necessary to cast the $attachment variable to type
    System.Net.Mail.Attachment, since new-object (in this instance)
    returns a REFERENCE to an object of that type, not an ACTUAL OBJECT of
    the type. But $msg.Attachments.Add($attachment) requires an actual
    object. Hence the need for the cast.

    So, here is my working code, enjoy!
     
    #<-------------- Begin ----------------------------------------->
    $file = "r:\dailylog.txt" <----the file you want to attach
    $sender = "joe@work.com"
    $recipient = "susie@work.com"
    $server = "mail.smtp.com"
    $subject = "Sending a File " + [System.DateTime]::Now
    $body = "I'm sending a file!"
    $msg = New-Object System.Net.Mail.MailMessage $sender, $recipient, $subject, $body
    $attachment = New-Object System.Net.Mail.Attachment $file
    $msg.Attachments.Add($attachment)
    $client = new-object System.Net.Mail.SmtpClient $server
    $client.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
    $client.Send($msg)
     
    #<--------------------End----------------------------------------->

    from Shay Levy
    Windows PowerShell MVP
    http://blogs.microsoft.co.il/blogs/ScriptFanatic
    PowerShell Toolbar: http://tinyurl.com/PSToolbar

    To add 2 recipients
    $msg.To.Add("te...@domain.com")
    $msg.To.Add(te...@domain.com)
    In the same way add cc and bcc:
    $msg.cc.Add(...)
    $msg.bcc.Add(...)

    To compare and contrast here is basicaly the same thing in vbScript;
     
    '<------------Begin----------------------------------------------->
     
    adminmail = "somebody@somewhere.com"
    '
     smtp = "mail_server name or IP"
     Set mailing = CreateObject("CDO.Message")
     Set wshNet = CreateObject("WScript.Network")
     
     mailing.From = ("fromSomeone@somewhere.com")
     mailing.To = adminmail
     mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
     mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtp
     mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
     mailing.Subject = header & "Data Transfer Success logs"
     sFullProductionMessage = "See attached file..."  & vbcrlf
     mailing.TextBody = sFullProductionMessage
     mailing.Configuration.Fields.Update
     mailing.AddAttachment "R:\dailylog.txt"
     mailing.Send
     On Error Goto 0
     
    '<---------------------------- END ----------------------------------->
     
    What if you wanted the Attachment to be the body text?
     
    Dim fso, f
    Set fso = CreateObject("Scripting.FileSystemObject")
    'Open the file for reading
    Set f = fso.OpenTextFile("C:\SendLogs\dailylog.txt", ForReading)
    'The ReadAll method reads the entire file into the variable BodyText
    BodyText = f.ReadAll
    'Close the file
    f.Close
    Set f = Nothing
    Set fso = Nothing
     
    And in your message function or sub or whatever;
     
     mailing.TextBody = BodyText
     
    How about CC?
     
     
     If you want to send an SMS (text) msg to a phone, just use the phone number and the appropriate SMTP gateways.
    October 12

    You can use the BorderAround() Method to set a border on a range:

    Yet another fine example from Kiron on the Powershell discussion board.
    http://groups.google.com/group/microsoft.public.windows.powershell/topics?hl=en


    You can use the BorderAround() Method to set a border on a range:

    # some Excel Constants used in the sample 

    # for more Constants you can look here

    # http://cid-c2db05eefa6c21a1.skydrive.live.com/browse.aspx/Public

    # line styles
    $xlLineStyleNone = -4142
    $xlContinuous = 1
    $xlDash = -4115

    # line weight
    $xlThin = 2
    $xlMedium = -4138
    $xlThick = 4

    # color index
    $xlColorIndexBlue = 5 # <-- depends on default palette

    # border index
    $xlEdgeLeft = 7
    $xlEdgeTop = 8
    $xlEdgeBottom = 9
    $xlEdgeRight = 10

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

    $xl = new-object -c excel.application
    $wb = $xl.workbooks.add()
    $sh = $wb.worksheets.item('Sheet1')
    $xl.visible = $true
    $range1 = $sh.range('b2:d4')
    $range2 = $sh.range('f2:h4')
    $range3 = $sh.range('b6:d8')
    $range4 = $sh.range('f6:h8')

    # thin blue border on a $range1; [void] suppresses the method's output
    [void]$range1.borderAround($xlContinuous,$xlThin,$xlColorIndexBlue)

    # set a medium border on $range2 (automatic color index)
    [void]$range2.borderAround($xlContinuous,$xlMedium)

    # medium blue dash border on $range3
    [void]$range3.borderAround($xlDash,$xlMedium,$xlColorIndexBlue)

    # set a thick line border on $range4 (automatic color index)
    [void]$range4.borderAround($xlContinuous,$xlThick)

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

    # to clear a range's borders, set its LineStyle to $xlLineStyleNone

    # clear $range2's borders, quick but not the safest way because it'll
    # also clear all borders on every cell within the range
    $range2.borders.lineStyle = $xlLineStyleNone

    # clear $range4's borders, safer, it clears specific borders one at
    # a time
    $xlEdgeLeft, $xlEdgeTop, $xlEdgeBottom, $xlEdgeRight | % {
     $range4.borders.item($_).lineStyle = $xlLineStyleNone

    }

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

    # close and release resources
    $wb.close($false)
    $xl.quit()
    spps -n excel

    --
    Kiron

    October 09

    Don't you hate it when Tab Complition does not work?

    Here is a VBScript that will solve that problem for you;
    '<--------- VBScript Starts here ---------------------------------------->
    Dim strComputer
    Dim objWMIService
    Dim SWBemlocator
    Dim UserName
    Dim Password
    Dim Title, Text1, Text2
    Dim Message, result
    Title = "Add Tab Complition"
    Text1 = "User Input Cancelled"
    Text2 = "You Entered: " & vbTab
    ' Define Msg Box Var
    Message = "PLease Enter Server Name"
    result = InputBox(Message, Title, "Type Server Name Here", 100, 100)
    ' Evaluate the user input.
    If result = "" Then
     WScript.Echo Text1
     WScript.Quit
    Else
     WScript.Echo Text2 & result & " Please wait"
    End If
    strComputer = result
    ' Add Tab Compition
    Set WshShell = WScript.CreateObject("WScript.Shell")
    SetTabComplet(strComputer)
    '
     Sub SetTabComplet(strComputer)
      ' Use to configure Tab Complition
      ' provide system name
      Dim sPath, oReg
      Const HKLM = &H80000002
      sPath = "\SOFTWARE\Microsoft\Command Processor"
    Set oReg = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" _
       & strComputer & "\root\default:StdRegProv")
     oReg.SetStringValue HKLM, sPath,"AutoRun"=""
     oReg.SetStringValue HKLM, sPath,"CompletionChar",9
     oReg.SetStringValue HKLM, sPath,"DefaultColor",0
     oReg.SetStringValue HKLM, sPath,"EnableExtensions",1
     oReg.SetStringValue HKLM, sPath,"PathCompletionChar",40
     End Sub
     
    '< End Script ---------------------------------------------------------->
    September 29

    Read a remote log, out put the log to your screen

     
    Works rather well, but it takes a moment to read in the log and parse it.
    This one asks for your domain credentials and goes back 7 days.
     
    $Credentials=Get-Credential("domain\username")
    $d = Get-Date -displayhint date
    $FQDNservername="your server"
    $A = Get-WmiObject win32_NTLogEvent –computerName $FQDNservername -credential $Credentials -filter "logfile = 'application' and eventcode = 1"
    Write-Host "Application event log acquired for Server $FQDNservername"  -backgroundcolor green -foregroundcolor black
    $BeginDate=[System.Management.ManagementDateTimeConverter]::ToDMTFDateTime($d.AddDays(-7))
    $results = $A | select TimeGenerated,Message
    $results
    September 26

    Read the log, out put the log

    This one will work on a local machine to find an event ID and displays it on your screen
    It looks in the application log for events for the last two days and ID = 9
     
    $date = Get-Date -displayhint date
    $d = ($date.AddDays(-2))
    Get-EventLog -logname application | where {$_.timegenerated -gt $d -and $_.eventid -eq "9"}

     
    September 24

    Record an Error in Excel

    If I get an error, Access denied or RPC service is unavailable, how
    would I Print the error message out to  $sh.Cells.Item($row, 2)

    And the answer is:

    $cred = Get-Credential 'YourAdminName' #ad\name or name@domain

    $row = 2

    $xl = New-Object -c excel.application

    $xl.visible = $true

    $wb = $xl.workbooks.add()

    $sh = $wb.sheets.item(1)

    $strComputer = "dogbert"

    $Var3 = gwmi -Class "Win32_OperatingSystem" -namespace "root\CIMV2" -computername $strComputer -cred $cred -ea continue

    # the above is all one line

    if ($Var3) {$sh.Cells.Item($row, 3) = $Var3.Caption }
    Else
    { $sh.Cells.Item($row, 2) = $error[0].tostring() }




     
    September 11

    Adding borders in Excel the Power Shell way

    This will open an Excel Workbook and add borders to a range of cells.
     
    <------------- Start PS Script-------------------->
     
    $xlAutomatic = -4105
    $xlBottom = -4107
    $xlCenter = -4108
    $xlContext = -5002
    $xlContinuous = 1
    $xlDiagonalDown = 5
    $xlDiagonalUp = 6
    $xlEdgeBottom = 9
    $xlEdgeLeft = 7
    $xlEdgeRight = 10
    $xlEdgeTop = 8
    $xlInsideHorizontal = 12
    $xlInsideVertical = 11
    $xlNone = -4142
    $xlThin = 2

    $xl = new-object -com excel.application
    $xl.visible=$true
    $wb = $xl.workbooks.open("C:\Scripts\Book1.xlsx")
    $ws = $wb.worksheets | where {$_.name -eq "sheet1"}
    $selection = $ws.range("A1:F29")
    $selection.select()

    $selection.HorizontalAlignment = $xlCenter
    $selection.VerticalAlignment = $xlBottom
    $selection.WrapText = $false
    $selection.Orientation = 0
    $selection.AddIndent = $false
    $selection.IndentLevel = 0
    $selection.ShrinkToFit = $false
    $selection.ReadingOrder = $xlContext
    $selection.MergeCells = $false
    $selection.Borders.Item($xlInsideHorizontal).Weight = $xlThin
    $selection.Borders.Item($xlInsideHorizontal).LineStyle = $xlContinuous
    $selection.Borders.Item($xlInsideHorizontal).ColorIndex = $xlAutomatic
     
     
    <-------------------end Script----------------------------------------------------->
    September 05

    Find All Scheduled Tasks, VBScript

    Yes I do use VBScript, a lot. I was recently asked to pull a record of all the scheduled tasks on a Windows 2000 server.

    The folks wanted to know as much as possible about their tasks so that they could recreate them when they migrated to Server 2003 or 08.
    I found that this was no easy task. Fortunatly, others had gone before me and done the hard work. It is true, We stand on the shoulders of giants.
     
    Here is my final script.
     
    '==========================================================================
    '
    ' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 2007
    '
    ' NAME: SchAgent.vbs
    '
    ' AUTHOR: Mike Felkins , IT
    ' DATE  : 9/3/2008
    '
    ' COMMENT: Collect Scheduled tasks from a Windows 2000 server and records them in an Excel file
    ' Target Environment
    '-----------------
    ' The DLL and the scripts apply to Winxp and earlier. Both Vista and Server08 have their own DLL, version 2.
    '
    'Requirements
    '----------
    ' You need to register TaskScheduler.dll
    ' regsvr32 TaskScheduler.dll
    '
    ' Available at http://www.tlviewer.org/mstask/
    '==========================================================================
    Dim objXL
    Dim strComputer
    Dim objWMIService
    Dim Title, Text1, Text2
    Dim Message, result
    ' Define Msg Box Var
    Message = "Please Enter Server Name"
    Title = "Automated Scheduled Task Inventory"
    Text1 = "User Input Cancelled"
    Text2 = "You Entered: " & vbTab
    result = InputBox(Message, Title, "Type Server Name Here", 100, 100)
    ' Evaluate the user input.
    If result = "" Then
     WScript.Echo Text1
     WScript.Quit
    Else
     WScript.Echo Text2 & result & "  ----> Please wait"
    End If
    strComputer = result
    Set objXL = WScript.CreateObject("Excel.Application")
    objXL.Visible = True
    objXL.WorkBooks.Add
    objXL.Columns(1).ColumnWidth = 20
    objXL.Columns(2).ColumnWidth = 30
    objXL.Columns(3).ColumnWidth = 40
    objXL.Columns(4).ColumnWidth = 40
    objXL.Columns(5).ColumnWidth = 40
    objXL.Columns(6).ColumnWidth = 40
    objXL.Cells(1, 1).Value = "Name"
    objXL.Cells(1, 2).Value = "ApplicationName"
    objXL.Cells(1, 3).Value = "LastRunTime"
    objXL.Cells(1, 4).Value = "NextRunTime"
    objXL.Cells(1, 5).Value = "Triggers"
    objXL.Cells(1, 6).Value = "CommandLine"
    objXL.Range("A1:F1").Select
    objXL.Selection.Font.Bold = True
    objXL.Selection.Interior.ColorIndex = 1
    objXL.Selection.Interior.Pattern = 1 'xlSolid
    objXL.Selection.Font.ColorIndex = 2
    objXL.Columns("B:B").Select
    objXL.Selection.HorizontalAlignment = &hFFFFEFDD ' xlLeft
    Dim intIndex
    intIndex = 2

    Call SchAgent

    objXL.ActiveWorkbook.SaveAs("C:\scripts\" & result & "_ScheduledJobs.xls")
    If MsgBox("Finished processing. Results saved to: " & "C:\scripts\" &result & "_ScheduledJobs.xls" &_
                vbTab & vbcrlf & VbCrLf & "Do you want to view the results now?", _
                4 + 32, sTitle) = 6 Then
    Else
     objXL.ActiveWorkbook.Close
      ' Quit Excel.
     objXL.Application.Quit
     
    ' Clean Up
     Set objXL = Nothing
    End If 

    Sub SchAgent
    Set objS = CreateObject("Scheduler.SchAgent")
    objS.TargetComputer = "\\" & strComputer
    WScript.Echo "Looking at: " & result & "  ----> Please wait"
    objS.Refresh
     For Each job In objS
      objXL.Cells(intIndex, 1).Value = job.Name
      objXL.Cells(intIndex, 2).Value = job.ApplicationName
      objXL.Cells(intIndex, 3).Value = job.LastRunTime
      objXL.Cells(intIndex, 4).Value = job.NextRunTime
      
       For Each oTrig In job.Triggers
             objXL.Cells(intIndex, 5).Value = "Trigger #" & i _
             & " (Typ " & oTrig.TriggerType _
             & ") " & oTrig.Text
             i = i + 1
          Next
          
      objXL.Cells(intIndex, 6).Value = job.CommandLine
      intIndex = intIndex + 1
     Next
      
      objXL.Cells.EntireColumn.AutoFit
    End Sub
     
     
     
     
     
    September 02

    Exiting Excel

    Alex, over at the Power Shell group in Google talked about Excel not shutting down when told.

    Excel is generally the worst offender this way - there have been problems
    with it not shutting down when told to that go back a very long time - but
    there definitely are other ActiveX applications that exhibit this kind of
    behavior. Since ActiveX applications are generally rare and each have their
    own quirks, I usually test whether they shut down in different situations
    when using them from PowerShell by keeping an eye on the process list, then
    release the object if they don't shut down correctly.
    Unfortunately, this isn't all that useful if you're keeping an application
    around to use during a PowerShell session. In those cases, I've noticed that
    even some of the better-behaved ActiveX applications don't work the way we
    might want. For example, some of the better-behaved ActiveX applications
    will indeed shut down automatically if they don't have an open, modified
    document when you close PowerShell by typing exit, but will hang around if
    you close PS with the "X" at the top of the shell window. My general rule of
    thumb is to always unhide ActiveX applications and minimize them. This at
    least ensures that I can see and close them if I exit PS the wrong way or
    lose connection to the app somehow.

    One way in Power Shell to kill the process is;

    Stop-Process -name EXCEL

    Another is to try to release the com object after quiting:

    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) 

    Or this;

    $xl.quit()
    spps -n excel

    I am sure that there are others.



    September 01

    Fixed the chart example

     There seems to a problem with the chart example. Doug, over at the power shell group sent this fix.

    $xrow = 1
    $yrow = 8
    $xl = New-Object -c excel.application
    $xl.visible = $true
    $wb = $xl.workbooks.add()
    $sh = $wb.sheets.item(1)
    1..8 | % { $sh.Cells.Item(1,$_) = $_ }
    1..8 | % { $sh.Cells.Item(2,$_) = 9-$_ }
    $range = $sh.range("a${xrow}:h$yrow")
    $range.activate
    # create and assign the chart to a variable
    $ch = $xl.charts.add()
    $ch.chartType = 58
    $ch.setSourceData($range)
    $ch.export("C:\test.jpg")
    $xl.quit()


    http://groups.google.com/group/microsoft.public.windows.powershell/browse_thread/thread/a43536968f0fdb5f

    August 30

    Non US locale

    One thing I would add is that if you are using  a non US locale some of
    these scripts won't work especially adding and saving workbooks

    http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!1204...

    August 29

    Excel Cookbook for PowerShell

    All errors and mistakes are my own. Thanks to all who have helped
    along the way.

    ________________________________________________________________________

    How do I create an Excel object?

    $xl = new-object -comobject excel.application

    The Scripting Guys have a column about tab expansion with an Excel
    example.
    ________________________________________________________________________

    How do I make Excel visible?
    $xl.Visible = $true

    ________________________________________________________________________

    How do I add a workbook?

    $wb = $xl.Workbooks.Add()

    ________________________________________________________________________

    How do I add a worksheet?

    $xl = new-object -comobject excel.application

    $xl.Visible = $true
    $wb = $xl.Workbooks.Open("C:\Scripts\ado_object_model.xls")
    $ws = $xl.Sheets.Add()

    ________________________________________________________________________

    How do I change the value of the active cell?

    $xl.ActiveCell.Value2 = "x"

    ________________________________________________________________________

    How do I change the value of a specified cell?

    $xl.ActiveSheet.Range("B1").Value2 = "y"

    ________________________________________________________________________

    How do I list the workbook's name?

    $wb.Name

    ________________________________________________________________________

    How do I loop through a range of cells by row number?

    $xl = new-object -comobject excel.application
    $xl.Visible = $true
    $wb = $xl.Workbooks.Add()
    $ws = $wb.Worksheets.Item(1)

    for ($row = 1; $row -lt 11; $row++)
    {
        $ws.Cells.Item($row,1) = $row

    }

    ________________________________________________________________________

    How do I write a list of files to Excel?

    $xl = new-object -comobject excel.application
    $xl.Visible = $true
    $wb = $xl.Workbooks.Add()
    $ws = $wb.Worksheets.Item(1)

    $row = 1
    $s = dir
    $s | foreach -process `
    { `
        $ws.Cells.Item($row,1) = $_; `
        $row++ `

    }

    ________________________________________________________________________

    How do I write a list of processes to Excel?

    function Release-Ref ($ref) {

    #[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
    [System.Runtime.InteropServices.Marshal]::ReleaseComObject($ref)
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    }


    # -----------------------------------------------------

    $xl = New-Object -comobject Excel.Application


    $xl.Visible = $True


    $wb = $xl.Workbooks.Add()
    $ws = $wb.Worksheets.Item(1)
    $range = $ws.Cells.Item(1,1)


    $row = 1
    $s = Get-Process | Select-Object name
     $s | foreach -process {
        $range = $ws.Cells.Item($row,1);
        $range.value2 = $_.Name;
        $row++ }


    $xl.DisplayAlerts = $False
    $wb.SaveAs("C:\Scripts\Get_Process.xls")

    Release-Ref $range

    Release-Ref $ws

    Release-Ref $wb

    $xl.Quit()

    Release-Ref $xl

    ***For a remote machine try

    $strComputer = (remote machine name)
    $P = gwmi win32_process -comp $strComputer

    ______________________________________________________________

    How do I open a workbook?

    #an existing Workbook
    $xl.Workbooks.Open("C:\Scripts\ado_object_model.xls")

    ________________________________________________________________________

    How do I open a new workbook?

    $xl = new-object -comobject excel.application
    $xl.Visible = $true
    $wb = $xl.Workbooks.Add()
    $xl.ActiveCell.Value2 = "x"
    $xl.ActiveSheet.Range("B1").Value2 = "y"

    ________________________________________________________________________

    How do I write the command history to Excel?

    function Release-Ref ($ref) {

    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComOb­ject]
    $ref) -gt 0)
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    }

    # -----------------------------------------------------

    $xl = New-Object -comobject Excel.Application

    $xl.Visible = $True

    $wb = $excel.Workbooks.Add()
    $ws = $workbook.Worksheets.Item(1)
    $range = $worksheet.Cells.Item(1,1)

    $row = 1
    $s = Get-History | Select-Object CommandLine $s | foreach -process { `
    $range = $worksheet.Cells.Item($row,1); `
    $range.value2 = $_.CommandLine; `
    $row++ }

    $xl.DisplayAlerts = $False
    $wb.SaveAs("C:\Scripts\Get_CommandLine.xls")

    Release-Ref $range

    Release-Ref $ws

    Release-Ref $wb

    $xl.Quit()

    Release-Ref $xl

    ________________________________________________________________________

    How Can I Convert a Tilde-Delimited File to Microsoft Excel Format?

    # Script name: ConvertTilde.ps1
    # Created on: 2007-01-06
    # Author: Kent Finkle
    # Purpose: How Can I Convert a Tilde-Delimited File to Microsoft Excel
    Format?

    $s = gc C:\Scripts\Test.txt
    $s = $s -replace("~","`t")
    $s | sc C:\Scripts\Test.txt
    $xl = new-object -comobject excel.application
    $xl.Visible = $true
    $wb = $xl.Workbooks.Open("C:\Scripts\Test.txt")

    ________________________________________________________________________

    Add Validation to an Excel Worksheet

    $comments = @'
    Script name: Add-Validation.ps1
    Created on: Wednesday, September 19, 2007
    Author: Kent Finkle
    Purpose: How can I use Windows Powershell to Add Validation to an
    Excel Worksheet?
    '@

    #-----------------------------------------------------
    function Release-Ref ($ref) {
    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject(
    [System.__ComObject]$ref) -gt 0)
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    }

    #-----------------------------------------------------

    $xlValidateWholeNumber = 1
    $xlValidAlertStop = 1
    $xlBetween = 1

    $xl = new-object -comobject excel.application
    $xl.Visible = $True

    $wb = $xl.Workbooks.Add()
    $ws = $wb.Worksheets.Item(1)
    $r = $ws.Range("e5")
    $r.Validation.Add($xlValidateWholeNumber, ` $xlValidAlertStop,
    $xlBetween, "5", "10") $r.Validation.InputTitle = "Integers"
    $r.Validation.ErrorTitle = "Integers"
    $r.Validation.InputMessage = "Enter an integer from five to ten"
    $r.Validation.ErrorMessage = "You must enter a number from five to
    ten"

    $a = Release-Ref $r
    $a = Release-Ref $ws
    $a = Release-Ref $wb
    $a = Release-Ref $xl

    ________________________________________________________________________

    Add a Chart to an Excel Worksheet

    $xrow = 1
    $yrow = 8
    $xl = New-Object -c excel.application
    $xl.visible = $true
    $wb = $xl.workbooks.add()
    $sh = $wb.sheets.item(1)
    1..8 | % { $sh.Cells.Item(1,$_) = $_ }
    1..8 | % { $sh.Cells.Item(2,$_) = 9-$_ }
    $range = $sh.range("a${xrow}:h$yrow")
    $range.activate
    # create and assign the chart to a variable
    $ch = $xl.charts.add()
    $ch.chartType = 58
    $ch.setSourceData($range)
    $ch.export("C:\test.jpg")
    $xl.quit()

    # excel has 48 chart styles, you can cycle through all
    1..48 | % {$ch.chartStyle = $_; $xl.speech.speak("Style $_"); sleep 1}
    $ch.chartStyle = 27                          # <-- use the one you like

    ________________________________________________________________________

    Sort a column in an Excel Worksheet

    $xlSummaryAbove = 0
    $xlSortValues = $xlPinYin = 1
    $xlAscending = 1
    $xlDescending = 2

    # one-column sort --> works
    [void]$range1.sort($range2, $xlAscending)
    [void]$range1.sort($range3, $xlAscending)
    # two-column sort --> doesn't sort both columns
    # the 4th arg [xlSortType] gives problems so pass $null or '',
    # it may be for PivotTables only
    [void]$range1.sort($range2, $xlAscending, $range3, '', $xlAscending)

    ________________________________________________________________________

    SubTotal a column in an Excel Worksheet

     Sample Spreadsheet
             mon    tue    wed 
    eggs     1     1         1 
    ham      5     5         5 
    spam    1     4         7 
    spam    2     5         8
    spam    3     6         9 
    Code to sub total
    $xlSum = -4157
    $range = $xl.range("A1:D6")
    $range.Subtotal(1,-4157,(2,3,4),$true,$false,$true)

    #     Selection.Subtotal GroupBy:=1, Function:=xlSum, TotalList:=Array(4), _
    #     Replace:=True, PageBreaks:=False, SummaryBelowData:=True
    ________________________________________________________________________

    How to use xlConstants

    $xlAutomatic=-4105
    $xlBottom = -4107
    $xlCenter = -4108
    $xlContext = -5002
    $xlContinuous=1
    $xlDiagonalDown=5
    $xlDiagonalUp=6
    $xlEdgeBottom=9
    $xlEdgeLeft=7
    $xlEdgeRight=10
    $xlEdgeTop=8
    $xlInsideHorizontal=12
    $xlInsideVertical=11
    $xlNone=-4142
    $xlThin=2

    $xl = new-object -com excel.application
    $xl.visible=$true
    $wb = $xl.workbooks.open("d:\book1.xls")
    $ws = $wb.worksheets | where {$_.name -eq "sheet1"}
    $selection = $ws.range("A1:D1")
    $selection.select()

    $selection.HorizontalAlignment = $xlCenter
    $selection.VerticalAlignment = $xlBottom
    $selection.WrapText = $false
    $selection.Orientation = 0
    $selection.AddIndent = $false
    $selection.IndentLevel = 0
    $selection.ShrinkToFit = $false
    $selection.ReadingOrder = $xlContext
    $selection.MergeCells = $false
    $selection.Borders.Item($xlInsideHorizontal).Weight = $xlThin
    ________________________________________________________________________

    About autofill in excel

    $xlFillWeekdays = 6

    $xl = new-object -com excel.application
    $xl.visible=$true
    $wb = $xl.workbooks.add()
    $ws = $wb.worksheets | where {$_.name -eq "sheet1"}
    $range1= $sheet.range("A1")
    $range1.value() = (get-date).toString("d")
    $range2 = $sheet.range("A1:A25")
    $range1.AutoFill($range2,$xlFillWeekdays)
    $range1.entireColumn.Autofit()
    # $wb.close()
    # $xl.quit()

    ________________________________________________________________________

    How to get a range in excel

    # get-excelrange.ps1
    # opens an existing workbook in Excel 2007, using PowerShell
    # and turns a range bold # Thomas Lee - t...@psp.co.uk

    # Create base object
    $xl = new-object -comobject Excel.Application

    # make Excel visible
    $xl.visible = $true

    # open a workbook
    $wb = $excel.workbooks.open("C:\Scripts\xlsx1.xlsx")

    # Get sheet1
    $ws = $wb.worksheets | where {$_.name -eq "sheet1"}

    # Make A1-B1 bold
    $range = $ws.range("A1:B1")
    $range.font.bold = "true"

    # Make A2-B2 italic
    $range2 = $sheet1.range("A2:B2")
    $range2.font.italic = "true"

    # Set range to a value
    $range3=$ws.range("table1")
    $Range3.font.size=24

    # now format an entire row
    $range4=$ws.range("3:3")
    $range4.cells="Row 3"
    $range4.font.italic="$true"
    $range4.font.bold=$True
    $range4.font.size=10
    $range4.font.name="comic Sans MS"

    # now format a Range of cells

    $ws.Range("D1:F5").NumberFormat = "#,##0.00"
    ______________________________________________________________________

    How do I add a comment to a cell in Excel

    $xll = New-Object -com Excel.Application
    $xl.visible = $True
    $wb = $xl.Workbooks.Add()
    $ws = $wb.Worksheets.Item(1)
    $ws.Cells.Item(1,1) = “A value in cell A1.”
    [void]$ws.Range("A1").AddComment()
    [void]$ws.Range("A1").comment.Visible = $False
    [void]$ws.Range("A1").Comment.text("OldDog: `r this is a comment")
    [void]$ws.Range("A2").Select

    The 'r adds a line feed after the comment's author. This is required!

    ________________________________________________________________________

    How do I copy and Paste Special in Excel

            $xlPasteValues = -4163          # Values only, not formulas
            $xlCellTypeLastCell = 11        # to find last used cell

            $used = $ws.usedRange
            $lastCell = $used.SpecialCells($xlCellTypeLastCell)
            $row = $lastCell.row

            $range = $ws.UsedRange
            [void]$ws.Range("A8:F$row").Copy()
            [void]$ws.Range("A8").PasteSpecial(-4163)